b80db49c5e
Kopfzeile 48 px dunkel mit Seitentitel statt immer Startseite, Dashboard-Reiter mit Akzent-Unterstrich; Seitenleiste mit Auswahlpille, Modul-Kacheln, aufgeklappten Kategorien und gefuelltem Suchfeld; eingeklappt nur Kacheln. Einheitlicher PageHeader. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
77 lines
2.9 KiB
TypeScript
77 lines
2.9 KiB
TypeScript
'use client';
|
|
|
|
import { useTranslations } from 'next-intl';
|
|
import { useState } from 'react';
|
|
import { captureScreenshot } from '@/lib/bug-report-api';
|
|
import { useAuthStore } from '@/lib/stores/auth-store';
|
|
import { BugReportDialog } from './bug-report-dialog';
|
|
|
|
/**
|
|
* Fehler-melden-Knopf in der Kopfzeile (quick-260914-m97), Stil wie
|
|
* `ThemeToggle`. Kernanforderung: das Bild der Seite wird aufgenommen,
|
|
* BEVOR der Dialog erscheint — sonst waere der Dialog im Bild.
|
|
*/
|
|
export function BugReportButton() {
|
|
const t = useTranslations('bugReport');
|
|
const user = useAuthStore((s) => s.user);
|
|
const isAdmin = user?.role === 'ADMIN' || user?.role === 'SUPER_ADMIN';
|
|
const [capturing, setCapturing] = useState(false);
|
|
const [open, setOpen] = useState(false);
|
|
const [screenshot, setScreenshot] = useState<string | null>(null);
|
|
|
|
const handleClick = async () => {
|
|
if (capturing) return;
|
|
setCapturing(true);
|
|
// Reihenfolge ist die Kernanforderung: erst aufnehmen, dann oeffnen.
|
|
const shot = await captureScreenshot();
|
|
setScreenshot(shot);
|
|
setOpen(true);
|
|
setCapturing(false);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
type="button"
|
|
onClick={handleClick}
|
|
className="inline-flex h-8 w-8 items-center justify-center rounded-md text-appbar-muted hover:bg-appbar-hover hover:text-appbar-foreground transition-colors disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-[-2px] focus-visible:outline-appbar-foreground"
|
|
aria-label={t('button')}
|
|
title={t('button')}
|
|
disabled={capturing}
|
|
data-bug-report-ignore="true"
|
|
>
|
|
{/* Kaefer-Symbol nach dem lucide-Symbol "bug" */}
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
width="20"
|
|
height="20"
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth="2"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
aria-hidden="true"
|
|
>
|
|
<path d="m8 2 1.88 1.88" />
|
|
<path d="M14.12 3.88 16 2" />
|
|
<path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1" />
|
|
<path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6" />
|
|
<path d="M12 20v-9" />
|
|
<path d="M6.53 9C4.6 8.8 3 7.1 3 5" />
|
|
<path d="M6 13H2" />
|
|
<path d="M3 21c0-2.1 1.7-3.9 3.8-4" />
|
|
<path d="M20.97 5c0 2.1-1.6 3.8-3.5 4" />
|
|
<path d="M22 13h-4" />
|
|
<path d="M17.2 17c2.1.1 3.8 1.9 3.8 4" />
|
|
</svg>
|
|
</button>
|
|
{/* Nur eingehaengt, solange offen (quick-260921-ldf): so startet jedes
|
|
Oeffnen mit frischem Zustand — Haekchen, Text und Status stimmen
|
|
schon im ersten Commit, statt einen Commit spaeter nachgezogen zu
|
|
werden. */}
|
|
{open && <BugReportDialog screenshot={screenshot} isAdmin={isAdmin} onClose={() => setOpen(false)} />}
|
|
</>
|
|
);
|
|
}
|