import { createContext, useCallback, useContext, useState } from "react"; import api from "@/utils/api.util"; import { toast } from "sonner"; const NotificationBroadcastsContext = createContext(null); export function useNotificationBroadcasts() { const ctx = useContext(NotificationBroadcastsContext); if (!ctx) throw new Error("useNotificationBroadcasts must be used within a NotificationBroadcastsProvider"); return ctx; } // ─── Initial States ──────────────────────────────────────────────────────────── const PAGINATION_INIT = { page: 1, limit: 10, totalRecords: 0, totalPages: 0, hasPrevPage: false, hasNextPage: false, }; export function NotificationBroadcastsProvider({ children }) { const [broadcasts, setBroadcasts] = useState([]); const [attributes, setAttributes] = useState([]); const [pagination, setPagination] = useState(PAGINATION_INIT); const [selectedBroadcast, setSelectedBroadcast] = useState(null); const [loading, setLoading] = useState(false); const request = useCallback(async (fn) => { setLoading(true); try { return await fn(); } catch (err) { const message = err?.response?.data?.message ?? "Something went wrong."; toast(message, { action: { label: "Close", onClick: () => {} } }); return null; } finally { setLoading(false); } }, []); // ─── GET /api/admin/notification-broadcasts ──────────────────────────────── const fetchBroadcasts = useCallback( ({ page = 1, limit = 10, filters = [], sort = [] } = {}) => request(async () => { const { data } = await api.get("/admin/notification-broadcasts", { params: { page, limit, filters: filters.length ? JSON.stringify(filters) : undefined, sort: sort.length ? JSON.stringify(sort) : undefined, }, }); const result = data?.data; setBroadcasts(result?.data ?? []); setPagination(result?.pagination ?? PAGINATION_INIT); setAttributes(result.attributes); return data.data; }), [request] ); // ─── GET /api/admin/notification-broadcasts/:broadcastId ────────────────── const fetchBroadcast = useCallback( (broadcastId) => request(async () => { const res = await api.get(`/admin/notification-broadcasts/${broadcastId}`); setSelectedBroadcast(res.data?.data?.data ?? null); return res.data; }), [request] ); // ─── GET /api/admin/notification-broadcasts/archived ─────────────────────── const fetchArchivedBroadcasts = useCallback( ({ page = 1, limit = 10, filters = [], sort = [] } = {}) => request(async () => { const { data } = await api.get("/admin/notification-broadcasts/archived", { params: { page, limit, filters: filters.length ? JSON.stringify(filters) : undefined, sort: sort.length ? JSON.stringify(sort) : undefined, }, }); const final_data = data?.data; setBroadcasts(final_data?.data ?? []); setPagination(final_data?.pagination ?? PAGINATION_INIT); setAttributes(final_data.attributes); return data; }), [request] ); // ─── POST /api/admin/notification-broadcasts ─────────────────────────────── const createBroadcast = useCallback( (fields) => request(async () => { const res = await api.post("/admin/notification-broadcasts", fields); const broadcast = res.data?.data?.data ?? null; if (broadcast) { setBroadcasts((prev) => [broadcast, ...prev]); toast("Notification broadcast created.", { action: { label: "Close", onClick: () => {} } }); } return res.data; }), [request] ); // ─── PATCH /api/admin/notification-broadcasts/:broadcastId ──────────────── const updateBroadcast = useCallback( (broadcastId, fields) => request(async () => { const res = await api.patch(`/admin/notification-broadcasts/${broadcastId}`, fields); const broadcast = res.data?.data?.data ?? null; if (broadcast) { setBroadcasts((prev) => prev.map((b) => (b.broadcast_id === broadcastId ? broadcast : b))); setSelectedBroadcast(broadcast); toast("Notification broadcast updated.", { action: { label: "Close", onClick: () => {} } }); } return res.data; }), [request] ); // ─── PATCH /api/admin/notification-broadcasts/:broadcastId/send ─────────── const sendBroadcast = useCallback( (broadcastId) => request(async () => { const res = await api.patch(`/admin/notification-broadcasts/${broadcastId}/send`); const broadcast = res.data?.data?.data ?? null; if (broadcast) { setBroadcasts((prev) => prev.map((b) => (b.broadcast_id === broadcastId ? broadcast : b))); setSelectedBroadcast(broadcast); toast("Notification broadcast sent.", { action: { label: "Close", onClick: () => {} } }); } return res.data; }), [request] ); // ─── DELETE /api/admin/notification-broadcasts/:broadcastId ─────────────── const archiveBroadcast = useCallback( (broadcastId, { deletedBy } = {}) => request(async () => { const res = await api.delete(`/admin/notification-broadcasts/${broadcastId}`, { data: { deletedBy }, }); setBroadcasts((prev) => prev.filter((b) => b.broadcast_id !== broadcastId)); setSelectedBroadcast((prev) => (prev?.broadcast_id === broadcastId ? null : prev)); toast("Notification broadcast archived.", { action: { label: "Close", onClick: () => {} } }); return res.data; }), [request] ); // ─── DELETE /api/admin/notification-broadcasts/bulk ──────────────────────── const archiveBroadcasts = useCallback( ({ ids }, { deletedBy } = {}) => request(async () => { const res = await api.delete("/admin/notification-broadcasts/bulk", { data: { ids, deletedBy }, }); setBroadcasts((prev) => prev.filter((b) => !ids.includes(b.broadcast_id))); toast(`${ids.length} notification broadcast(s) archived.`, { action: { label: "Close", onClick: () => {} } }); return res.data; }), [request] ); // ─── PATCH /api/admin/notification-broadcasts/:broadcastId/restore ──────── const restoreBroadcast = useCallback( (broadcastId) => request(async () => { const res = await api.patch(`/admin/notification-broadcasts/${broadcastId}/restore`); const broadcast = res.data?.data?.data ?? null; if (broadcast) { setBroadcasts((prev) => prev.filter((b) => b.broadcast_id !== broadcastId)); toast("Notification broadcast restored.", { action: { label: "Close", onClick: () => {} } }); } return res.data; }), [request] ); // ─── PATCH /api/admin/notification-broadcasts/bulk-restore ───────────────── const restoreBroadcasts = useCallback( ({ ids }) => request(async () => { const res = await api.patch("/admin/notification-broadcasts/bulk-restore", { ids }); setBroadcasts((prev) => prev.filter((b) => !ids.includes(b.broadcast_id))); toast(`${ids.length} notification broadcast(s) restored.`, { action: { label: "Close", onClick: () => {} } }); return res.data; }), [request] ); // ─── DELETE /api/admin/notification-broadcasts/:broadcastId/permanent ───── const permanentlyDeleteBroadcast = useCallback( (broadcastId) => request(async () => { const res = await api.delete(`/admin/notification-broadcasts/${broadcastId}/permanent`); setBroadcasts((prev) => prev.filter((b) => b.broadcast_id !== broadcastId)); toast("Notification broadcast permanently deleted.", { action: { label: "Close", onClick: () => {} } }); return res.data; }), [request] ); // ─── DELETE /api/admin/notification-broadcasts/bulk/permanent ───────────── const permanentlyDeleteBroadcasts = useCallback( ({ ids }) => request(async () => { const res = await api.delete("/admin/notification-broadcasts/bulk/permanent", { data: { ids } }); setBroadcasts((prev) => prev.filter((b) => !ids.includes(b.broadcast_id))); toast(`${ids.length} notification broadcast(s) permanently deleted.`, { action: { label: "Close", onClick: () => {} } }); return res.data; }), [request] ); return ( {children} ); }