diff --git a/src/components/PermissionList.tsx b/src/components/PermissionList.tsx index 828c6aac..2911b22f 100644 --- a/src/components/PermissionList.tsx +++ b/src/components/PermissionList.tsx @@ -1,62 +1,105 @@ -import {Permission} from "@/interfaces/permissions"; -import {createColumnHelper, flexRender, getCoreRowModel, useReactTable} from "@tanstack/react-table"; +import React from "react"; +import { Permission } from "@/interfaces/permissions"; +import { + createColumnHelper, + flexRender, + getCoreRowModel, + useReactTable, + Row, +} from "@tanstack/react-table"; import Link from "next/link"; -import {convertCamelCaseToReadable} from "@/utils/string"; +import { convertCamelCaseToReadable } from "@/utils/string"; interface Props { - permissions: Permission[]; + permissions: Permission[]; } const columnHelper = createColumnHelper(); const defaultColumns = [ - columnHelper.accessor("type", { - header: () => Type, - cell: ({row, getValue}) => ( - - {convertCamelCaseToReadable(getValue() as string)} - - ), - }), + columnHelper.accessor("type", { + header: () => Type, + cell: ({ row, getValue }) => ( + + {convertCamelCaseToReadable(getValue() as string)} + + ), + }), ]; -export default function PermissionList({permissions}: Props) { - const table = useReactTable({ - data: permissions, - columns: defaultColumns, - getCoreRowModel: getCoreRowModel(), - }); - return ( -
-
- - - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => ( - - ))} - - ))} - - - {table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - ))} - - ))} - -
- {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} -
- {flexRender(cell.column.columnDef.cell, cell.getContext())} -
-
-
- ); +export default function PermissionList({ permissions }: Props) { + const table = useReactTable({ + data: permissions, + columns: defaultColumns, + getCoreRowModel: getCoreRowModel(), + }); + + const groupedData: { [key: string]: Row[] } = table + .getRowModel() + .rows.reduce((groups: { [key: string]: Row[] }, row) => { + const parent = row.original.topic; + if (!groups[parent]) { + groups[parent] = []; + } + groups[parent].push(row); + return groups; + }, {}); + + return ( +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + ))} + + ))} + + + {Object.keys(groupedData).map((parent) => ( + + + + + {groupedData[parent].map((row, i) => ( + + {row.getVisibleCells().map((cell) => ( + + ))} + + ))} + + ))} + +
+ {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} +
+ {parent} +
+ {flexRender( + cell.column.columnDef.cell, + cell.getContext() + )} +
+
+
+ ); } diff --git a/src/interfaces/permissions.ts b/src/interfaces/permissions.ts index 7ed7337b..d1261b7c 100644 --- a/src/interfaces/permissions.ts +++ b/src/interfaces/permissions.ts @@ -1,58 +1,89 @@ -export const markets = ["au", "br", "de"] as const; +export interface PermissionTopic { + topic: string; + list: string[]; +} export const permissions = [ - // generate codes are basicly invites - "createCodeStudent", - "createCodeTeacher", - "createCodeCorporate", - "createCodeCountryManager", - "createCodeAdmin", - // exams - "createReadingExam", - "createListeningExam", - "createWritingExam", - "createSpeakingExam", - "createLevelExam", - // view pages - "viewExams", - "viewExercises", - "viewRecords", - "viewStats", - "viewTickets", - "viewPaymentRecords", - // view data - "viewStudent", - "viewTeacher", - "viewCorporate", - "viewCountryManager", - "viewAdmin", - "viewGroup", - "viewCodes", - // edit data - "editStudent", - "editTeacher", - "editCorporate", - "editCountryManager", - "editAdmin", - "editGroup", - // delete data - "deleteStudent", - "deleteTeacher", - "deleteCorporate", - "deleteCountryManager", - "deleteAdmin", - "deleteGroup", - "deleteCodes", - // create options - "createGroup", - "createCodes", - "all", + { + topic: "Manage Corporate", + list: [ + "viewCorporate", + "editCorporate", + "deleteCorporate", + "createCodeCorporate", + ], + }, + { + topic: "Manage Admin", + list: ["viewAdmin", "editAdmin", "deleteAdmin", "createCodeAdmin"], + }, + { + topic: "Manage Student", + list: ["viewStudent", "editStudent", "deleteStudent", "createCodeStudent"], + }, + { + topic: "Manage Teacher", + list: ["viewTeacher", "editTeacher", "deleteTeacher", "createCodeTeacher"], + }, + { + topic: "Manage Country Manager", + list: [ + "viewCountryManager", + "editCountryManager", + "deleteCountryManager", + "createCodeCountryManager", + ], + }, + { + topic: "Manage Exams", + list: [ + "createReadingExam", + "createListeningExam", + "createWritingExam", + "createSpeakingExam", + "createLevelExam", + ], + }, + { + topic: "View Pages", + list: [ + "viewExams", + "viewExercises", + "viewRecords", + "viewStats", + "viewTickets", + "viewPaymentRecords", + ], + }, + { + topic: "Manage Group", + list: ["viewGroup", "editGroup", "deleteGroup", "createGroup"], + }, + { + topic: "Manage Codes", + list: ["viewCodes", "deleteCodes", "createCodes"], + }, + { + topic: "Others", + list: ["all"], + }, ] as const; -export type PermissionType = (typeof permissions)[keyof typeof permissions]; +const permissionsList = [ + ...new Set( + permissions.reduce( + (accm: string[], permission) => [...accm, ...permission.list], + [] + ) + ), +]; + +export type PermissionType = + (typeof permissionsList)[keyof typeof permissionsList]; export interface Permission { - id: string; - type: PermissionType; - users: string[]; + id: string; + type: PermissionType; + topic: string; + users: string[]; } diff --git a/src/pages/permissions/index.tsx b/src/pages/permissions/index.tsx index 1beeb146..bce6ed26 100644 --- a/src/pages/permissions/index.tsx +++ b/src/pages/permissions/index.tsx @@ -55,9 +55,7 @@ interface Props { } export default function Page(props: Props) { - const { permissions, user } = props; - return ( <> diff --git a/src/utils/permissions.be.ts b/src/utils/permissions.be.ts index e5b1d979..1f03ffcc 100644 --- a/src/utils/permissions.be.ts +++ b/src/utils/permissions.be.ts @@ -16,12 +16,13 @@ import { Permission, PermissionType, permissions, + PermissionTopic, } from "@/interfaces/permissions"; -import {v4} from "uuid"; +import { v4 } from "uuid"; const db = getFirestore(app); -async function createPermission(type: string) { +async function createPermission(topic: string, type: string) { const permData = doc(db, "permissions", v4()); const permDoc = await getDoc(permData); if (permDoc.exists()) { @@ -30,9 +31,14 @@ async function createPermission(type: string) { await setDoc(permData, { type, + topic, users: [], }); } +interface PermissionsHelperList { + topic: string; + type: string; +} export function getPermissions(userId: string | undefined, docs: Permission[]) { if (!userId) { return []; @@ -52,9 +58,19 @@ export function getPermissions(userId: string | undefined, docs: Permission[]) { } export async function bootstrap() { - await permissions.forEach(async (type) => { - await createPermission(type); - }); + await permissions + .reduce((accm: PermissionsHelperList[], permissionData) => { + return [ + ...accm, + ...permissionData.list.map((type) => ({ + topic: permissionData.topic, + type, + })), + ]; + }, []) + .forEach(async ({ topic, type }) => { + await createPermission(topic, type); + }); } export async function getPermissionDoc(id: string) {