nsfwapp/frontend/src/components/ui/CookieModal.tsx
2026-01-13 14:00:05 +01:00

131 lines
4.4 KiB
TypeScript

'use client'
import { Dialog } from '@headlessui/react'
import { useEffect, useState, useRef } from 'react'
import Button from './Button'
export type CookieEntry = { name: string; value: string }
type CookieModalProps = {
open: boolean
onClose: () => void
onApply: (cookies: CookieEntry[]) => void
initialCookies: CookieEntry[]
}
export default function CookieModal({
open,
onClose,
onApply,
initialCookies,
}: CookieModalProps) {
const [name, setName] = useState('')
const [value, setValue] = useState('')
const [cookies, setCookies] = useState<CookieEntry[]>([])
const wasOpen = useRef(false)
// ✅ Beim Öffnen: Inputs resetten UND Cookies aus Props übernehmen
useEffect(() => {
if (open && !wasOpen.current) {
setName('')
setValue('')
setCookies(initialCookies ?? [])
}
wasOpen.current = open
}, [open, initialCookies])
function addCookie() {
const n = name.trim()
const v = value.trim()
if (!n || !v) return
setCookies((prev) => {
const filtered = prev.filter((c) => c.name !== n)
return [...filtered, { name: n, value: v }]
})
setName('')
setValue('')
}
function removeCookie(n: string) {
setCookies((prev) => prev.filter((c) => c.name !== n))
}
function applyAndClose() {
onApply(cookies)
onClose()
}
return (
<Dialog open={open} onClose={onClose} className="relative z-50">
<div className="fixed inset-0 bg-black/40" aria-hidden="true" />
<div className="fixed inset-0 flex items-center justify-center p-4">
<Dialog.Panel className="w-full max-w-lg rounded-lg bg-white dark:bg-gray-800 p-6 shadow-xl dark:outline dark:-outline-offset-1 dark:outline-white/10">
<Dialog.Title className="text-base font-semibold text-gray-900 dark:text-white">
Zusätzliche Cookies
</Dialog.Title>
<div className="mt-4 grid grid-cols-1 sm:grid-cols-3 gap-2">
<input
value={name}
onChange={(e) => setName(e.target.value)}
placeholder="Name (z. B. cf_clearance)"
className="col-span-1 truncate rounded-md px-3 py-2 text-sm bg-white text-gray-900 dark:bg-white/10 dark:text-white"
/>
<input
value={value}
onChange={(e) => setValue(e.target.value)}
placeholder="Wert"
className="col-span-1 truncate sm:col-span-2 rounded-md px-3 py-2 text-sm bg-white text-gray-900 dark:bg-white/10 dark:text-white"
/>
</div>
<div className="mt-2">
<Button size="sm" variant="secondary" onClick={addCookie} disabled={!name.trim() || !value.trim()}>
Hinzufügen
</Button>
</div>
<div className="mt-4">
{cookies.length === 0 ? (
<div className="text-sm text-gray-500 dark:text-gray-400">Noch keine Cookies hinzugefügt.</div>
) : (
<table className="min-w-full text-sm border divide-y dark:divide-white/10">
<thead className="bg-gray-50 dark:bg-gray-700/50">
<tr>
<th className="px-3 py-2 text-left font-medium">Name</th>
<th className="px-3 py-2 text-left font-medium">Wert</th>
<th className="px-3 py-2" />
</tr>
</thead>
<tbody className="divide-y dark:divide-white/10">
{cookies.map((c) => (
<tr key={c.name}>
<td className="px-3 py-2 font-mono">{c.name}</td>
<td className="px-3 py-2 truncate max-w-[240px]">{c.value}</td>
<td className="px-3 py-2 text-right">
<button
onClick={() => removeCookie(c.name)}
className="text-xs text-red-600 hover:underline dark:text-red-400"
>
Entfernen
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
</div>
<div className="mt-6 flex justify-end gap-2">
<Button variant="secondary" onClick={onClose}>Abbrechen</Button>
<Button variant="primary" onClick={applyAndClose}>Übernehmen</Button>
</div>
</Dialog.Panel>
</div>
</Dialog>
)
}