From 94a1d5b94bf10419936bb124dfcab03629c5c4e8 Mon Sep 17 00:00:00 2001 From: JoeX17 Date: Sat, 27 Jun 2026 21:35:16 +0100 Subject: [PATCH] feat: implement admin audit log UI (FE-26), admin events management (FE-27), admin announcements UI (FE-28, BE-30) Closes #1206 Closes #1207 Closes #1208 Closes #1209 --- frontend/app/admin/announcements/page.tsx | 105 ++++++++++++++ frontend/app/admin/audit-log/page.tsx | 121 ++++++++++++++++ frontend/app/admin/events/page.tsx | 135 ++++++++++++++++++ .../announcements/useGetAnnouncements.ts | 11 ++ .../announcements/useSendAnnouncement.ts | 13 ++ .../hooks/admin/audit/useGetAuditLog.ts | 27 ++++ .../hooks/admin/events/useCancelEvent.ts | 12 ++ .../hooks/admin/events/useCreateEvent.ts | 12 ++ .../hooks/admin/events/useGetAdminEvents.ts | 11 ++ .../hooks/admin/events/useUpdateEvent.ts | 13 ++ 10 files changed, 460 insertions(+) create mode 100644 frontend/app/admin/announcements/page.tsx create mode 100644 frontend/app/admin/audit-log/page.tsx create mode 100644 frontend/app/admin/events/page.tsx create mode 100644 frontend/lib/react-query/hooks/admin/announcements/useGetAnnouncements.ts create mode 100644 frontend/lib/react-query/hooks/admin/announcements/useSendAnnouncement.ts create mode 100644 frontend/lib/react-query/hooks/admin/audit/useGetAuditLog.ts create mode 100644 frontend/lib/react-query/hooks/admin/events/useCancelEvent.ts create mode 100644 frontend/lib/react-query/hooks/admin/events/useCreateEvent.ts create mode 100644 frontend/lib/react-query/hooks/admin/events/useGetAdminEvents.ts create mode 100644 frontend/lib/react-query/hooks/admin/events/useUpdateEvent.ts diff --git a/frontend/app/admin/announcements/page.tsx b/frontend/app/admin/announcements/page.tsx new file mode 100644 index 00000000..9e725210 --- /dev/null +++ b/frontend/app/admin/announcements/page.tsx @@ -0,0 +1,105 @@ +"use client"; + +import { useState } from "react"; +import DashboardLayout from "@/components/dashboard/DashboardLayout"; +import { useGetAnnouncements } from "@/lib/react-query/hooks/admin/announcements/useGetAnnouncements"; +import { useSendAnnouncement } from "@/lib/react-query/hooks/admin/announcements/useSendAnnouncement"; +import { Megaphone, Plus, X } from "lucide-react"; + +const AUDIENCES = ["ALL_MEMBERS", "ACTIVE_MEMBERS", "STAFF"]; +const CHANNELS = ["IN_APP", "EMAIL", "BOTH"]; + +export default function AdminAnnouncementsPage() { + const [showModal, setShowModal] = useState(false); + const [form, setForm] = useState({ title: "", content: "", audience: "ALL_MEMBERS", channel: "IN_APP" }); + + const { data, isLoading } = useGetAnnouncements(); + const send = useSendAnnouncement(); + const announcements = (data as any)?.items ?? (data as any)?.data ?? []; + + const handleSend = async (e: React.FormEvent) => { + e.preventDefault(); + await send.mutateAsync({ title: form.title, content: form.content }); + setShowModal(false); + setForm({ title: "", content: "", audience: "ALL_MEMBERS", channel: "IN_APP" }); + }; + + return ( + +
+
+

Announcements

+

Broadcast messages to member segments.

+
+ +
+ + {isLoading ? ( +
Loading...
+ ) : (Array.isArray(announcements) ? announcements : []).length === 0 ? ( +
+ +

No announcements yet.

+
+ ) : ( +
+ {(Array.isArray(announcements) ? announcements : []).map((ann: any) => ( +
+
+
+

{ann.title}

+

{ann.content}

+
+ {new Date(ann.createdAt).toLocaleDateString()} +
+
+ ))} +
+ )} + + {showModal && ( +
+
+
+

New Announcement

+ +
+
+
+ + setForm({ ...form, title: e.target.value })} required className="w-full border border-gray-200 rounded-lg px-3 py-2 text-sm" /> +
+
+ + +
+
+ + +
+
+ +