import type { Metadata } from "next"; import Link from "next/link"; import { notFound } from "next/navigation"; import { Icon } from "@/components/icons"; import { Card } from "@/components/ui"; import { requirePageActor } from "@/lib/auth/guard"; import { can } from "@/lib/auth/policy"; import { prisma } from "@/lib/db"; import { FEEDBACK_SCALES, feedbackDataSchema } from "@/lib/qr/types/feedback"; export const dynamic = "force-dynamic"; export const metadata: Metadata = { title: "Rückmeldungen" }; type PageProps = { params: Promise<{ id: string }> }; function formatDate(value: Date): string { return new Intl.DateTimeFormat("de-DE", { dateStyle: "medium", timeStyle: "short", }).format(value); } export default async function FeedbackResultsPage({ params }: PageProps) { const { id } = await params; const actor = await requirePageActor(); const code = await prisma.qrCode.findUnique({ where: { id }, include: { feedback: { orderBy: { createdAt: "desc" }, take: 200 }, }, }); if (!code || code.type !== "feedback") notFound(); if (!can(actor, "codes:read", { groupId: code.groupId })) notFound(); const daten = feedbackDataSchema.safeParse(code.data); const skala = daten.success ? daten.data.scale : "stars"; const titel = daten.success ? daten.data.title : (code.label ?? "Feedback"); const eintraege = code.feedback; const anzahl = eintraege.length; const schnitt = anzahl > 0 ? eintraege.reduce((summe, eintrag) => summe + eintrag.rating, 0) / anzahl : 0; // Verteilung von 5 nach 1 — so liest man eine Bewertungsübersicht. const verteilung = [5, 4, 3, 2, 1].map((note) => ({ note, anzahl: eintraege.filter((eintrag) => eintrag.rating === note).length, })); const groesste = Math.max(1, ...verteilung.map((zeile) => zeile.anzahl)); const kommentare = eintraege.filter((eintrag) => eintrag.comment); return (
Zurück zu Meine Codes

{titel}

{anzahl === 0 ? "Es ist noch keine Rückmeldung eingegangen." : `${anzahl} ${anzahl === 1 ? "Rückmeldung" : "Rückmeldungen"} · ${code.scans} ${code.scans === 1 ? "Scan" : "Scans"}`}

{anzahl > 0 ? ( <>

{schnitt.toFixed(1).replace(".", ",")}

von 5 im Schnitt

{verteilung.map((zeile) => (
{zeile.note}{" "} {zeile.anzahl}
))}
{kommentare.length > 0 ? (

Kommentare ({kommentare.length})

    {kommentare.map((eintrag) => (
  • {eintrag.rating}/5

    {eintrag.comment}

  • ))}
{anzahl >= 200 ? (

Angezeigt werden die 200 jüngsten Rückmeldungen.

) : null}
) : (

Bisher hat niemand etwas dazugeschrieben.

)} ) : (

Sobald jemand den Code scannt und eine Bewertung abgibt, steht sie hier. Die Rückmeldungen enthalten keinen Namen und keine IP-Adresse.

)}
); }