diff --git a/src/app/(main)/settings/group/create/page.tsx b/src/app/(main)/settings/group/create/page.tsx
new file mode 100644
index 0000000..9130236
--- /dev/null
+++ b/src/app/(main)/settings/group/create/page.tsx
@@ -0,0 +1,22 @@
+// 'use client';
+import { I18nProvider, getServerI18n } from "@/i18n";
+import React, { useCallback, useState } from "react";
+import { Typography } from "@mui/material";
+import CreateGroup from "@/components/CreateGroup";
+
+// const Title = ["title1", "title2"];
+
+const CreateStaff: React.FC = async () => {
+ const { t } = await getServerI18n("group");
+
+ return (
+ <>
+ {t("Create Group")}
+
+
+
+ >
+ );
+};
+
+export default CreateStaff;
diff --git a/src/app/(main)/settings/group/edit/page.tsx b/src/app/(main)/settings/group/edit/page.tsx
new file mode 100644
index 0000000..e69de29
diff --git a/src/app/(main)/settings/group/page.tsx b/src/app/(main)/settings/group/page.tsx
new file mode 100644
index 0000000..5322132
--- /dev/null
+++ b/src/app/(main)/settings/group/page.tsx
@@ -0,0 +1,55 @@
+import { preloadClaims } from "@/app/api/claims";
+import { preloadStaff, preloadTeamLeads } from "@/app/api/staff";
+import StaffSearch from "@/components/StaffSearch";
+import TeamSearch from "@/components/TeamSearch";
+import UserGroupSearch from "@/components/UserGroupSearch";
+import UserSearch from "@/components/UserSearch";
+import { I18nProvider, getServerI18n } from "@/i18n";
+import Add from "@mui/icons-material/Add";
+import Button from "@mui/material/Button";
+import Stack from "@mui/material/Stack";
+import Typography from "@mui/material/Typography";
+import { Metadata } from "next";
+import Link from "next/link";
+import { Suspense } from "react";
+
+
+export const metadata: Metadata = {
+ title: "User Group",
+ };
+
+
+ const UserGroup: React.FC = async () => {
+ const { t } = await getServerI18n("User Group");
+ // preloadTeamLeads();
+ // preloadStaff();
+ return (
+ <>
+
+
+ {t("User Group")}
+
+ }
+ LinkComponent={Link}
+ href="/settings/group/create"
+ >
+ {t("Create User Group")}
+
+
+
+ }>
+
+
+
+ >
+ );
+ };
+
+ export default UserGroup;
\ No newline at end of file
diff --git a/src/app/(main)/settings/team/create/page.tsx b/src/app/(main)/settings/team/create/page.tsx
index 721fda7..a47d81c 100644
--- a/src/app/(main)/settings/team/create/page.tsx
+++ b/src/app/(main)/settings/team/create/page.tsx
@@ -28,10 +28,6 @@ import CreateTeam from "@/components/CreateTeam";
const CreateTeamPage: React.FC = async () => {
const { t } = await getServerI18n("team");
- const title = ['', t('Additional Info')]
- // const regex = new RegExp("^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$")
- // console.log(regex)
-
return (
<>
{t("Create Team")}
diff --git a/src/app/(main)/settings/user/edit/page.tsx b/src/app/(main)/settings/user/edit/page.tsx
new file mode 100644
index 0000000..659347b
--- /dev/null
+++ b/src/app/(main)/settings/user/edit/page.tsx
@@ -0,0 +1,24 @@
+import { Edit } from "@mui/icons-material";
+import { useSearchParams } from "next/navigation";
+// import EditStaff from "@/components/EditStaff";
+import { Suspense } from "react";
+import { I18nProvider } from "@/i18n";
+// import EditStaffWrapper from "@/components/EditStaff/EditStaffWrapper";
+import { Metadata } from "next";
+import EditUser from "@/components/EditUser";
+
+
+const EditUserPage: React.FC = () => {
+
+ return (
+ <>
+
+ }>
+
+
+
+ >
+ );
+};
+
+export default EditUserPage;
diff --git a/src/app/(main)/settings/user/page.tsx b/src/app/(main)/settings/user/page.tsx
index 95973ab..ef7635f 100644
--- a/src/app/(main)/settings/user/page.tsx
+++ b/src/app/(main)/settings/user/page.tsx
@@ -33,14 +33,14 @@ export const metadata: Metadata = {
{t("User")}
- }
LinkComponent={Link}
href="/settings/team/create"
>
{t("Create User")}
-
+ */}
}>
diff --git a/src/app/api/group/actions.ts b/src/app/api/group/actions.ts
new file mode 100644
index 0000000..c8881de
--- /dev/null
+++ b/src/app/api/group/actions.ts
@@ -0,0 +1,44 @@
+"use server";
+
+import { serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
+import { BASE_API_URL } from "@/config/api";
+import { revalidateTag } from "next/cache";
+import { cache } from "react";
+
+
+export interface CreateGroupInputs {
+ id?: number;
+ name: string;
+ description: string;
+ addUserIds?: number[];
+ removeUserIds?: number[];
+ addAuthIds?: number[];
+ removeAuthIds?: number[];
+ }
+
+export interface auth {
+ id: number;
+ module?: any | null;
+ authority: string;
+ name: string;
+ description: string | null;
+ v: number;
+ }
+
+export interface record {
+ records: auth[];
+ }
+
+ export const fetchAuth = cache(async () => {
+ return serverFetchJson(`${BASE_API_URL}/group/auth/combo`, {
+ next: { tags: ["auth"] },
+ });
+ });
+
+export const saveGroup = async (data: CreateGroupInputs) => {
+ return serverFetchJson(`${BASE_API_URL}/group/save`, {
+ method: "POST",
+ body: JSON.stringify(data),
+ headers: { "Content-Type": "application/json" },
+ });
+ };
\ No newline at end of file
diff --git a/src/app/api/group/index.ts b/src/app/api/group/index.ts
new file mode 100644
index 0000000..9dcee9e
--- /dev/null
+++ b/src/app/api/group/index.ts
@@ -0,0 +1,21 @@
+import { serverFetchJson } from "@/app/utils/fetchUtil";
+import { BASE_API_URL } from "@/config/api";
+import { cache } from "react";
+import "server-only";
+
+export interface Records {
+ records: UserGroupResult[]
+}
+
+export interface UserGroupResult {
+ id: number;
+ action: () => void;
+ name: string;
+ description: string;
+}
+
+export const fetchGroup = cache(async () => {
+ return serverFetchJson(`${BASE_API_URL}/group`, {
+ next: { tags: ["group"] },
+ });
+ });
diff --git a/src/app/api/user/actions.ts b/src/app/api/user/actions.ts
index 5df734a..4d353c3 100644
--- a/src/app/api/user/actions.ts
+++ b/src/app/api/user/actions.ts
@@ -8,8 +8,7 @@ import { cache } from "react";
export interface UserInputs {
username: string;
- firstname: string;
- lastname: string;
+ email: string;
}
@@ -19,6 +18,14 @@ export const fetchUserDetails = cache(async (id: number) => {
});
});
+export const editUser = async (id: number, data: UserInputs) => {
+ return serverFetchWithNoContent(`${BASE_API_URL}/user/${id}`, {
+ method: "PUT",
+ body: JSON.stringify(data),
+ headers: { "Content-Type": "application/json" },
+ });
+ };
+
export const deleteUser = async (id: number) => {
return serverFetchWithNoContent(`${BASE_API_URL}/user/${id}`, {
method: "DELETE",
diff --git a/src/app/api/user/index.ts b/src/app/api/user/index.ts
index 9a6065b..3151b64 100644
--- a/src/app/api/user/index.ts
+++ b/src/app/api/user/index.ts
@@ -19,6 +19,7 @@ export interface UserResult {
phone1: string;
phone2: string;
remarks: string;
+ groupId: number;
}
// export interface DetailedUser extends UserResult {
diff --git a/src/components/CreateGroup/AuthorityAllocation.tsx b/src/components/CreateGroup/AuthorityAllocation.tsx
new file mode 100644
index 0000000..fd9610b
--- /dev/null
+++ b/src/components/CreateGroup/AuthorityAllocation.tsx
@@ -0,0 +1,211 @@
+"use client";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
+import {
+ FieldErrors,
+ FormProvider,
+ SubmitErrorHandler,
+ SubmitHandler,
+ useForm,
+ useFormContext,
+} from "react-hook-form";
+import {
+ Box,
+ Card,
+ CardContent,
+ Grid,
+ IconButton,
+ InputAdornment,
+ Stack,
+ Tab,
+ Tabs,
+ TabsProps,
+ TextField,
+ Typography,
+} from "@mui/material";
+import { differenceBy } from "lodash";
+import { CreateGroupInputs, auth } from "@/app/api/group/actions";
+import SearchResults, { Column } from "../SearchResults";
+import { Add, Clear, Remove, Search } from "@mui/icons-material";
+
+export interface Props {
+ auth: auth[];
+}
+
+const AuthorityAllocation: React.FC = ({ auth }) => {
+ const { t } = useTranslation();
+ const {
+ setValue,
+ getValues,
+ formState: { defaultValues },
+ reset,
+ resetField,
+ } = useFormContext();
+ const initialAuths = auth.map((a) => ({ ...a })).sort((a, b) => a.id - b.id);
+ const [filteredAuths, setFilteredAuths] = useState(initialAuths);
+ const [selectedAuths, setSelectedAuths] = useState(
+ () => {
+ return filteredAuths.filter(
+ (s) => getValues("addAuthIds")?.includes(s.id)
+ );
+ }
+ );
+ // Adding / Removing Auth
+ const addAuth = useCallback((auth: auth) => {
+ setSelectedAuths((a) => [...a, auth]);
+ }, []);
+ const removeAuth = useCallback((auth: auth) => {
+ setSelectedAuths((a) => a.filter((a) => a.id !== auth.id));
+ }, []);
+
+ const clearAuth = useCallback(() => {
+ if (defaultValues !== undefined) {
+ resetField("addAuthIds");
+ setSelectedAuths(
+ initialAuths.filter((s) => defaultValues.addAuthIds?.includes(s.id))
+ );
+ }
+ }, [defaultValues]);
+
+ // Sync with form
+ useEffect(() => {
+ setValue(
+ "addAuthIds",
+ selectedAuths.map((a) => a.id)
+ );
+ }, [selectedAuths, setValue]);
+
+ const AuthPoolColumns = useMemo[]>(
+ () => [
+ {
+ label: t("Add"),
+ name: "id",
+ onClick: addAuth,
+ buttonIcon: ,
+ },
+ { label: t("authority"), name: "authority" },
+ { label: t("Auth Name"), name: "name" },
+ // { label: t("Current Position"), name: "currentPosition" },
+ ],
+ [addAuth, t]
+ );
+
+ const allocatedAuthColumns = useMemo[]>(
+ () => [
+ {
+ label: t("Remove"),
+ name: "id",
+ onClick: removeAuth,
+ buttonIcon: ,
+ },
+ { label: t("authority"), name: "authority" },
+ { label: t("Auth Name"), name: "name" },
+ ],
+ [removeAuth, selectedAuths, t]
+ );
+ const [query, setQuery] = React.useState("");
+ const onQueryInputChange = React.useCallback<
+ React.ChangeEventHandler
+ >((e) => {
+ setQuery(e.target.value);
+ }, []);
+ const clearQueryInput = React.useCallback(() => {
+ setQuery("");
+ }, []);
+
+ React.useEffect(() => {
+ // setFilteredStaff(
+ // initialStaffs.filter((s) => {
+ // const q = query.toLowerCase();
+ // // s.staffId.toLowerCase().includes(q)
+ // // const q = query.toLowerCase();
+ // // return s.name.toLowerCase().includes(q);
+ // // s.code.toString().includes(q) ||
+ // // (s.brNo != null && s.brNo.toLowerCase().includes(q))
+ // })
+ // );
+ }, [auth, query]);
+
+ useEffect(() => {
+ // console.log(getValues("addStaffIds"))
+ }, [initialAuths]);
+
+ const resetAuth = React.useCallback(() => {
+ clearQueryInput();
+ clearAuth();
+ }, [clearQueryInput, clearAuth]);
+
+ const formProps = useForm({});
+
+ // Tab related
+ const [tabIndex, setTabIndex] = React.useState(0);
+ const handleTabChange = React.useCallback>(
+ (_e, newValue) => {
+ setTabIndex(newValue);
+ },
+ []
+ );
+
+ return (
+ <>
+
+
+
+
+
+ {t("Authority")}
+
+
+
+
+
+
+
+
+
+ ),
+ }}
+ />
+
+
+
+
+
+
+
+ {tabIndex === 0 && (
+
+ )}
+ {tabIndex === 1 && (
+
+ )}
+
+
+
+
+
+ >
+ );
+};
+
+export default AuthorityAllocation;
diff --git a/src/components/CreateGroup/CreateGroup.tsx b/src/components/CreateGroup/CreateGroup.tsx
new file mode 100644
index 0000000..e931521
--- /dev/null
+++ b/src/components/CreateGroup/CreateGroup.tsx
@@ -0,0 +1,130 @@
+"use client";
+
+import { CreateGroupInputs, auth, saveGroup } from "@/app/api/group/actions";
+import { useRouter } from "next/navigation";
+import { useCallback, useState } from "react";
+import { FieldErrors, FormProvider, SubmitHandler, useForm } from "react-hook-form";
+import { useTranslation } from "react-i18next";
+import { Button, Stack, Tab, Tabs, TabsProps, Typography } from "@mui/material";
+import { Check, Close, Error } from "@mui/icons-material";
+import GroupInfo from "./GroupInfo";
+import AuthorityAllocation from "./AuthorityAllocation";
+import UserAllocation from "./UserAllocation";
+import { UserResult } from "@/app/api/user";
+
+interface Props {
+ auth?: auth[]
+ users?: UserResult[]
+}
+
+const CreateGroup: React.FC = ({ auth, users }) => {
+ const formProps = useForm();
+ const [serverError, setServerError] = useState("");
+ const router = useRouter();
+ const [tabIndex, setTabIndex] = useState(0);
+ const { t } = useTranslation();
+
+ const errors = formProps.formState.errors;
+
+ const onSubmit = useCallback>(
+ async (data) => {
+ try {
+ console.log(data);
+ const postData = {
+ ...data,
+ removeUserIds: [],
+ removeAuthIds: [],
+
+ }
+ console.log(postData)
+ await saveGroup(postData)
+ router.replace("/settings/group")
+ } catch (e) {
+ console.log(e);
+ setServerError(t("An error has occurred. Please try again later."));
+ }
+ },
+ [router]
+ );
+
+ const handleCancel = () => {
+ router.back();
+ };
+
+ const handleTabChange = useCallback>(
+ (_e, newValue) => {
+ setTabIndex(newValue);
+ },
+ []
+ );
+
+ const hasErrorsInTab = (
+ tabIndex: number,
+ errors: FieldErrors,
+ ) => {
+ switch (tabIndex) {
+ case 0:
+ return Object.keys(errors).length > 0;
+ default:
+ false;
+ }
+ };
+
+ return (
+ <>
+
+
+
+
+ ) : undefined
+ }
+ iconPosition="end"
+ />
+
+
+
+ {serverError && (
+
+ {serverError}
+
+ )}
+ {tabIndex === 0 && }
+ {tabIndex === 1 && }
+ {tabIndex === 2 && }
+
+
+ }
+ onClick={handleCancel}
+ >
+ {t("Cancel")}
+
+ }
+ type="submit"
+ // disabled={Boolean(formProps.watch("isGridEditing"))}
+ >
+ {t("Confirm")}
+
+
+
+
+ >
+ );
+};
+
+export default CreateGroup;
diff --git a/src/components/CreateGroup/CreateGroupLoading.tsx b/src/components/CreateGroup/CreateGroupLoading.tsx
new file mode 100644
index 0000000..6a48c4e
--- /dev/null
+++ b/src/components/CreateGroup/CreateGroupLoading.tsx
@@ -0,0 +1,40 @@
+import Card from "@mui/material/Card";
+import CardContent from "@mui/material/CardContent";
+import Skeleton from "@mui/material/Skeleton";
+import Stack from "@mui/material/Stack";
+import React from "react";
+
+// Can make this nicer
+export const CreateGroupLoading: React.FC = () => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+ Create Group
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default CreateGroupLoading;
diff --git a/src/components/CreateGroup/CreateGroupWrapper.tsx b/src/components/CreateGroup/CreateGroupWrapper.tsx
new file mode 100644
index 0000000..e4bd018
--- /dev/null
+++ b/src/components/CreateGroup/CreateGroupWrapper.tsx
@@ -0,0 +1,24 @@
+import React from "react";
+import CreateGroupLoading from "./CreateGroupLoading";
+import { fetchStaff, fetchTeamLeads } from "@/app/api/staff";
+import { useSearchParams } from "next/navigation";
+import CreateGroup from "./CreateGroup";
+import { auth, fetchAuth } from "@/app/api/group/actions";
+import { fetchUser } from "@/app/api/user";
+
+interface SubComponents {
+ Loading: typeof CreateGroupLoading;
+}
+
+const CreateGroupWrapper: React.FC & SubComponents = async () => {
+ const records = await fetchAuth()
+ const users = await fetchUser()
+ console.log(users)
+ const auth = records.records as auth[]
+
+ return ;
+};
+
+CreateGroupWrapper.Loading = CreateGroupLoading;
+
+export default CreateGroupWrapper;
diff --git a/src/components/CreateGroup/GroupInfo.tsx b/src/components/CreateGroup/GroupInfo.tsx
new file mode 100644
index 0000000..d9141bc
--- /dev/null
+++ b/src/components/CreateGroup/GroupInfo.tsx
@@ -0,0 +1,81 @@
+"use client";
+import Stack from "@mui/material/Stack";
+import Box from "@mui/material/Box";
+import Card from "@mui/material/Card";
+import CardContent from "@mui/material/CardContent";
+import Grid from "@mui/material/Grid";
+import TextField from "@mui/material/TextField";
+import Typography from "@mui/material/Typography";
+import { CreateGroupInputs } from "@/app/api/group/actions";
+import { useFormContext } from "react-hook-form";
+import { useTranslation } from "react-i18next";
+import { useCallback } from "react";
+
+const GroupInfo: React.FC = () => {
+ const { t } = useTranslation();
+ const {
+ register,
+ formState: { errors, defaultValues },
+ control,
+ reset,
+ resetField,
+ setValue,
+ } = useFormContext();
+
+
+ const resetGroup = useCallback(() => {
+ console.log(defaultValues);
+ if (defaultValues !== undefined) {
+ resetField("description");
+ }
+ }, [defaultValues]);
+
+
+ return (
+
+
+
+
+ {t("Group Info")}
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default GroupInfo;
diff --git a/src/components/CreateGroup/UserAllocation.tsx b/src/components/CreateGroup/UserAllocation.tsx
new file mode 100644
index 0000000..ff13c52
--- /dev/null
+++ b/src/components/CreateGroup/UserAllocation.tsx
@@ -0,0 +1,209 @@
+"use client";
+import React, { useCallback, useEffect, useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
+import {
+ FieldErrors,
+ FormProvider,
+ SubmitErrorHandler,
+ SubmitHandler,
+ useForm,
+ useFormContext,
+} from "react-hook-form";
+import {
+ Box,
+ Card,
+ CardContent,
+ Grid,
+ IconButton,
+ InputAdornment,
+ Stack,
+ Tab,
+ Tabs,
+ TabsProps,
+ TextField,
+ Typography,
+} from "@mui/material";
+import { differenceBy } from "lodash";
+import { CreateGroupInputs, auth } from "@/app/api/group/actions";
+import SearchResults, { Column } from "../SearchResults";
+import { Add, Clear, Remove, Search } from "@mui/icons-material";
+import { UserResult } from "@/app/api/user";
+
+export interface Props {
+ users: UserResult[];
+}
+
+const UserAllocation: React.FC = ({ users }) => {
+ const { t } = useTranslation();
+ const {
+ setValue,
+ getValues,
+ formState: { defaultValues },
+ reset,
+ resetField,
+ } = useFormContext();
+ const initialUsers = users.map((u) => ({ ...u })).sort((a, b) => a.id - b.id).filter((u) => u.groupId !== null);
+ const [filteredUsers, setFilteredUsers] = useState(initialUsers);
+ const [selectedUsers, setSelectedUsers] = useState(
+ () => {
+ return filteredUsers.filter(
+ (s) => getValues("addUserIds")?.includes(s.id)
+ );
+ }
+ );
+ // Adding / Removing Auth
+ const addUser = useCallback((users: UserResult) => {
+ setSelectedUsers((a) => [...a, users]);
+ }, []);
+
+ const removeUser = useCallback((users: UserResult) => {
+ setSelectedUsers((a) => a.filter((a) => a.id !== users.id));
+ }, []);
+
+ const clearUser = useCallback(() => {
+ if (defaultValues !== undefined) {
+ resetField("addUserIds");
+ setSelectedUsers(
+ initialUsers.filter((s) => defaultValues.addUserIds?.includes(s.id))
+ );
+ }
+ }, [defaultValues]);
+
+ // Sync with form
+ useEffect(() => {
+ setValue(
+ "addUserIds",
+ selectedUsers.map((u) => u.id)
+ );
+ }, [selectedUsers, setValue]);
+
+ const UserPoolColumns = useMemo[]>(
+ () => [
+ {
+ label: t("Add"),
+ name: "id",
+ onClick: addUser,
+ buttonIcon: ,
+ },
+ { label: t("User Name"), name: "username" },
+ { label: t("name"), name: "name" },
+ ],
+ [addUser, t]
+ );
+
+ const allocatedUserColumns = useMemo[]>(
+ () => [
+ {
+ label: t("Remove"),
+ name: "id",
+ onClick: removeUser,
+ buttonIcon: ,
+ },
+ { label: t("User Name"), name: "username" },
+ { label: t("name"), name: "name" },
+ ],
+ [removeUser, selectedUsers, t]
+ );
+
+ const [query, setQuery] = React.useState("");
+ const onQueryInputChange = React.useCallback<
+ React.ChangeEventHandler
+ >((e) => {
+ setQuery(e.target.value);
+ }, []);
+ const clearQueryInput = React.useCallback(() => {
+ setQuery("");
+ }, []);
+
+ React.useEffect(() => {
+ // setFilteredStaff(
+ // initialStaffs.filter((s) => {
+ // const q = query.toLowerCase();
+ // // s.staffId.toLowerCase().includes(q)
+ // // const q = query.toLowerCase();
+ // // return s.name.toLowerCase().includes(q);
+ // // s.code.toString().includes(q) ||
+ // // (s.brNo != null && s.brNo.toLowerCase().includes(q))
+ // })
+ // );
+ }, [users, query]);
+
+ const resetUser = React.useCallback(() => {
+ clearQueryInput();
+ clearUser();
+ }, [clearQueryInput, clearUser]);
+
+ const formProps = useForm({});
+
+ // Tab related
+ const [tabIndex, setTabIndex] = React.useState(0);
+ const handleTabChange = React.useCallback>(
+ (_e, newValue) => {
+ setTabIndex(newValue);
+ },
+ []
+ );
+
+ return (
+ <>
+
+
+
+
+
+ {t("User")}
+
+
+
+
+
+
+
+
+
+ ),
+ }}
+ />
+
+
+
+
+
+
+
+ {tabIndex === 0 && (
+
+ )}
+ {tabIndex === 1 && (
+
+ )}
+
+
+
+
+
+ >
+ );
+};
+
+export default UserAllocation;
diff --git a/src/components/CreateGroup/index.ts b/src/components/CreateGroup/index.ts
new file mode 100644
index 0000000..1034fc8
--- /dev/null
+++ b/src/components/CreateGroup/index.ts
@@ -0,0 +1 @@
+export { default } from "./CreateGroupWrapper"
\ No newline at end of file
diff --git a/src/components/CreateTeam/TeamInfo.tsx b/src/components/CreateTeam/TeamInfo.tsx
index 4e61f4b..cd8b90a 100644
--- a/src/components/CreateTeam/TeamInfo.tsx
+++ b/src/components/CreateTeam/TeamInfo.tsx
@@ -27,7 +27,7 @@ const TeamInfo: React.FC = (
setValue,
} = useFormContext();
- const resetCustomer = useCallback(() => {
+ const resetTeam = useCallback(() => {
console.log(defaultValues);
if (defaultValues !== undefined) {
resetField("description");
diff --git a/src/components/EditTeam/Allocation.tsx b/src/components/EditTeam/Allocation.tsx
index 2599867..61e9e8f 100644
--- a/src/components/EditTeam/Allocation.tsx
+++ b/src/components/EditTeam/Allocation.tsx
@@ -49,7 +49,7 @@ const Allocation: React.FC = ({ allStaffs: staff, teamLead }) => {
reset,
resetField,
} = useFormContext();
-
+
// let firstFilter: StaffResult[] = []
const initialStaffs = staff.map((s) => ({ ...s }));
@@ -63,7 +63,6 @@ const Allocation: React.FC = ({ allStaffs: staff, teamLead }) => {
return rearrangedStaff.filter((s) => getValues("addStaffIds")?.includes(s.id))
}
);
- console.log(filteredStaff.filter((s) => getValues("addStaffIds")?.includes(s.id)))
const [seletedTeamLead, setSeletedTeamLead] = useState();
const [deletedStaffIds, setDeletedStaffIds] = useState([]);
diff --git a/src/components/NavigationContent/NavigationContent.tsx b/src/components/NavigationContent/NavigationContent.tsx
index 233f228..226482e 100644
--- a/src/components/NavigationContent/NavigationContent.tsx
+++ b/src/components/NavigationContent/NavigationContent.tsx
@@ -143,6 +143,7 @@ const NavigationContent: React.FC = ({ abilities }) => {
{ 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" },
{ icon: , label: "Holiday", path: "/settings/holiday" },
],
},
diff --git a/src/components/UserGroupSearch/UserGroupSearch.tsx b/src/components/UserGroupSearch/UserGroupSearch.tsx
new file mode 100644
index 0000000..0480167
--- /dev/null
+++ b/src/components/UserGroupSearch/UserGroupSearch.tsx
@@ -0,0 +1,94 @@
+"use client";
+
+import SearchBox, { Criterion } from "../SearchBox";
+import { useCallback, useMemo, useState } from "react";
+import { useTranslation } from "react-i18next";
+import SearchResults, { Column } from "../SearchResults/index";
+import EditNote from "@mui/icons-material/EditNote";
+import DeleteIcon from "@mui/icons-material/Delete";
+import { useRouter } from "next/navigation";
+import { deleteDialog, successDialog } from "../Swal/CustomAlerts";
+import { UserGroupResult } from "@/app/api/group";
+import { deleteUser } from "@/app/api/user/actions";
+
+interface Props {
+ users: UserGroupResult[];
+}
+type SearchQuery = Partial>;
+type SearchParamNames = keyof SearchQuery;
+
+const UserGroupSearch: React.FC = ({ users }) => {
+ const { t } = useTranslation();
+ const [filteredUser, setFilteredUser] = useState(users);
+ const router = useRouter();
+
+ const searchCriteria: Criterion[] = useMemo(
+ () => [
+ {
+ label: t("User Name"),
+ paramName: "name",
+ type: "text",
+ },
+ ],
+ [t]
+ );
+
+ const onUserClick = useCallback(
+ (users: UserGroupResult) => {
+ console.log(users);
+ // router.push(`/settings/user/edit?id=${users.id}`)
+ },
+ [router, t]
+ );
+
+ const onDeleteClick = useCallback((users: UserGroupResult) => {
+ deleteDialog(async () => {
+ await deleteUser(users.id);
+
+ successDialog(t("Delete Success"), t);
+
+ setFilteredUser((prev) => prev.filter((obj) => obj.id !== users.id));
+ }, t);
+ }, []);
+
+ const columns = useMemo[]>(
+ () => [
+ {
+ name: "action",
+ label: t("Edit"),
+ onClick: onUserClick,
+ buttonIcon: ,
+ },
+ { name: "name", label: t("Group Name") },
+ { name: "description", label: t("Description") },
+ {
+ name: "action",
+ label: t("Delete"),
+ onClick: onDeleteClick,
+ buttonIcon: ,
+ color: "error"
+ },
+ ],
+ [t]
+ );
+
+ return (
+ <>
+ {
+ // setFilteredUser(
+ // users.filter(
+ // (t) =>
+ // t.name.toLowerCase().includes(query.name.toLowerCase()) &&
+ // t.code.toLowerCase().includes(query.code.toLowerCase()) &&
+ // t.description.toLowerCase().includes(query.description.toLowerCase())
+ // )
+ // )
+ }}
+ />
+ items={filteredUser} columns={columns} />
+ >
+ );
+};
+export default UserGroupSearch;
diff --git a/src/components/UserGroupSearch/UserGroupSearchLoading.tsx b/src/components/UserGroupSearch/UserGroupSearchLoading.tsx
new file mode 100644
index 0000000..5d8df0f
--- /dev/null
+++ b/src/components/UserGroupSearch/UserGroupSearchLoading.tsx
@@ -0,0 +1,40 @@
+import Card from "@mui/material/Card";
+import CardContent from "@mui/material/CardContent";
+import Skeleton from "@mui/material/Skeleton";
+import Stack from "@mui/material/Stack";
+import React from "react";
+
+// Can make this nicer
+export const UserGroupSearchLoading: React.FC = () => {
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
+export default UserGroupSearchLoading;
diff --git a/src/components/UserGroupSearch/UserGroupSearchWrapper.tsx b/src/components/UserGroupSearch/UserGroupSearchWrapper.tsx
new file mode 100644
index 0000000..9f792ed
--- /dev/null
+++ b/src/components/UserGroupSearch/UserGroupSearchWrapper.tsx
@@ -0,0 +1,19 @@
+import React from "react";
+import UserGroupSearchLoading from "./UserGroupSearchLoading";
+import { UserGroupResult, fetchGroup } from "@/app/api/group";
+import UserGroupSearch from "./UserGroupSearch";
+
+interface SubComponents {
+ Loading: typeof UserGroupSearchLoading;
+}
+
+const UserGroupSearchWrapper: React.FC & SubComponents = async () => {
+const group = await fetchGroup()
+ console.log(group.records);
+
+ return ;
+};
+
+UserGroupSearchWrapper.Loading = UserGroupSearchLoading;
+
+export default UserGroupSearchWrapper;
diff --git a/src/components/UserGroupSearch/index.ts b/src/components/UserGroupSearch/index.ts
new file mode 100644
index 0000000..f2e5e63
--- /dev/null
+++ b/src/components/UserGroupSearch/index.ts
@@ -0,0 +1 @@
+export { default } from "./UserGroupSearchWrapper";