'use client'; import { useEffect, useState } from 'react'; import { useTranslations } from 'next-intl'; import { XFRAME_SANDBOX } from '@/components/dashboard/widgets/xframe-config'; import { type CustomModule, checkCustomModuleUrl, getCustomModule } from '@/lib/custom-modules-api'; type LoadState = { status: 'loading' } | { status: 'missing' } | { status: 'ready'; mod: CustomModule }; /** * Rahmen-Ansicht eines eigenen Moduls (quick-260929-9wc, D-06): schmale * Leiste mit Name, Hinweis und dem immer sichtbaren Knopf „In neuem Tab * oeffnen“, darunter der flaechenfuellende Rahmen. Sandbox-Wert und * Attribute wie im XFrame-Widget (`XFRAME_SANDBOX`, kein `allow`, kein * Referrer). Iframe und Link entstehen NUR bei einer https-Adresse ohne * Zugangsdaten — auch eine von Hand veraenderte Datenbankzeile mit * `javascript:` oder `http:` wird nie gerendert (T-9WC-03). */ export function CustomModuleView({ id }: { id: string }) { const t = useTranslations('customModules'); const [state, setState] = useState({ status: 'loading' }); useEffect(() => { let cancelled = false; setState({ status: 'loading' }); getCustomModule(id) .then((mod) => { if (cancelled) return; setState(mod ? { status: 'ready', mod } : { status: 'missing' }); }) .catch(() => { if (!cancelled) setState({ status: 'missing' }); }); return () => { cancelled = true; }; }, [id]); if (state.status === 'loading') { return
{t('loading')}
; } if (state.status === 'missing') { return
{t('notFound')}
; } const { mod } = state; const urlOk = checkCustomModuleUrl(mod.url) === 'ok'; return (

{mod.name}

{urlOk &&

{t('embedHint')}

}
{urlOk && ( {t('openInNewTab')} )}
{urlOk ? (