add: more commits

Signed-off-by: Kenneth Obsequio <k80308392@gmail.com>
This commit is contained in:
2026-07-03 16:21:27 +08:00
parent 17326b2c2e
commit 7e964f2432
112 changed files with 9160 additions and 3461 deletions
@@ -0,0 +1,221 @@
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.error(message);
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.success("Notification broadcast created.");
}
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.success("Notification broadcast updated.");
}
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.success("Notification broadcast sent.");
}
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.success("Notification broadcast archived.");
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.success(`${ids.length} notification broadcast(s) archived.`);
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.success("Notification broadcast restored.");
}
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.success(`${ids.length} notification broadcast(s) restored.`);
return res.data;
}),
[request]
);
return (
<NotificationBroadcastsContext.Provider value={{
broadcasts,
attributes,
pagination,
selectedBroadcast,
loading,
setPagination,
setSelectedBroadcast,
fetchBroadcasts,
fetchBroadcast,
fetchArchivedBroadcasts,
createBroadcast,
updateBroadcast,
sendBroadcast,
archiveBroadcast,
archiveBroadcasts,
restoreBroadcast,
restoreBroadcasts,
}}>
{children}
</NotificationBroadcastsContext.Provider>
);
}