diff --git a/src/app/(main)/settings/company/page.tsx b/src/app/(main)/settings/company/page.tsx
index 26332c1..3b6e140 100644
--- a/src/app/(main)/settings/company/page.tsx
+++ b/src/app/(main)/settings/company/page.tsx
@@ -8,6 +8,8 @@ import Typography from "@mui/material/Typography";
import Link from "next/link";
import { Suspense } from "react";
import { fetchCompanys, preloadCompanys } from "@/app/api/companys";
+import { getUserAbilities } from "@/app/utils/commonUtil";
+import { MAINTAIN_COMPANY } from "@/middleware";
export const metadata: Metadata = {
title: "Company",
@@ -20,6 +22,9 @@ const Company: React.FC = async () => {
fetchCompanys();
preloadCompanys();
+ const abilities = await getUserAbilities()
+ const maintainCompany = abilities.includes(MAINTAIN_COMPANY)
+
return (
<>
{
{t("Company")}
- }
LinkComponent={Link}
href="/settings/company/create"
>
{t("Create Company")}
-
+ }
}>
diff --git a/src/app/(main)/settings/customer/page.tsx b/src/app/(main)/settings/customer/page.tsx
index 1f55f78..91f5ac3 100644
--- a/src/app/(main)/settings/customer/page.tsx
+++ b/src/app/(main)/settings/customer/page.tsx
@@ -9,6 +9,8 @@ import { Metadata } from "next";
import Link from "next/link";
import { Suspense } from "react";
import { I18nProvider } from "@/i18n";
+import { getUserAbilities } from "@/app/utils/commonUtil";
+import { MAINTAIN_CLIENT } from "@/middleware";
export const metadata: Metadata = {
title: "Customer",
@@ -17,6 +19,8 @@ export const metadata: Metadata = {
const Customer: React.FC = async () => {
const { t } = await getServerI18n("customer");
preloadAllCustomers();
+ const abilities = await getUserAbilities()
+ const maintainClient = abilities.includes(MAINTAIN_CLIENT)
return (
<>
@@ -29,14 +33,14 @@ const Customer: React.FC = async () => {
{t("Customer")}
- }
LinkComponent={Link}
href="/settings/customer/create"
>
{t("Create Customer")}
-
+ }
}>
diff --git a/src/app/(main)/settings/department/page.tsx b/src/app/(main)/settings/department/page.tsx
index a051721..be2b265 100644
--- a/src/app/(main)/settings/department/page.tsx
+++ b/src/app/(main)/settings/department/page.tsx
@@ -8,6 +8,8 @@ import Typography from "@mui/material/Typography";
import Link from "next/link";
import { Suspense } from "react";
import { fetchDepartments, preloadDepartments } from "@/app/api/departments";
+import { getUserAbilities } from "@/app/utils/commonUtil";
+import { MAINTAIN_DEPARTMENT } from "@/middleware";
export const metadata: Metadata = {
title: "Department",
@@ -20,6 +22,9 @@ const Department: React.FC = async () => {
// fetchDepartments();
// preloadDepartments();
+ const abilities = await getUserAbilities()
+ const maintainDepartment = abilities.includes(MAINTAIN_DEPARTMENT)
+
return (
<>
{
{t("Department")}
- }
LinkComponent={Link}
href="/settings/department/new"
>
{t("Create Department")}
-
+ }
}>
diff --git a/src/app/(main)/settings/position/page.tsx b/src/app/(main)/settings/position/page.tsx
index 5342145..5eccd8d 100644
--- a/src/app/(main)/settings/position/page.tsx
+++ b/src/app/(main)/settings/position/page.tsx
@@ -8,6 +8,8 @@ import Typography from "@mui/material/Typography";
import Link from "next/link";
import { Suspense } from "react";
import { fetchPositions, preloadPositions } from "@/app/api/positions";
+import { getUserAbilities } from "@/app/utils/commonUtil";
+import { MAINTAIN_POSITION } from "@/middleware";
export const metadata: Metadata = {
title: "Position",
@@ -20,6 +22,9 @@ const Position: React.FC = async () => {
// fetchPositions();
// preloadPositions();
+ const abilities = await getUserAbilities()
+ const maintainPosition = abilities.includes(MAINTAIN_POSITION)
+
return (
<>
{
{t("Position")}
- }
LinkComponent={Link}
href="/settings/position/new"
>
{t("Create Position")}
-
+ }
}>
diff --git a/src/app/(main)/settings/skill/page.tsx b/src/app/(main)/settings/skill/page.tsx
index bcb14ab..44d3c53 100644
--- a/src/app/(main)/settings/skill/page.tsx
+++ b/src/app/(main)/settings/skill/page.tsx
@@ -1,7 +1,9 @@
import { preloadClaims } from "@/app/api/claims";
+import { getUserAbilities } from "@/app/utils/commonUtil";
// import { preloadSkill, preloadTeamLeads } from "@/app/api/staff";
import SkillSearch from "@/components/SkillSearch";
import { I18nProvider, getServerI18n } from "@/i18n";
+import { MAINTAIN_SKILL } from "@/middleware";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
@@ -18,6 +20,10 @@ const Skill: React.FC = async () => {
const { t } = await getServerI18n("skill");
// preloadTeamLeads();
// preloadSkill();
+
+ const abilities = await getUserAbilities()
+ const maintainSkill = abilities.includes(MAINTAIN_SKILL)
+
return (
<>
{
{t("Skill")}
- }
LinkComponent={Link}
href="/settings/skill/create"
>
{t("Create Skill")}
-
+ }
}>
diff --git a/src/app/(main)/settings/staff/page.tsx b/src/app/(main)/settings/staff/page.tsx
index db26d1b..5bb84cb 100644
--- a/src/app/(main)/settings/staff/page.tsx
+++ b/src/app/(main)/settings/staff/page.tsx
@@ -1,7 +1,9 @@
import { preloadClaims } from "@/app/api/claims";
import { preloadStaff, preloadTeamLeads } from "@/app/api/staff";
+import { getUserAbilities } from "@/app/utils/commonUtil";
import StaffSearch from "@/components/StaffSearch";
import { I18nProvider, getServerI18n } from "@/i18n";
+import { MAINTAIN_STAFF } from "@/middleware";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
@@ -18,6 +20,10 @@ const Staff: React.FC = async () => {
const { t } = await getServerI18n("staff");
preloadTeamLeads();
preloadStaff();
+
+ const abilities = await getUserAbilities();
+ const maintainStaff = abilities.includes(MAINTAIN_STAFF)
+
return (
<>
{
{t("Staff")}
- }
LinkComponent={Link}
href="/settings/staff/create"
>
{t("Create Staff")}
-
+ }
}>
diff --git a/src/app/(main)/settings/subsidiary/page.tsx b/src/app/(main)/settings/subsidiary/page.tsx
index cadb670..ad7fd74 100644
--- a/src/app/(main)/settings/subsidiary/page.tsx
+++ b/src/app/(main)/settings/subsidiary/page.tsx
@@ -9,6 +9,8 @@ import { Suspense } from "react";
import { I18nProvider } from "@/i18n";
import { preloadAllSubsidiaries } from "@/app/api/subsidiary";
import SubsidiarySearch from "@/components/SubsidiarySearch";
+import { getUserAbilities } from "@/app/utils/commonUtil";
+import { MAINTAIN_SUBSIDIARY } from "@/middleware";
export const metadata: Metadata = {
title: "Subsidiary",
@@ -17,6 +19,8 @@ export const metadata: Metadata = {
const Subsidiary: React.FC = async () => {
const { t } = await getServerI18n("subsidiary");
preloadAllSubsidiaries();
+ const abilities = await getUserAbilities()
+ const maintainSubsidiary = abilities.includes(MAINTAIN_SUBSIDIARY)
return (
<>
@@ -29,14 +33,14 @@ const Subsidiary: React.FC = async () => {
{t("Subsidiary")}
- }
LinkComponent={Link}
href="/settings/subsidiary/create"
>
{t("Create Subsidiary")}
-
+ }
}>
diff --git a/src/app/(main)/settings/team/page.tsx b/src/app/(main)/settings/team/page.tsx
index b2b67ab..d2965a1 100644
--- a/src/app/(main)/settings/team/page.tsx
+++ b/src/app/(main)/settings/team/page.tsx
@@ -1,8 +1,10 @@
import { preloadClaims } from "@/app/api/claims";
import { preloadStaff, preloadTeamLeads } from "@/app/api/staff";
+import { getUserAbilities } from "@/app/utils/commonUtil";
import StaffSearch from "@/components/StaffSearch";
import TeamSearch from "@/components/TeamSearch";
import { I18nProvider, getServerI18n } from "@/i18n";
+import { MAINTAIN_TEAM } from "@/middleware";
import Add from "@mui/icons-material/Add";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
@@ -21,6 +23,10 @@ export const metadata: Metadata = {
const { t } = await getServerI18n("team");
// preloadTeamLeads();
// preloadStaff();
+
+ const abilities = await getUserAbilities()
+ const maintainTeam = abilities.includes(MAINTAIN_TEAM)
+
return (
<>
{t("Team")}
- }
LinkComponent={Link}
href="/settings/team/create"
>
{t("Create Team")}
-
+ }
}>
diff --git a/src/components/CompanyHoliday/CompanyHoliday.tsx b/src/components/CompanyHoliday/CompanyHoliday.tsx
index ec92960..c3d9f32 100644
--- a/src/components/CompanyHoliday/CompanyHoliday.tsx
+++ b/src/components/CompanyHoliday/CompanyHoliday.tsx
@@ -23,16 +23,19 @@ import {
import { useRouter } from "next/navigation";
import { deleteDialog, submitDialog } from "../Swal/CustomAlerts";
import { getPublicHolidaysForNYears } from "@/app/utils/holidayUtils";
+import { MAINTAIN_HOLIDAY } from "@/middleware";
interface Props {
holidays: HolidaysList[];
+ abilities: String[];
}
-const CompanyHoliday: React.FC = ({ holidays }) => {
+const CompanyHoliday: React.FC = ({ holidays, abilities }) => {
const { t } = useTranslation("holidays");
const router = useRouter();
const formValues = useFormContext();
const [serverError, setServerError] = useState("");
+ const maintainHoliday = abilities.includes(MAINTAIN_HOLIDAY)
const companyHolidays = useMemo(
() => [...getPublicHolidaysForNYears(2), ...holidays],
@@ -139,7 +142,7 @@ const CompanyHoliday: React.FC = ({ holidays }) => {
}}
/>
{
// const Companys = await fetchCompanys();
- const companyHolidays: HolidaysResult[] = await fetchHolidays()
+ const [companyHolidays, abilities] = await Promise.all([fetchHolidays(), getUserAbilities()])
// console.log(companyHolidays)
const convertedHolidays = companyHolidays.map((holiday) => {
@@ -26,7 +27,7 @@ const CompanyHolidayWrapper: React.FC & SubComponents = async () => {
})
- return ;
+ return ;
};
CompanyHolidayWrapper.Loading = CompanyHolidayLoading;
diff --git a/src/components/CompanySearch/CompanySearch.tsx b/src/components/CompanySearch/CompanySearch.tsx
index 8a12f75..94cc1b6 100644
--- a/src/components/CompanySearch/CompanySearch.tsx
+++ b/src/components/CompanySearch/CompanySearch.tsx
@@ -10,21 +10,25 @@ import { useRouter } from "next/navigation";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { deleteCompany } from "@/app/api/companys/actions";
import DeleteIcon from '@mui/icons-material/Delete';
+import { MAINTAIN_COMPANY } from "@/middleware";
interface Props {
companys: CompanyResult[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const CompanySearch: React.FC = ({ companys }) => {
+const CompanySearch: React.FC = ({ companys, abilities }) => {
const { t } = useTranslation("companys");
const router = useRouter()
const [filteredCompanys, setFilteredCompanys] = useState(companys);
+ const maintainCompany = abilities.includes(MAINTAIN_COMPANY)
+
const searchCriteria: Criterion[] = useMemo(
() => [
{ label: t("Company code"), paramName: "companyCode", type: "text" },
@@ -62,6 +66,7 @@ const CompanySearch: React.FC = ({ companys }) => {
label: t("Details"),
onClick: onProjectClick,
buttonIcon: ,
+ isHidden: !maintainCompany,
},
{ name: "companyCode", label: t("Company Code") },
{ name: "name", label: t("Company Name") },
@@ -74,7 +79,8 @@ const CompanySearch: React.FC = ({ companys }) => {
label: t("Delete"),
onClick: onDeleteClick,
buttonIcon: ,
- color: "error"
+ color: "error",
+ isHidden: !maintainCompany,
},
],
[t, onProjectClick],
diff --git a/src/components/CompanySearch/CompanySearchWrapper.tsx b/src/components/CompanySearch/CompanySearchWrapper.tsx
index f7e61a0..2fdfe55 100644
--- a/src/components/CompanySearch/CompanySearchWrapper.tsx
+++ b/src/components/CompanySearch/CompanySearchWrapper.tsx
@@ -3,6 +3,7 @@ import React from "react";
import CompanySearch from "./CompanySearch";
import CompanySearchLoading from "./CompanySearchLoading";
import { fetchCompanys } from "@/app/api/companys";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof CompanySearchLoading;
@@ -10,9 +11,9 @@ interface SubComponents {
const CompanySearchWrapper: React.FC & SubComponents = async () => {
// const Companys = await fetchCompanys();
- const Companys = await fetchCompanys();
+ const [Companys, abilities] = await Promise.all([fetchCompanys(), getUserAbilities()]);
- return ;
+ return ;
};
CompanySearchWrapper.Loading = CompanySearchLoading;
diff --git a/src/components/CustomerSearch/CustomerSearch.tsx b/src/components/CustomerSearch/CustomerSearch.tsx
index cacf5fa..7b39ade 100644
--- a/src/components/CustomerSearch/CustomerSearch.tsx
+++ b/src/components/CustomerSearch/CustomerSearch.tsx
@@ -10,18 +10,21 @@ import DeleteIcon from '@mui/icons-material/Delete';
import { useRouter, useSearchParams } from "next/navigation";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { deleteCustomer } from "@/app/api/customer/actions";
+import { MAINTAIN_CLIENT } from "@/middleware";
interface Props {
customers: Customer[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const CustomerSearch: React.FC = ({ customers }) => {
+const CustomerSearch: React.FC = ({ customers, abilities }) => {
const { t } = useTranslation();
const router = useRouter()
const searchParams = useSearchParams()
+ const maintainClient = abilities.includes(MAINTAIN_CLIENT)
const [filteredCustomers, setFilteredCustomers] = useState(customers);
useEffect(() => {
@@ -60,6 +63,7 @@ const CustomerSearch: React.FC = ({ customers }) => {
label: t("Details"),
onClick: onTaskClick,
buttonIcon: ,
+ isHidden: !maintainClient
},
{ name: "code", label: t("Customer Code") },
{ name: "name", label: t("Customer Name") },
@@ -68,7 +72,8 @@ const CustomerSearch: React.FC = ({ customers }) => {
label: t("Delete"),
onClick: onDeleteClick,
buttonIcon: ,
- color: "error"
+ color: "error",
+ isHidden: !maintainClient
},
],
[onTaskClick, t],
diff --git a/src/components/CustomerSearch/CustomerSearchWrapper.tsx b/src/components/CustomerSearch/CustomerSearchWrapper.tsx
index 531adb6..0b696b4 100644
--- a/src/components/CustomerSearch/CustomerSearchWrapper.tsx
+++ b/src/components/CustomerSearch/CustomerSearchWrapper.tsx
@@ -2,15 +2,16 @@ import { fetchAllCustomers } from "@/app/api/customer";
import React from "react";
import CustomerSearch from "./CustomerSearch";
import CustomerSearchLoading from "./CustomerSearchLoading";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof CustomerSearchLoading;
}
const CustomerSearchWrapper: React.FC & SubComponents = async () => {
- const [customers] = await Promise.all([fetchAllCustomers()]);
+ const [customers, abilities] = await Promise.all([fetchAllCustomers(), getUserAbilities()]);
- return ;
+ return ;
};
CustomerSearchWrapper.Loading = CustomerSearchLoading;
diff --git a/src/components/DepartmentSearch/DepartmentSearch.tsx b/src/components/DepartmentSearch/DepartmentSearch.tsx
index bbbd0a7..cb95aa2 100644
--- a/src/components/DepartmentSearch/DepartmentSearch.tsx
+++ b/src/components/DepartmentSearch/DepartmentSearch.tsx
@@ -10,19 +10,22 @@ import { useRouter } from "next/navigation";
import DeleteIcon from '@mui/icons-material/Delete';
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { deleteDepartment } from "@/app/api/departments/actions";
+import { MAINTAIN_DEPARTMENT } from "@/middleware";
interface Props {
departments: DepartmentResult[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const DepartmentSearch: React.FC = ({ departments }) => {
+const DepartmentSearch: React.FC = ({ departments, abilities }) => {
const { t } = useTranslation("departments");
const router = useRouter();
const [filteredDepartments, setFilteredDepartments] = useState(departments);
+ const maintainDepartment = abilities.includes(MAINTAIN_DEPARTMENT)
const searchCriteria: Criterion[] = useMemo(
() => [
@@ -60,6 +63,7 @@ const DepartmentSearch: React.FC = ({ departments }) => {
label: t("Details"),
onClick: onProjectClick,
buttonIcon: ,
+ isHidden: !maintainDepartment,
},
{ name: "code", label: t("Department Code") },
{ name: "name", label: t("Department Name") },
@@ -69,7 +73,8 @@ const DepartmentSearch: React.FC = ({ departments }) => {
label: t("Delete"),
onClick: onDeleteClick,
buttonIcon: ,
- color: "error"
+ color: "error",
+ isHidden: !maintainDepartment,
},
],
[t, onProjectClick],
diff --git a/src/components/DepartmentSearch/DepartmentSearchWrapper.tsx b/src/components/DepartmentSearch/DepartmentSearchWrapper.tsx
index 4249dfd..109f058 100644
--- a/src/components/DepartmentSearch/DepartmentSearchWrapper.tsx
+++ b/src/components/DepartmentSearch/DepartmentSearchWrapper.tsx
@@ -3,16 +3,17 @@ import React from "react";
import DepartmentSearch from "./DepartmentSearch";
import DepartmentSearchLoading from "./DepartmentSearchLoading";
import { fetchDepartments } from "@/app/api/departments";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof DepartmentSearchLoading;
}
const DepartmentSearchWrapper: React.FC & SubComponents = async () => {
- const Departments = await fetchDepartments();
+ const [Departments, abilities] = await Promise.all([fetchDepartments(), getUserAbilities()]);
// const Departments:any[] = []
- return ;
+ return ;
};
DepartmentSearchWrapper.Loading = DepartmentSearchLoading;
diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx
index 1332fe6..110870d 100644
--- a/src/components/NavigationContent/NavigationContent.tsx
+++ b/src/components/NavigationContent/NavigationContent.tsx
@@ -39,15 +39,34 @@ import {
GENERATE_REPORTS,
IMPORT_INVOICE,
IMPORT_RECEIPT,
- MAINTAIN_MASTERDATA,
MAINTAIN_PROJECT,
MAINTAIN_TASK_TEMPLATE,
MAINTAIN_USER,
VIEW_DASHBOARD_ALL,
VIEW_DASHBOARD_SELF,
- VIEW_MASTERDATA,
VIEW_PROJECT,
- VIEW_USER,
+ VIEW_CLIENT,
+ VIEW_SUBSIDIARY,
+ VIEW_STAFF,
+ VIEW_COMPANY,
+ VIEW_SKILL,
+ VIEW_DEPARTMENT,
+ VIEW_POSITION,
+ VIEW_SALARY,
+ VIEW_TEAM,
+ VIEW_USER_GROUP,
+ VIEW_HOLIDAY,
+ MAINTAIN_CLIENT,
+ MAINTAIN_SUBSIDIARY,
+ MAINTAIN_STAFF,
+ MAINTAIN_COMPANY,
+ MAINTAIN_SKILL,
+ MAINTAIN_DEPARTMENT,
+ MAINTAIN_POSITION,
+ MAINTAIN_SALARY,
+ MAINTAIN_TEAM,
+ MAINTAIN_USER_GROUP,
+ MAINTAIN_HOLIDAY,
} from "@/middleware";
import { SessionWithAbilities } from "../AppBar/NavigationToggle";
import { authOptions } from "@/config/authConfig";
@@ -217,35 +236,101 @@ const NavigationContent: React.FC = ({ abilities, username }) => {
icon: ,
label: "Setting",
path: "",
- isHidden: ![VIEW_MASTERDATA, MAINTAIN_MASTERDATA].some((ability) =>
+ isHidden: ![
+ VIEW_CLIENT,
+ VIEW_SUBSIDIARY,
+ VIEW_STAFF,
+ VIEW_COMPANY,
+ VIEW_SKILL,
+ VIEW_DEPARTMENT,
+ VIEW_POSITION,
+ VIEW_SALARY,
+ VIEW_TEAM,
+ VIEW_USER_GROUP,
+ VIEW_HOLIDAY,
+ MAINTAIN_CLIENT,
+ MAINTAIN_SUBSIDIARY,
+ MAINTAIN_STAFF,
+ MAINTAIN_COMPANY,
+ MAINTAIN_SKILL,
+ MAINTAIN_DEPARTMENT,
+ MAINTAIN_POSITION,
+ MAINTAIN_SALARY,
+ MAINTAIN_TEAM,
+ MAINTAIN_USER_GROUP,
+ MAINTAIN_HOLIDAY
+ ].some((ability) =>
abilities!.includes(ability),
),
children: [
- { icon: , label: "Client", path: "/settings/customer" },
+ {
+ icon: ,
+ label: "Client",
+ path: "/settings/customer",
+ isHidden: ![VIEW_CLIENT, MAINTAIN_CLIENT].some((ability) => abilities!.includes(ability),),
+ },
{
icon: ,
label: "Subsidiary",
path: "/settings/subsidiary",
+ isHidden: ![VIEW_SUBSIDIARY, MAINTAIN_SUBSIDIARY].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Staff",
+ path: "/settings/staff",
+ isHidden: ![VIEW_STAFF, MAINTAIN_STAFF].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Company",
+ path: "/settings/company",
+ isHidden: ![VIEW_COMPANY, MAINTAIN_COMPANY].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Skill",
+ path: "/settings/skill",
+ isHidden: ![VIEW_SKILL, MAINTAIN_SKILL].some((ability) => abilities!.includes(ability),),
},
- { icon: , label: "Staff", path: "/settings/staff" },
- { icon: , label: "Company", path: "/settings/company" },
- { icon: , label: "Skill", path: "/settings/skill" },
{
icon: ,
label: "Department",
path: "/settings/department",
+ isHidden: ![VIEW_DEPARTMENT, MAINTAIN_DEPARTMENT].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Position",
+ path: "/settings/position",
+ isHidden: ![VIEW_POSITION, MAINTAIN_POSITION].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Salary",
+ path: "/settings/salary",
+ isHidden: ![VIEW_SALARY, MAINTAIN_SALARY].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Team",
+ path: "/settings/team",
+ isHidden: ![VIEW_TEAM, MAINTAIN_TEAM].some((ability) => abilities!.includes(ability),),
},
- { icon: , label: "Position", path: "/settings/position" },
- { icon: , label: "Salary", path: "/settings/salary" },
- { icon: , label: "Team", path: "/settings/team" },
// { icon: , label: "User", path: "/settings/user" },
{
icon: ,
label: "User Group",
path: "/settings/group",
+ isHidden: ![VIEW_USER_GROUP, MAINTAIN_USER_GROUP].some((ability) => abilities!.includes(ability),),
+ },
+ {
+ icon: ,
+ label: "Holiday",
+ path: "/settings/holiday",
+ isHidden: ![VIEW_HOLIDAY, MAINTAIN_HOLIDAY].some((ability) => abilities!.includes(ability),),
},
- { icon: , label: "Holiday", path: "/settings/holiday"},
- { icon: , label: "Import Excel File", path: "/settings/import", isHidden: username !== "2fi"},
+ { icon: , label: "Import Excel File", path: "/settings/import", isHidden: username !== "2fi" },
],
},
];
diff --git a/src/components/PositionSearch/PositionSearch.tsx b/src/components/PositionSearch/PositionSearch.tsx
index e700e2a..26085fe 100644
--- a/src/components/PositionSearch/PositionSearch.tsx
+++ b/src/components/PositionSearch/PositionSearch.tsx
@@ -10,19 +10,22 @@ import { useRouter } from "next/navigation";
import DeleteIcon from '@mui/icons-material/Delete';
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { deletePosition } from "@/app/api/positions/actions";
+import { MAINTAIN_POSITION } from "@/middleware";
interface Props {
positions: PositionResult[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const PositionSearch: React.FC = ({ positions }) => {
+const PositionSearch: React.FC = ({ positions, abilities }) => {
const { t } = useTranslation("positions");
const router = useRouter();
const [filteredPositions, setFilteredPositions] = useState(positions);
+ const maintainPosition = abilities.includes(MAINTAIN_POSITION)
const searchCriteria: Criterion[] = useMemo(
() => [
@@ -61,6 +64,7 @@ const PositionSearch: React.FC = ({ positions }) => {
label: t("Details"),
onClick: onPositionClick,
buttonIcon: ,
+ isHidden: !maintainPosition,
},
{ name: "code", label: t("Position Code") },
{ name: "name", label: t("Position Name") },
@@ -70,7 +74,8 @@ const PositionSearch: React.FC = ({ positions }) => {
label: t("Delete"),
onClick: onDeleteClick,
buttonIcon: ,
- color: "error"
+ color: "error",
+ isHidden: !maintainPosition,
},
],
[t, onPositionClick],
diff --git a/src/components/PositionSearch/PositionSearchWrapper.tsx b/src/components/PositionSearch/PositionSearchWrapper.tsx
index f115a77..a76f302 100644
--- a/src/components/PositionSearch/PositionSearchWrapper.tsx
+++ b/src/components/PositionSearch/PositionSearchWrapper.tsx
@@ -3,16 +3,17 @@ import React from "react";
import PositionSearch from "./PositionSearch";
import PositionSearchLoading from "./PositionSearchLoading";
import { fetchPositions } from "@/app/api/positions";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof PositionSearchLoading;
}
const PositionSearchWrapper: React.FC & SubComponents = async () => {
- const Positions = await fetchPositions();
+ const [Positions, abilities] = await Promise.all([fetchPositions(), getUserAbilities()]);
// const Positions:any[] = []
- return ;
+ return ;
};
PositionSearchWrapper.Loading = PositionSearchLoading;
diff --git a/src/components/SalarySearch/SalarySearch.tsx b/src/components/SalarySearch/SalarySearch.tsx
index 5c3a49d..0022a48 100644
--- a/src/components/SalarySearch/SalarySearch.tsx
+++ b/src/components/SalarySearch/SalarySearch.tsx
@@ -13,18 +13,21 @@ import FileUploadIcon from '@mui/icons-material/FileUpload';
import { exportSalary, importSalarys } from "@/app/api/salarys/actions";
import { downloadFile } from "@/app/utils/commonUtil";
import { errorDialog, successDialog } from "../Swal/CustomAlerts";
+import { MAINTAIN_SALARY } from "@/middleware";
interface Props {
salarys: SalaryResult[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const SalarySearch: React.FC = ({ salarys }) => {
+const SalarySearch: React.FC = ({ salarys, abilities }) => {
const { t } = useTranslation("salarys");
const [filteredSalarys, setFilteredSalarys] = useState(salarys);
+ const maintainSalary = abilities.includes(MAINTAIN_SALARY)
const searchCriteria: Criterion[] = useMemo(
() => [
@@ -109,7 +112,7 @@ const SalarySearch: React.FC = ({ salarys }) => {
return (
<>
- = ({ salarys }) => {
{t("Export Salary")}
-
+ }
{
diff --git a/src/components/SalarySearch/SalarySearchWrapper.tsx b/src/components/SalarySearch/SalarySearchWrapper.tsx
index 83fe593..650a011 100644
--- a/src/components/SalarySearch/SalarySearchWrapper.tsx
+++ b/src/components/SalarySearch/SalarySearchWrapper.tsx
@@ -3,6 +3,7 @@ import React from "react";
import SalarySearch from "./SalarySearch";
import SalarySearchLoading from "./SalarySearchLoading";
import { fetchSalarys } from "@/app/api/salarys";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof SalarySearchLoading;
@@ -14,7 +15,7 @@ interface SubComponents {
// }
const SalarySearchWrapper: React.FC & SubComponents = async () => {
- const Salarys = await fetchSalarys();
+ const [Salarys, abilities] = await Promise.all([fetchSalarys(), getUserAbilities()]);
// const Salarys:any[] = []
const salarysWithHourlyRate = Salarys.map((salary) => {
// const hourlyRate = calculateHourlyRate(Number(salary.lowerLimit), Number(salary.upperLimit),22, 8)
@@ -27,7 +28,7 @@ const SalarySearchWrapper: React.FC & SubComponents = async () => {
})
// console.log(salarysWithHourlyRate)
- return ;
+ return ;
};
SalarySearchWrapper.Loading = SalarySearchLoading;
diff --git a/src/components/SkillSearch/SkillSearch.tsx b/src/components/SkillSearch/SkillSearch.tsx
index 0e883b7..0b5a481 100644
--- a/src/components/SkillSearch/SkillSearch.tsx
+++ b/src/components/SkillSearch/SkillSearch.tsx
@@ -9,15 +9,17 @@ import { useRouter } from "next/navigation";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { SkillResult } from "@/app/api/skill";
import { deleteSkill } from "@/app/api/skill/actions";
+import { MAINTAIN_SKILL } from "@/middleware";
interface Props {
skill: SkillResult[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const SkillSearch: React.FC = ({ skill }) => {
+const SkillSearch: React.FC = ({ skill, abilities }) => {
const { t } = useTranslation();
const [filteredSkill, setFilteredSkill] = useState(skill);
const router = useRouter();
@@ -30,6 +32,8 @@ const SkillSearch: React.FC = ({ skill }) => {
const code = t("code")
const description = t("description")
+ const maintainSkill = abilities.includes(MAINTAIN_SKILL)
+
const searchCriteria: Criterion[] = useMemo(
() => [
{
@@ -73,6 +77,7 @@ const SkillSearch: React.FC = ({ skill }) => {
label: edit,
onClick: onSkillClick,
buttonIcon: ,
+ isHidden: !maintainSkill,
},
{ name: "name", label: name },
{ name: "code", label: code },
@@ -83,6 +88,7 @@ const SkillSearch: React.FC = ({ skill }) => {
onClick: deleteClick,
buttonIcon: ,
color: "error",
+ isHidden: !maintainSkill,
},
],
[t, onSkillClick, deleteClick]
diff --git a/src/components/SkillSearch/SkillSearchWrapper.tsx b/src/components/SkillSearch/SkillSearchWrapper.tsx
index ba5be7d..8936b56 100644
--- a/src/components/SkillSearch/SkillSearchWrapper.tsx
+++ b/src/components/SkillSearch/SkillSearchWrapper.tsx
@@ -2,15 +2,16 @@ import React from "react";
import SkillSearch from "./SkillSearch";
import SkillSearchLoading from "./SkillSearchLoading";
import { fetchSkill } from "@/app/api/skill";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof SkillSearchLoading;
}
const SkillSearchWrapper: React.FC & SubComponents = async () => {
- const skill = await fetchSkill()
+ const [skill, abilities] = await Promise.all([fetchSkill(), getUserAbilities()])
- return ;
+ return ;
};
SkillSearchWrapper.Loading = SkillSearchLoading;
diff --git a/src/components/StaffSearch/StaffSearch.tsx b/src/components/StaffSearch/StaffSearch.tsx
index 16b4dba..b38b005 100644
--- a/src/components/StaffSearch/StaffSearch.tsx
+++ b/src/components/StaffSearch/StaffSearch.tsx
@@ -10,7 +10,7 @@ import { deleteStaff } from "@/app/api/staff/actions";
import { useRouter } from "next/navigation";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import Person from '@mui/icons-material/Person';
-import { MAINTAIN_USER, VIEW_USER } from "@/middleware";
+import { MAINTAIN_STAFF, MAINTAIN_USER } from "@/middleware";
import { TeamResult } from "@/app/api/team";
import { Grade } from "@/app/api/grades";
import { PositionResult } from "@/app/api/positions";
@@ -20,13 +20,13 @@ interface Props {
teams: TeamResult[]
grades: Grade[]
positions: PositionResult[]
- isAuthed: boolean
+ abilities: String[]
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const StaffSearch: React.FC = ({ staff, teams, grades, positions, isAuthed }) => {
+const StaffSearch: React.FC = ({ staff, teams, grades, positions, abilities }) => {
const { t } = useTranslation();
const [filteredStaff, setFilteredStaff] = useState(staff);
const router = useRouter();
@@ -35,6 +35,9 @@ const StaffSearch: React.FC = ({ staff, teams, grades, positions, isAuthe
const gradeCombo = grades.map(g => `${g.name}`)
const positionCombo = positions.map(p => `${p.name}`)
+ const maintainUser = abilities.includes(MAINTAIN_USER)
+ const maintainStaff = abilities.includes(MAINTAIN_STAFF)
+
const searchCriteria: Criterion[] = useMemo(
() => [
{
@@ -104,13 +107,14 @@ const StaffSearch: React.FC = ({ staff, teams, grades, positions, isAuthe
label: t("Actions"),
onClick: onStaffClick,
buttonIcon: ,
+ isHidden: !maintainStaff,
},
{
name: "id",
label: t("Users"),
onClick: onUserClick,
buttonIcon: ,
- isHidden: isAuthed,
+ isHidden: !maintainUser,
},
{ name: "team", label: t("Team") },
{ name: "name", label: t("Staff Name") },
@@ -123,6 +127,7 @@ const StaffSearch: React.FC = ({ staff, teams, grades, positions, isAuthe
onClick: deleteClick,
buttonIcon: ,
color: "error",
+ isHidden: !maintainStaff,
},
],
[t, onStaffClick, deleteClick]
diff --git a/src/components/StaffSearch/StaffSearchWrapper.tsx b/src/components/StaffSearch/StaffSearchWrapper.tsx
index 42f5f83..6a4854e 100644
--- a/src/components/StaffSearch/StaffSearchWrapper.tsx
+++ b/src/components/StaffSearch/StaffSearchWrapper.tsx
@@ -7,7 +7,7 @@ import { authOptions } from "@/config/authConfig";
import { fetchTeam } from "@/app/api/team";
import { fetchPositions } from "@/app/api/positions";
import { fetchGrades } from "@/app/api/grades";
-import { MAINTAIN_USER, VIEW_USER } from "@/middleware";
+import { MAINTAIN_USER } from "@/middleware";
interface SubComponents {
Loading: typeof StaffSearchLoading;
@@ -19,14 +19,14 @@ interface SessionWithAbilities extends Session {
const StaffSearchWrapper: React.FC & SubComponents = async () => {
const session = await getServerSession(authOptions) as SessionWithAbilities;
- const isAuthed = ![MAINTAIN_USER, VIEW_USER].some((ability) => session.abilities!.includes(ability))
+ const abilities = session.abilities!
const staff = await fetchStaff();
const teams = await fetchTeam();
const grades = await fetchGrades();
const positions = await fetchPositions();
- return ;
+ return ;
};
StaffSearchWrapper.Loading = StaffSearchLoading;
diff --git a/src/components/SubsidiarySearch/SubsidiarySearch.tsx b/src/components/SubsidiarySearch/SubsidiarySearch.tsx
index a50f4a9..79bab48 100644
--- a/src/components/SubsidiarySearch/SubsidiarySearch.tsx
+++ b/src/components/SubsidiarySearch/SubsidiarySearch.tsx
@@ -10,18 +10,21 @@ import { useRouter, useSearchParams } from "next/navigation";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
import { Subsidiary } from "@/app/api/subsidiary";
import { deleteSubsidiary } from "@/app/api/subsidiary/actions";
+import { MAINTAIN_SUBSIDIARY } from "@/middleware";
interface Props {
subsidiaries: Subsidiary[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const SubsidiarySearch: React.FC = ({ subsidiaries }) => {
+const SubsidiarySearch: React.FC = ({ subsidiaries, abilities }) => {
const { t } = useTranslation();
const router = useRouter()
const searchParams = useSearchParams()
+ const maintainSubsidiary = abilities.includes(MAINTAIN_SUBSIDIARY)
const [filteredSubsidiaries, setFilteredSubsidiaries] = useState(subsidiaries);
useEffect(() => {
@@ -63,6 +66,7 @@ const SubsidiarySearch: React.FC = ({ subsidiaries }) => {
label: t("Details"),
onClick: onTaskClick,
buttonIcon: ,
+ isHidden: !maintainSubsidiary,
},
{ name: "code", label: t("Subsidiary Code") },
{ name: "name", label: t("Subsidiary Name") },
@@ -71,7 +75,8 @@ const SubsidiarySearch: React.FC = ({ subsidiaries }) => {
label: t("Delete"),
onClick: onDeleteClick,
buttonIcon: ,
- color: "error"
+ color: "error",
+ isHidden: !maintainSubsidiary,
},
],
[onTaskClick, t],
diff --git a/src/components/SubsidiarySearch/SubsidiarySearchWrapper.tsx b/src/components/SubsidiarySearch/SubsidiarySearchWrapper.tsx
index 13e8312..e6a8134 100644
--- a/src/components/SubsidiarySearch/SubsidiarySearchWrapper.tsx
+++ b/src/components/SubsidiarySearch/SubsidiarySearchWrapper.tsx
@@ -2,15 +2,16 @@ import React from "react";
import SubsidiarySearch from "./SubsidiarySearch";
import SubsidiarySearchLoading from "./SubsidiarySearchLoading";
import { fetchAllSubsidiaries } from "@/app/api/subsidiary";
+import { getUserAbilities } from "@/app/utils/commonUtil";
interface SubComponents {
Loading: typeof SubsidiarySearchLoading;
}
const SubsidiarySearchWrapper: React.FC & SubComponents = async () => {
- const subsidiaries = await fetchAllSubsidiaries();
+ const [subsidiaries, abilities] = await Promise.all([fetchAllSubsidiaries(), getUserAbilities()]);
- return ;
+ return ;
};
SubsidiarySearchWrapper.Loading = SubsidiarySearchLoading;
diff --git a/src/components/TeamSearch/TeamSearch.tsx b/src/components/TeamSearch/TeamSearch.tsx
index 571a6ab..3c16a11 100644
--- a/src/components/TeamSearch/TeamSearch.tsx
+++ b/src/components/TeamSearch/TeamSearch.tsx
@@ -10,14 +10,16 @@ import DeleteIcon from "@mui/icons-material/Delete";
import { useRouter } from "next/navigation";
import { deleteTeam } from "@/app/api/team/actions";
import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
+import { MAINTAIN_TEAM } from "@/middleware";
interface Props {
team: TeamResult[];
+ abilities: String[];
}
type SearchQuery = Partial>;
type SearchParamNames = keyof SearchQuery;
-const TeamSearch: React.FC = ({ team }) => {
+const TeamSearch: React.FC = ({ team, abilities }) => {
const { t } = useTranslation();
const [filteredTeam, setFilteredTeam] = useState(team);
const router = useRouter();
@@ -29,6 +31,8 @@ const TeamSearch: React.FC = ({ team }) => {
const teamLead = t("teamLead")
const delete_t = t("delete")
+ const maintainTeam = abilities.includes(MAINTAIN_TEAM)
+
const searchCriteria: Criterion[] = useMemo(
() => [
{
@@ -77,6 +81,7 @@ const TeamSearch: React.FC = ({ team }) => {
label: edit,
onClick: onTeamClick,
buttonIcon: ,
+ isHidden: !maintainTeam,
},
{ name: "name", label: name },
{ name: "code", label: code },
@@ -87,7 +92,8 @@ const TeamSearch: React.FC = ({ team }) => {
label: delete_t,
onClick: onDeleteClick,
buttonIcon: ,
- color: "error"
+ color: "error",
+ isHidden: !maintainTeam,
},
],
[t]
diff --git a/src/components/TeamSearch/TeamSearchWrapper.tsx b/src/components/TeamSearch/TeamSearchWrapper.tsx
index bd4f714..f27f228 100644
--- a/src/components/TeamSearch/TeamSearchWrapper.tsx
+++ b/src/components/TeamSearch/TeamSearchWrapper.tsx
@@ -3,6 +3,7 @@ import React from "react";
import TeamSearch from "./TeamSearch";
import TeamSearchLoading from "./TeamSearchLoading";
import { fetchTeam } from "@/app/api/team";
+import { getUserAbilities } from "@/app/utils/commonUtil";
// import { preloadTeam } from "@/app/api/Team";
interface SubComponents {
@@ -10,10 +11,10 @@ interface SubComponents {
}
const TeamSearchWrapper: React.FC & SubComponents = async () => {
- const Team = await fetchTeam();
+ const [Team, abilities] = await Promise.all([fetchTeam(), getUserAbilities()]);
console.log(Team);
- return ;
+ return ;
};
TeamSearchWrapper.Loading = TeamSearchLoading;
diff --git a/src/middleware.ts b/src/middleware.ts
index 6dce586..a719d65 100644
--- a/src/middleware.ts
+++ b/src/middleware.ts
@@ -11,22 +11,41 @@ export const [
NORMAL_STAFF,
SUPPORTING_STAFF
] = [
- "Super Admin",
- "Top Management",
- "Team Leader",
- "Normal Staff",
- "Supporting Staff"
-]
+ "Super Admin",
+ "Top Management",
+ "Team Leader",
+ "Normal Staff",
+ "Supporting Staff"
+ ]
// abilities
export const [
- VIEW_USER,
MAINTAIN_USER,
MAINTAIN_TIMESHEET,
VIEW_TASK_TEMPLATE,
VIEW_GROUP,
- VIEW_MASTERDATA,
- MAINTAIN_MASTERDATA,
+ VIEW_CLIENT,
+ VIEW_SUBSIDIARY,
+ VIEW_STAFF,
+ VIEW_COMPANY,
+ VIEW_SKILL,
+ VIEW_DEPARTMENT,
+ VIEW_POSITION,
+ VIEW_SALARY,
+ VIEW_TEAM,
+ VIEW_USER_GROUP,
+ VIEW_HOLIDAY,
+ MAINTAIN_CLIENT,
+ MAINTAIN_SUBSIDIARY,
+ MAINTAIN_STAFF,
+ MAINTAIN_COMPANY,
+ MAINTAIN_SKILL,
+ MAINTAIN_DEPARTMENT,
+ MAINTAIN_POSITION,
+ MAINTAIN_SALARY,
+ MAINTAIN_TEAM,
+ MAINTAIN_USER_GROUP,
+ MAINTAIN_HOLIDAY,
VIEW_DASHBOARD_SELF,
VIEW_DASHBOARD_ALL,
IMPORT_INVOICE,
@@ -41,27 +60,46 @@ export const [
DELETE_PROJECT,
MAINTAIN_TIMESHEET_FAST_TIME_ENTRY,
] = [
- 'VIEW_USER',
- 'MAINTAIN_USER',
- 'MAINTAIN_TIMESHEET',
- 'VIEW_TASK_TEMPLATE',
- 'VIEW_GROUP',
- 'VIEW_MASTERDATA',
- 'MAINTAIN_MASTERDATA',
- 'VIEW_DASHBOARD_SELF',
- 'VIEW_DASHBOARD_ALL',
- 'IMPORT_INVOICE',
- 'MAINTAIN_GROUP',
- 'GENERATE_REPORTS',
- 'VIEW_STAFF_PROFILE',
- 'IMPORT_RECEIPT',
- 'MAINTAIN_TASK_TEMPLATE',
- 'MAINTAIN_TIMESHEET_7DAYS',
- 'VIEW_PROJECT',
- 'MAINTAIN_PROJECT',
- 'DELETE_PROJECT',
- 'MAINTAIN_TIMESHEET_FAST_TIME_ENTRY'
-]
+ 'MAINTAIN_USER',
+ 'MAINTAIN_TIMESHEET',
+ 'VIEW_TASK_TEMPLATE',
+ 'VIEW_GROUP',
+ 'VIEW_CLIENT',
+ 'VIEW_SUBSIDIARY',
+ 'VIEW_STAFF',
+ 'VIEW_COMPANY',
+ 'VIEW_SKILL',
+ 'VIEW_DEPARTMENT',
+ 'VIEW_POSITION',
+ 'VIEW_SALARY',
+ 'VIEW_TEAM',
+ 'VIEW_USER_GROUP',
+ 'VIEW_HOLIDAY',
+ 'MAINTAIN_CLIENT',
+ 'MAINTAIN_SUBSIDIARY',
+ 'MAINTAIN_STAFF',
+ 'MAINTAIN_COMPANY',
+ 'MAINTAIN_SKILL',
+ 'MAINTAIN_DEPARTMENT',
+ 'MAINTAIN_POSITION',
+ 'MAINTAIN_SALARY',
+ 'MAINTAIN_TEAM',
+ 'MAINTAIN_USER_GROUP',
+ 'MAINTAIN_HOLIDAY',
+ 'VIEW_DASHBOARD_SELF',
+ 'VIEW_DASHBOARD_ALL',
+ 'IMPORT_INVOICE',
+ 'MAINTAIN_GROUP',
+ 'GENERATE_REPORTS',
+ 'VIEW_STAFF_PROFILE',
+ 'IMPORT_RECEIPT',
+ 'MAINTAIN_TASK_TEMPLATE',
+ 'MAINTAIN_TIMESHEET_7DAYS',
+ 'VIEW_PROJECT',
+ 'MAINTAIN_PROJECT',
+ 'DELETE_PROJECT',
+ 'MAINTAIN_TIMESHEET_FAST_TIME_ENTRY'
+ ]
const PRIVATE_ROUTES = [
"/analytics",
@@ -93,7 +131,7 @@ export default async function middleware(
const authMiddleware = withAuth({
pages: authOptions.pages,
callbacks: {
- authorized: ({req, token}) => {
+ authorized: ({ req, token }) => {
let isAuth = Boolean(token);
if (!Boolean(token)) {
return Boolean(token)
@@ -109,26 +147,96 @@ export default async function middleware(
}
if (req.nextUrl.pathname.startsWith('/settings')) {
- isAuth = [VIEW_MASTERDATA, MAINTAIN_MASTERDATA].some((ability) => abilities.includes(ability));
- }
+ isAuth = [
+ VIEW_CLIENT,
+ VIEW_SUBSIDIARY,
+ VIEW_STAFF,
+ VIEW_COMPANY,
+ VIEW_SKILL,
+ VIEW_DEPARTMENT,
+ VIEW_POSITION,
+ VIEW_SALARY,
+ VIEW_TEAM,
+ VIEW_USER_GROUP,
+ VIEW_HOLIDAY,
+ MAINTAIN_CLIENT,
+ MAINTAIN_SUBSIDIARY,
+ MAINTAIN_STAFF,
+ MAINTAIN_COMPANY,
+ MAINTAIN_SKILL,
+ MAINTAIN_DEPARTMENT,
+ MAINTAIN_POSITION,
+ MAINTAIN_SALARY,
+ MAINTAIN_TEAM,
+ MAINTAIN_USER_GROUP,
+ MAINTAIN_HOLIDAY
+ ].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/customer/create') || req.nextUrl.pathname.startsWith('/settings/customer/edit')) {
+ isAuth = [MAINTAIN_CLIENT].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/subsidiary/create') || req.nextUrl.pathname.startsWith('/settings/subsidiary/edit')) {
+ isAuth = [MAINTAIN_SUBSIDIARY].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/staff/create') || req.nextUrl.pathname.startsWith('/settings/staff/edit')) {
+ isAuth = [MAINTAIN_STAFF].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/company/create') || req.nextUrl.pathname.startsWith('/settings/company/edit')) {
+ isAuth = [MAINTAIN_COMPANY].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/skill/create') || req.nextUrl.pathname.startsWith('/settings/skill/edit')) {
+ isAuth = [MAINTAIN_SKILL].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/department/create') || req.nextUrl.pathname.startsWith('/settings/department/edit')) {
+ isAuth = [MAINTAIN_DEPARTMENT].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/position/create') || req.nextUrl.pathname.startsWith('/settings/position/edit')) {
+ isAuth = [MAINTAIN_POSITION].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/team/create') || req.nextUrl.pathname.startsWith('/settings/team/edit')) {
+ isAuth = [MAINTAIN_TEAM].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/group/create') || req.nextUrl.pathname.startsWith('/settings/group/edit')) {
+ isAuth = [MAINTAIN_USER_GROUP].some((ability) => abilities.includes(ability));
+ }
+
+ if (req.nextUrl.pathname.startsWith('/settings/holiday/create') || req.nextUrl.pathname.startsWith('/settings/holiday/edit')) {
+ isAuth = [MAINTAIN_HOLIDAY].some((ability) => abilities.includes(ability));
+ }
+
if (req.nextUrl.pathname.startsWith('/settings/user')) {
- isAuth = [MAINTAIN_USER, VIEW_USER].some((ability) => abilities.includes(ability));
+ isAuth = [MAINTAIN_USER].some((ability) => abilities.includes(ability));
}
+
if (req.nextUrl.pathname.startsWith('/settings/staff/user')) {
- isAuth = [MAINTAIN_USER, VIEW_USER].some((ability) => abilities.includes(ability));
+ isAuth = [MAINTAIN_USER].some((ability) => abilities.includes(ability));
}
+
if (req.nextUrl.pathname.startsWith('/analytics')) {
isAuth = [GENERATE_REPORTS].some((ability) => abilities.includes(ability));
}
+
if (req.nextUrl.pathname.startsWith('/settings/staff/edit')) {
isAuth = [VIEW_STAFF_PROFILE].some((ability) => abilities.includes(ability));
}
+
if (req.nextUrl.pathname.startsWith('/invoice')) {
isAuth = [IMPORT_INVOICE, IMPORT_RECEIPT].some((ability) => abilities.includes(ability));
}
+
if (req.nextUrl.pathname.startsWith('/dashboard')) {
isAuth = [VIEW_DASHBOARD_ALL, VIEW_DASHBOARD_SELF].some((ability) => abilities.includes(ability));
}
+
return isAuth
}
}