kontenhumas-fe/components/context/permission-context.tsx

117 lines
3.4 KiB
TypeScript

"use client";
import React, { createContext, useContext, useEffect, useState } from "react";
import { getCookiesDecrypt } from "@/lib/utils";
import { getUserLevelModuleAccessesByUserLevelId } from "@/service/user-level-module-accesses";
import { getUserLevelMenuActionAccesses } from "@/service/user-level-menu-action-accesses";
import { getUserInfo } from "@/service/user";
type ModuleAccessMap = Record<string, boolean>;
type ActionAccessMap = Record<string, string[]>;
interface PermissionContextType {
canModule: (moduleCode: string) => boolean;
canAction: (actionCode: string) => boolean;
can: (moduleCode: string, actionCode: string) => boolean;
loading: boolean;
}
const PermissionContext = createContext<PermissionContextType | null>(null);
export const PermissionProvider = ({
children,
}: {
children: React.ReactNode;
}) => {
const [moduleAccess, setModuleAccess] = useState<ModuleAccessMap>({});
const [actionCodes, setActionCodes] = useState<string[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const loadPermissions = async () => {
try {
// ✅ SUMBER KEBENARAN: API USER INFO
const userRes = await getUserInfo();
const userLevelId = userRes?.data?.data?.userLevelId;
console.log("USER LEVEL ID FROM API:", userLevelId);
if (!userLevelId) {
console.error("userLevelId not found from users/info");
return;
}
const [moduleRes, actionRes] = await Promise.all([
getUserLevelModuleAccessesByUserLevelId(userLevelId),
getUserLevelMenuActionAccesses({
userLevelId,
canAccess: true,
limit: 10000,
}),
]);
console.log("ACTION ACCESS RAW:", actionRes?.data?.data);
// 🔹 MODULE ACCESS
// MODULE ACCESS
const moduleMap: Record<string, boolean> = {};
moduleRes?.data?.data?.forEach((item: any) => {
if (
item.module?.code &&
item.canAccess === true &&
item.isActive !== false
) {
moduleMap[item.module.code] = true;
}
});
// ACTION ACCESS
const actions =
actionRes?.data?.data
?.filter(
(item: any) =>
Number(item.userLevelId) === Number(userLevelId) &&
item.canAccess === true &&
item.isActive === true,
)
.map((item: any) => item.actionCode) ?? [];
setModuleAccess(moduleMap);
setActionCodes(actions);
} catch (error) {
console.error("Failed to load permissions", error);
} finally {
setLoading(false);
}
};
loadPermissions();
}, []);
const canModule = (moduleCode: string) => moduleAccess[moduleCode] === true;
const canAction = (actionCode: string) => actionCodes.includes(actionCode);
/**
* FINAL GUARD
* - harus punya module
* - harus punya action
*/
const can = (moduleCode: any, actionCode: any) =>
canModule(moduleCode) && canAction(actionCode);
return (
<PermissionContext.Provider value={{ canModule, canAction, can, loading }}>
{children}
</PermissionContext.Provider>
);
};
export const usePermission = () => {
const ctx = useContext(PermissionContext);
if (!ctx) {
throw new Error("usePermission must be used inside PermissionProvider");
}
return ctx;
};