mirror of
https://github.com/rgrgogu/new_starr.git
synced 2026-09-27 00:12:54 +08:00
Adjusted
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
/***********************************************************************************************************************************************************************
|
||||
* File Name: AdminUserGroupContext.jsx
|
||||
* Type of Program: Context
|
||||
* Description: Admin-level user group management context.
|
||||
* Covers: list groups, get single group + members, create, update,
|
||||
* deactivate, restore, add/remove members.
|
||||
*
|
||||
* Author: rgrgogu
|
||||
***********************************************************************************************************************************************************************/
|
||||
import { createContext, useCallback, useContext, useState } from "react";
|
||||
import api from "@/utils/api.util";
|
||||
import { toast } from "sonner";
|
||||
|
||||
const BASE = "/admin";
|
||||
|
||||
// ─── Context ──────────────────────────────────────────────────────────────────
|
||||
const UserGroupContext = createContext(null);
|
||||
|
||||
export function useUserGroups() {
|
||||
const ctx = useContext(UserGroupContext);
|
||||
if (!ctx) throw new Error("useUserGroups must be used within a UserGroupProvider");
|
||||
return ctx;
|
||||
}
|
||||
|
||||
// ─── Provider ─────────────────────────────────────────────────────────────────
|
||||
export function UserGroupProvider({ children }) {
|
||||
const [groups, setGroups] = useState([]);
|
||||
const [group, setGroup] = useState(null); // single group + its members
|
||||
const [members, setMembers] = useState([]); // members inside current group
|
||||
const [usersIn, setUsersIn] = useState([]); // users already in group (for remove)
|
||||
const [usersNotIn, setUsersNotIn] = useState([]); // users not in group (for add)
|
||||
const [attributes, setAttributes] = useState([]);
|
||||
const [pagination, setPagination] = useState({ page: 1, limit: 10, total: 0, totalPages: 1 });
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
// ─── Generic request wrapper ────────────────────────────────────────────────
|
||||
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/groups ─────────────────────────────────────────────────
|
||||
const fetchGroups = useCallback(
|
||||
({ page = 1, limit = 10, filters = [], sort = [] } = {}) =>
|
||||
request(async () => {
|
||||
const res = await api.get(`${BASE}/groups`, {
|
||||
params: { page, limit, filters: JSON.stringify(filters), sort: JSON.stringify(sort) },
|
||||
});
|
||||
|
||||
const { data, attributes: attrs, pagination: pg } = res.data?.data ?? {};
|
||||
|
||||
setGroups(data ?? []);
|
||||
setAttributes(attrs ?? []);
|
||||
setPagination(pg ?? { page, limit, total: 0, totalPages: 1 });
|
||||
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── GET /api/admin/groups/:gid ────────────────────────────────────────────
|
||||
const fetchGroup = useCallback(
|
||||
(gid, paginationParams = {}) =>
|
||||
request(async () => {
|
||||
const { page = 1, limit = 10, filters = [], sort = [] } = paginationParams;
|
||||
|
||||
const res = await api.get(`${BASE}/groups/${gid}`, {
|
||||
params: { page, limit, filters: JSON.stringify(filters), sort: JSON.stringify(sort) },
|
||||
});
|
||||
|
||||
const { group: g, members: m } = res.data?.data ?? {};
|
||||
|
||||
setGroup(g ?? null);
|
||||
setMembers(m?.data ?? []);
|
||||
setPagination(m?.pagination ?? { page, limit, total: 0, totalPages: 1 });
|
||||
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── GET /api/admin/groups/:gid/users ──────────────────────────────────────
|
||||
const fetchUsersInGroup = useCallback(
|
||||
(gid) =>
|
||||
request(async () => {
|
||||
const res = await api.get(`${BASE}/groups/${gid}/users`);
|
||||
setUsersIn(res.data?.data ?? []);
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── GET /api/admin/groups/:gid/users/add ──────────────────────────────────
|
||||
const fetchUsersNotInGroup = useCallback(
|
||||
(gid) =>
|
||||
request(async () => {
|
||||
const res = await api.get(`${BASE}/groups/${gid}/users/add`);
|
||||
setUsersNotIn(res.data?.data ?? []);
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── POST /api/admin/groups ────────────────────────────────────────────────
|
||||
const createGroup = useCallback(
|
||||
({ name, description }) =>
|
||||
request(async () => {
|
||||
const res = await api.post(`${BASE}/groups`, { name, description });
|
||||
|
||||
setGroups((prev) => [res.data?.data, ...prev]);
|
||||
|
||||
toast.success("Group created successfully.");
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── PUT /api/admin/groups/:gid ────────────────────────────────────────────
|
||||
const updateGroup = useCallback(
|
||||
(gid, { name, description }) =>
|
||||
request(async () => {
|
||||
const res = await api.put(`${BASE}/groups/${gid}`, { name, description });
|
||||
|
||||
setGroups((prev) =>
|
||||
prev.map((g) => (g.group_id === gid ? { ...g, ...res.data?.data } : g))
|
||||
);
|
||||
|
||||
// Update single group view if open
|
||||
setGroup((prev) => (prev?.group_id === gid ? { ...prev, ...res.data?.data } : prev));
|
||||
|
||||
toast.success("Group updated successfully.");
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── PATCH /api/admin/groups/:gid/deactivate ───────────────────────────────
|
||||
const deactivateGroup = useCallback(
|
||||
(gid) =>
|
||||
request(async () => {
|
||||
const res = await api.patch(`${BASE}/groups/${gid}/deactivate`);
|
||||
|
||||
setGroups((prev) =>
|
||||
prev.map((g) => (g.group_id === gid ? { ...g, is_active: false } : g))
|
||||
);
|
||||
|
||||
toast.success("Group deactivated.");
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── PATCH /api/admin/groups/:gid/restore ─────────────────────────────────
|
||||
const restoreGroup = useCallback(
|
||||
(gid) =>
|
||||
request(async () => {
|
||||
const res = await api.patch(`${BASE}/groups/${gid}/restore`);
|
||||
|
||||
setGroups((prev) =>
|
||||
prev.map((g) => (g.group_id === gid ? { ...g, is_active: true } : g))
|
||||
);
|
||||
|
||||
toast.success("Group restored.");
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── POST /api/admin/groups/:gid/users ────────────────────────────────────
|
||||
const addUsersToGroup = useCallback(
|
||||
(gid, user_ids) =>
|
||||
request(async () => {
|
||||
const res = await api.post(`${BASE}/groups/${gid}/users`, { user_ids });
|
||||
|
||||
// Remove added users from usersNotIn list
|
||||
setUsersNotIn((prev) => prev.filter((u) => !user_ids.includes(u.user_id)));
|
||||
|
||||
toast.success("Users added to group.");
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── DELETE /api/admin/groups/:gid/users ──────────────────────────────────
|
||||
const removeUsersFromGroup = useCallback(
|
||||
(gid, user_ids) =>
|
||||
request(async () => {
|
||||
const res = await api.delete(`${BASE}/groups/${gid}/users`, { data: { user_ids } });
|
||||
|
||||
// Remove from members list
|
||||
setMembers((prev) => prev.filter((u) => !user_ids.includes(u.user_id)));
|
||||
setUsersIn((prev) => prev.filter((u) => !user_ids.includes(u.user_id)));
|
||||
|
||||
toast.success("Users removed from group.");
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── DELETE /api/admin/groups/bulk ────────────────────────────────────────────
|
||||
const deactivateGroups = useCallback(
|
||||
({ ids }) =>
|
||||
request(async () => {
|
||||
const res = await api.delete(`${BASE}/groups/bulk`, { data: { ids } });
|
||||
const { deactivated_ids } = res.data?.data ?? {};
|
||||
|
||||
if (deactivated_ids?.length) {
|
||||
setGroups((prev) =>
|
||||
prev.map((g) =>
|
||||
deactivated_ids.includes(g.group_id) ? { ...g, is_active: false } : g
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── POST /api/admin/groups/bulk/restore ──────────────────────────────────────
|
||||
const restoreGroups = useCallback(
|
||||
({ ids }) =>
|
||||
request(async () => {
|
||||
const res = await api.post(`${BASE}/groups/bulk/restore`, { ids });
|
||||
const { restored_ids } = res.data?.data ?? {};
|
||||
|
||||
if (restored_ids?.length) {
|
||||
setGroups((prev) =>
|
||||
prev.map((g) =>
|
||||
restored_ids.includes(g.group_id) ? { ...g, is_active: true } : g
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
// ─── GET /api/admin/groups/field-values ───────────────────────────────────────
|
||||
const fetchGroupFieldValues = useCallback(
|
||||
(field) =>
|
||||
request(async () => {
|
||||
const res = await api.get(`${BASE}/groups/field-values`, { params: { field } });
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
const fetchArchivedGroups = useCallback(
|
||||
({ page = 1, limit = 10, filters = [], sort = [] } = {}) =>
|
||||
request(async () => {
|
||||
const res = await api.get(`${BASE}/groups/archived`, {
|
||||
params: { page, limit, filters: JSON.stringify(filters), sort: JSON.stringify(sort) },
|
||||
});
|
||||
|
||||
const { data, attributes: attrs, pagination: pg } = res.data?.data ?? {};
|
||||
|
||||
setGroups(data ?? []);
|
||||
setAttributes(attrs ?? []);
|
||||
setPagination(pg ?? { page, limit, total: 0, totalPages: 1 });
|
||||
|
||||
return res.data;
|
||||
}),
|
||||
[request]
|
||||
);
|
||||
|
||||
return (
|
||||
<UserGroupContext.Provider
|
||||
value={{
|
||||
// state
|
||||
groups,
|
||||
group,
|
||||
members,
|
||||
usersIn,
|
||||
usersNotIn,
|
||||
attributes,
|
||||
pagination,
|
||||
setPagination,
|
||||
loading,
|
||||
|
||||
// actions
|
||||
fetchGroups,
|
||||
fetchGroup,
|
||||
fetchUsersInGroup,
|
||||
fetchUsersNotInGroup,
|
||||
fetchGroupFieldValues,
|
||||
fetchArchivedGroups,
|
||||
createGroup,
|
||||
updateGroup,
|
||||
deactivateGroup,
|
||||
deactivateGroups,
|
||||
restoreGroup,
|
||||
restoreGroups,
|
||||
addUsersToGroup,
|
||||
removeUsersFromGroup,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</UserGroupContext.Provider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user