refactor(admin): split audit-checklist, cookie-banner, escalations pages
Each page.tsx was 750-780 LOC. Extracted React components to _components/ and custom hooks to _hooks/ next to each page.tsx. All three pages are now under 215 LOC (well within the 500 LOC hard cap). Zero behavior changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
'use client'
|
||||
|
||||
import { useState, useMemo } from 'react'
|
||||
import { Copy, Check } from 'lucide-react'
|
||||
import { CookieBannerConfig } from '@/lib/sdk/einwilligungen/types'
|
||||
import { generateEmbedCode } from '@/lib/sdk/einwilligungen/generator/cookie-banner'
|
||||
|
||||
interface EmbedCodeViewerProps {
|
||||
config: CookieBannerConfig | null
|
||||
}
|
||||
|
||||
export function EmbedCodeViewer({ config }: EmbedCodeViewerProps) {
|
||||
const [activeTab, setActiveTab] = useState<'script' | 'html' | 'css' | 'js'>('script')
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
const embedCode = useMemo(() => {
|
||||
if (!config) return null
|
||||
return generateEmbedCode(config, '/datenschutz')
|
||||
}, [config])
|
||||
|
||||
const copyToClipboard = async (text: string) => {
|
||||
await navigator.clipboard.writeText(text)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 2000)
|
||||
}
|
||||
|
||||
if (!embedCode) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-48 bg-slate-100 rounded-xl">
|
||||
<p className="text-slate-400">Embed-Code wird generiert...</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const tabs = [
|
||||
{ id: 'script', label: 'Script-Tag', content: embedCode.scriptTag },
|
||||
{ id: 'html', label: 'HTML', content: embedCode.html },
|
||||
{ id: 'css', label: 'CSS', content: embedCode.css },
|
||||
{ id: 'js', label: 'JavaScript', content: embedCode.js },
|
||||
] as const
|
||||
|
||||
const currentContent = tabs.find((t) => t.id === activeTab)?.content || ''
|
||||
|
||||
return (
|
||||
<div className="border border-slate-200 rounded-xl overflow-hidden">
|
||||
<div className="flex border-b border-slate-200 bg-slate-50">
|
||||
{tabs.map((tab) => (
|
||||
<button
|
||||
key={tab.id}
|
||||
onClick={() => setActiveTab(tab.id)}
|
||||
className={`px-4 py-2 text-sm font-medium transition-colors ${
|
||||
activeTab === tab.id
|
||||
? 'bg-white text-indigo-600 border-b-2 border-indigo-600 -mb-px'
|
||||
: 'text-slate-600 hover:text-slate-900'
|
||||
}`}
|
||||
>
|
||||
{tab.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<pre className="p-4 bg-slate-900 text-slate-100 text-sm font-mono overflow-x-auto max-h-[400px]">
|
||||
{currentContent}
|
||||
</pre>
|
||||
<button
|
||||
onClick={() => copyToClipboard(currentContent)}
|
||||
className="absolute top-3 right-3 flex items-center gap-1.5 px-3 py-1.5 bg-slate-800 hover:bg-slate-700 text-slate-200 rounded-lg text-xs"
|
||||
>
|
||||
{copied ? (
|
||||
<>
|
||||
<Check className="w-3.5 h-3.5 text-green-400" />
|
||||
Kopiert
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Copy className="w-3.5 h-3.5" />
|
||||
Kopieren
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{activeTab === 'script' && (
|
||||
<div className="p-4 bg-amber-50 border-t border-amber-200">
|
||||
<p className="text-sm text-amber-800">
|
||||
<strong>Integration:</strong> Fuegen Sie den Script-Tag in den{' '}
|
||||
<code className="bg-amber-100 px-1 rounded"><head></code> oder vor dem
|
||||
schliessenden{' '}
|
||||
<code className="bg-amber-100 px-1 rounded"></body></code>-Tag ein.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user