Files
fotospiel-app/resources/js/guest/components/Header.tsx

106 lines
3.8 KiB
TypeScript

import React from 'react';
import { Button } from '@/components/ui/button';
import { Link } from 'react-router-dom';
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet';
import AppearanceToggleDropdown from '@/components/appearance-dropdown';
import { Settings, ChevronDown } from 'lucide-react';
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
export default function Header({ title = '' }: { title?: string }) {
return (
<div className="sticky top-0 z-20 flex items-center justify-between border-b bg-white/70 px-4 py-2 backdrop-blur dark:bg-black/40">
<div className="font-semibold">{title}</div>
<div className="flex items-center gap-2">
<AppearanceToggleDropdown />
<SettingsSheet />
</div>
</div>
);
}
function SettingsSheet() {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="h-9 w-9 rounded-md">
<Settings className="h-5 w-5" />
<span className="sr-only">Einstellungen öffnen</span>
</Button>
</SheetTrigger>
<SheetContent side="right" className="w-80 sm:w-96">
<SheetHeader>
<SheetTitle>Einstellungen</SheetTitle>
</SheetHeader>
<div className="mt-4 space-y-4">
<Collapsible defaultOpen>
<div className="flex items-center justify-between">
<div className="text-sm font-medium">Cache</div>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="sm" className="h-7 px-2">
<ChevronDown className="h-4 w-4" />
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent>
<div className="mt-2">
<ClearCacheButton />
</div>
</CollapsibleContent>
</Collapsible>
<Collapsible defaultOpen>
<div className="flex items-center justify-between">
<div className="text-sm font-medium">Rechtliches</div>
<CollapsibleTrigger asChild>
<Button variant="ghost" size="sm" className="h-7 px-2">
<ChevronDown className="h-4 w-4" />
</Button>
</CollapsibleTrigger>
</div>
<CollapsibleContent>
<ul className="mt-2 list-disc pl-5 text-sm">
<li><Link to="/legal/impressum" className="underline">Impressum</Link></li>
<li><Link to="/legal/datenschutz" className="underline">Datenschutz</Link></li>
<li><Link to="/legal/agb" className="underline">AGB</Link></li>
</ul>
</CollapsibleContent>
</Collapsible>
</div>
</SheetContent>
</Sheet>
);
}
function ClearCacheButton() {
const [busy, setBusy] = React.useState(false);
const [done, setDone] = React.useState(false);
async function clearAll() {
setBusy(true); setDone(false);
try {
// Clear CacheStorage
if ('caches' in window) {
const keys = await caches.keys();
await Promise.all(keys.map((k) => caches.delete(k)));
}
// Clear known IndexedDB dbs (best-effort)
if ('indexedDB' in window) {
try { await new Promise((res, rej) => { const r = indexedDB.deleteDatabase('upload-queue'); r.onsuccess=()=>res(null); r.onerror=()=>res(null); }); } catch {}
}
setDone(true);
} finally {
setBusy(false);
setTimeout(() => setDone(false), 2500);
}
}
return (
<div className="mt-2">
<Button variant="secondary" onClick={clearAll} disabled={busy}>
{busy ? 'Leere Cache…' : 'Cache leeren'}
</Button>
{done && <div className="mt-2 text-xs text-muted-foreground">Cache gelöscht.</div>}
</div>
);
}