From ce8d478ecda7a8a621d2843dbe344e200fc1e31c Mon Sep 17 00:00:00 2001 From: neodk2004 Date: Mon, 5 Oct 2026 08:56:10 +0200 Subject: [PATCH] feat(admin): Verwaltungs-Seiten im neuen Design (Etappe 3, Paket 3) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Team & Rollen: Personen mit Name/E-Mail statt Clerk-ID, Rollen- Erklärung, „Person hinzufügen“ per Suche nach Name/E-Mail statt eingefügter user_-ID, deutsche Dialoge; listModerators liefert Namen - Mitteilungen, Rechtstexte, Begrüßung, Empfehlungen: einheitlicher Seitenkopf, „Halter“ statt „Owner“ Co-Authored-By: Claude Opus 5.5 --- src/__tests__/admin.test.ts | 21 ++ src/app/p/[secret]/broadcasts/page.tsx | 21 +- src/app/p/[secret]/curator/page.tsx | 13 +- src/app/p/[secret]/legal/page.tsx | 19 +- src/app/p/[secret]/moderators/page.tsx | 284 +++++++++++------- src/app/p/[secret]/referrals/page.tsx | 11 +- .../admin/referrals/OverviewTab.tsx | 2 +- src/trpc/routers/admin.ts | 26 +- 8 files changed, 246 insertions(+), 151 deletions(-) diff --git a/src/__tests__/admin.test.ts b/src/__tests__/admin.test.ts index 7e2a1f6..9df0071 100644 --- a/src/__tests__/admin.test.ts +++ b/src/__tests__/admin.test.ts @@ -881,3 +881,24 @@ describe("admin.listReports", () => { expect(mockPrisma.post.findMany).not.toHaveBeenCalled(); }); }); + +describe("admin.listModerators", () => { + it("adds names and e-mail from Clerk so the team page shows people instead of IDs", async () => { + vi.stubEnv("ADMIN_OWNER_ID", "admin-1"); + const { caller, mockPrisma } = await createAdminCaller(); + mockPrisma.adminRole.findMany.mockResolvedValue([ + { id: "r1", ownerId: "user_lea", role: "MODERATOR", grantedBy: "admin-1", grantedAt: new Date(), owner: { pets: [] } }, + ]); + mockGetUserList.mockResolvedValue({ + data: [ + { id: "user_lea", firstName: "Lea", lastName: "M", primaryEmailAddressId: "e1", emailAddresses: [{ id: "e1", emailAddress: "lea@example.com" }] }, + { id: "admin-1", firstName: "Daniel", lastName: null, primaryEmailAddressId: null, emailAddresses: [] }, + ], + }); + + const [mod] = await caller.admin.listModerators(); + + expect(mod!.person).toEqual({ name: "Lea M", email: "lea@example.com" }); + expect(mod!.grantedByName).toBe("Daniel"); + }); +}); diff --git a/src/app/p/[secret]/broadcasts/page.tsx b/src/app/p/[secret]/broadcasts/page.tsx index f82691c..a904791 100644 --- a/src/app/p/[secret]/broadcasts/page.tsx +++ b/src/app/p/[secret]/broadcasts/page.tsx @@ -9,6 +9,7 @@ import { Input } from "@/components/ui/input"; import { Textarea } from "@/components/ui/textarea"; import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog"; import { toast } from "sonner"; +import { AdminPageHeader } from "@/components/admin/AdminSection"; function formatDate(d: string | Date) { return new Date(d).toLocaleString("de-DE", { @@ -34,7 +35,7 @@ export default function AdminBroadcastsPage() { trpc.admin.createBroadcast.mutationOptions({ onSuccess: () => { void qc.invalidateQueries({ queryKey: trpc.admin.listBroadcasts.queryKey() }); - toast.success("Mitteilung gesendet — Owner sehen sie beim nächsten Laden der App"); + toast.success("Mitteilung gesendet – Halter sehen sie beim nächsten Öffnen der App"); setTitle(""); setBody(""); }, @@ -65,15 +66,11 @@ export default function AdminBroadcastsPage() { }; return ( -
-
-

Mitteilungen

-

- System-weite Ankündigungen an alle Owner. Senden zeigt den Banner beim nächsten - App-Start; Owner bestätigen mit "Gelesen". Verlauf zeigt, wie viele Owner die - Mitteilung schon erhalten bzw. gelesen haben. -

-
+
+ {/* Send form */}
@@ -85,7 +82,7 @@ export default function AdminBroadcastsPage() { className="bg-muted border-border text-foreground placeholder:text-muted-foreground" />