| @@ -60,24 +60,20 @@ const Allocation: React.FC<Props> = ({ allStaffs: staff, teamLead }) => { | |||||
| return rearrangedStaff.filter((s) => getValues("addStaffIds")?.includes(s.id)) | return rearrangedStaff.filter((s) => getValues("addStaffIds")?.includes(s.id)) | ||||
| } | } | ||||
| ); | ); | ||||
| const [seletedTeamLead, setSeletedTeamLead] = useState<number>(); | |||||
| const [deletedStaffIds, setDeletedStaffIds] = useState<number[]>([]); | const [deletedStaffIds, setDeletedStaffIds] = useState<number[]>([]); | ||||
| // Adding / Removing staff | // Adding / Removing staff | ||||
| const addStaff = useCallback((staff: StaffResult) => { | const addStaff = useCallback((staff: StaffResult) => { | ||||
| setSelectedStaff((s) => [...s, staff]); | setSelectedStaff((s) => [...s, staff]); | ||||
| // setDeletedStaffIds((s) => s.filter((s) => s === selectedStaff.id)) | |||||
| }, []); | }, []); | ||||
| const removeStaff = useCallback((staff: StaffResult) => { | const removeStaff = useCallback((staff: StaffResult) => { | ||||
| setSelectedStaff((s) => s.filter((s) => s.id !== staff.id)); | setSelectedStaff((s) => s.filter((s) => s.id !== staff.id)); | ||||
| // setDeletedStaffIds((s) => s) | |||||
| setDeletedStaffIds((prevIds) => [...prevIds, staff.id]); | setDeletedStaffIds((prevIds) => [...prevIds, staff.id]); | ||||
| }, []); | }, []); | ||||
| const setTeamLead = useCallback( | const setTeamLead = useCallback( | ||||
| (staff: StaffResult) => { | (staff: StaffResult) => { | ||||
| setSeletedTeamLead(staff.id); | |||||
| const rearrangedList = getValues("addStaffIds").reduce<number[]>( | const rearrangedList = getValues("addStaffIds").reduce<number[]>( | ||||
| (acc, num, index) => { | (acc, num, index) => { | ||||
| if (num === staff.id && index !== 0) { | if (num === staff.id && index !== 0) { | ||||
| @@ -171,16 +167,16 @@ const Allocation: React.FC<Props> = ({ allStaffs: staff, teamLead }) => { | |||||
| }, []); | }, []); | ||||
| React.useEffect(() => { | 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)) | |||||
| // }) | |||||
| // ); | |||||
| setFilteredStaff( | |||||
| initialStaffs.filter((i) => { | |||||
| const q = query.toLowerCase(); | |||||
| return ( | |||||
| i.staffId.toLowerCase().includes(q) || | |||||
| i.name.toLowerCase().includes(q) || | |||||
| i.currentPosition.toLowerCase().includes(q) | |||||
| ); | |||||
| }) | |||||
| ); | |||||
| }, [staff, query]); | }, [staff, query]); | ||||
| useEffect(() => { | useEffect(() => { | ||||
| @@ -1,93 +1,97 @@ | |||||
| "use client"; | "use client"; | ||||
| import React, { useCallback, useEffect, useMemo, useState } from "react"; | import React, { useCallback, useEffect, useMemo, useState } from "react"; | ||||
| import { useRouter, useSearchParams } from "next/navigation"; | import { useRouter, useSearchParams } from "next/navigation"; | ||||
| import { Add, Clear, PersonAdd, PersonRemove, Remove, Search } from "@mui/icons-material"; | |||||
| import { | |||||
| Add, | |||||
| Clear, | |||||
| PersonAdd, | |||||
| PersonRemove, | |||||
| Remove, | |||||
| Search, | |||||
| } from "@mui/icons-material"; | |||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { | import { | ||||
| FieldErrors, | |||||
| FormProvider, | |||||
| SubmitErrorHandler, | |||||
| SubmitHandler, | |||||
| useForm, | |||||
| useFormContext, | |||||
| } from "react-hook-form"; | |||||
| FieldErrors, | |||||
| FormProvider, | |||||
| SubmitErrorHandler, | |||||
| SubmitHandler, | |||||
| useForm, | |||||
| useFormContext, | |||||
| } from "react-hook-form"; | |||||
| import { | import { | ||||
| Box, | |||||
| Card, | |||||
| CardContent, | |||||
| Grid, | |||||
| IconButton, | |||||
| InputAdornment, | |||||
| Stack, | |||||
| Tab, | |||||
| Tabs, | |||||
| TabsProps, | |||||
| TextField, | |||||
| Typography, | |||||
| } from "@mui/material"; | |||||
| import { differenceBy } from "lodash"; | |||||
| Box, | |||||
| Card, | |||||
| CardContent, | |||||
| Grid, | |||||
| IconButton, | |||||
| InputAdornment, | |||||
| Stack, | |||||
| Tab, | |||||
| Tabs, | |||||
| TabsProps, | |||||
| TextField, | |||||
| Typography, | |||||
| } from "@mui/material"; | |||||
| import { differenceBy } from "lodash"; | |||||
| import { UserInputs } from "@/app/api/user/actions"; | import { UserInputs } from "@/app/api/user/actions"; | ||||
| import { auth } from "@/app/api/group/actions"; | import { auth } from "@/app/api/group/actions"; | ||||
| import SearchResults, { Column } from "../SearchResults"; | import SearchResults, { Column } from "../SearchResults"; | ||||
| export interface Props { | export interface Props { | ||||
| auths: auth[] | |||||
| } | |||||
| auths: auth[]; | |||||
| } | |||||
| const AuthAllocation: React.FC<Props> = ({ auths }) => { | const AuthAllocation: React.FC<Props> = ({ auths }) => { | ||||
| const { t } = useTranslation(); | |||||
| const searchParams = useSearchParams(); | |||||
| const id = parseInt(searchParams.get("id") || "0"); | |||||
| const { | |||||
| setValue, | |||||
| getValues, | |||||
| formState: { defaultValues }, | |||||
| reset, | |||||
| resetField, | |||||
| } = useFormContext<UserInputs>(); | |||||
| const initialAuths = auths.map((u) => ({ ...u })).sort((a, b) => a.id - b.id); | |||||
| const [filteredAuths, setFilteredAuths] = useState(initialAuths); | |||||
| const [selectedAuths, setSelectedAuths] = useState<typeof filteredAuths>( | |||||
| () => { | |||||
| return filteredAuths.filter( | |||||
| (s) => getValues("addAuthIds")?.includes(s.id) | |||||
| ); | |||||
| } | |||||
| const { t } = useTranslation(); | |||||
| const searchParams = useSearchParams(); | |||||
| const id = parseInt(searchParams.get("id") || "0"); | |||||
| const { | |||||
| setValue, | |||||
| getValues, | |||||
| formState: { defaultValues }, | |||||
| reset, | |||||
| resetField, | |||||
| } = useFormContext<UserInputs>(); | |||||
| const initialAuths = auths.map((u) => ({ ...u })).sort((a, b) => a.id - b.id); | |||||
| const [filteredAuths, setFilteredAuths] = useState(initialAuths); | |||||
| const [selectedAuths, setSelectedAuths] = useState<typeof filteredAuths>( | |||||
| () => { | |||||
| return filteredAuths.filter( | |||||
| (s) => getValues("addAuthIds")?.includes(s.id) | |||||
| ); | ); | ||||
| const [removeAuthIds, setRemoveAuthIds] = useState<number[]>([]); | |||||
| } | |||||
| ); | |||||
| const [removeAuthIds, setRemoveAuthIds] = useState<number[]>([]); | |||||
| // 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)); | |||||
| setRemoveAuthIds((prevIds) => [...prevIds, auth.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)); | |||||
| setRemoveAuthIds((prevIds) => [...prevIds, auth.id]); | |||||
| }, []); | |||||
| const clearAuth = useCallback(() => { | |||||
| if (defaultValues !== undefined) { | |||||
| resetField("addAuthIds"); | |||||
| setSelectedAuths( | |||||
| initialAuths.filter((auth) => defaultValues.addAuthIds?.includes(auth.id)) | |||||
| ); | |||||
| } | |||||
| }, [defaultValues]); | |||||
| const clearAuth = useCallback(() => { | |||||
| if (defaultValues !== undefined) { | |||||
| resetField("addAuthIds"); | |||||
| setSelectedAuths( | |||||
| initialAuths.filter( | |||||
| (auth) => defaultValues.addAuthIds?.includes(auth.id) | |||||
| ) | |||||
| ); | |||||
| } | |||||
| }, [defaultValues]); | |||||
| // Sync with form | |||||
| // Sync with form | |||||
| useEffect(() => { | useEffect(() => { | ||||
| setValue( | setValue( | ||||
| "addAuthIds", | "addAuthIds", | ||||
| selectedAuths.map((a) => a.id) | selectedAuths.map((a) => a.id) | ||||
| ); | ); | ||||
| setValue( | |||||
| "removeAuthIds", | |||||
| removeAuthIds | |||||
| ); | |||||
| setValue("removeAuthIds", removeAuthIds); | |||||
| }, [selectedAuths, removeAuthIds, setValue]); | }, [selectedAuths, removeAuthIds, setValue]); | ||||
| const AuthPoolColumns = useMemo<Column<auth>[]>( | const AuthPoolColumns = useMemo<Column<auth>[]>( | ||||
| () => [ | () => [ | ||||
| { | { | ||||
| @@ -97,8 +101,7 @@ const AuthAllocation: React.FC<Props> = ({ auths }) => { | |||||
| buttonIcon: <Add />, | buttonIcon: <Add />, | ||||
| }, | }, | ||||
| { label: t("authority"), name: "authority" }, | { label: t("authority"), name: "authority" }, | ||||
| { label: t("Auth Name"), name: "name" }, | |||||
| // { label: t("Current Position"), name: "currentPosition" }, | |||||
| { label: t("description"), name: "name" }, | |||||
| ], | ], | ||||
| [addAuth, t] | [addAuth, t] | ||||
| ); | ); | ||||
| @@ -109,10 +112,10 @@ const AuthAllocation: React.FC<Props> = ({ auths }) => { | |||||
| label: t("Remove"), | label: t("Remove"), | ||||
| name: "id", | name: "id", | ||||
| onClick: removeAuth, | onClick: removeAuth, | ||||
| buttonIcon: <Remove color="warning"/>, | |||||
| buttonIcon: <Remove color="warning" />, | |||||
| }, | }, | ||||
| { label: t("authority"), name: "authority" }, | { label: t("authority"), name: "authority" }, | ||||
| { label: t("Auth Name"), name: "name" }, | |||||
| { label: t("description"), name: "name" }, | |||||
| ], | ], | ||||
| [removeAuth, selectedAuths, t] | [removeAuth, selectedAuths, t] | ||||
| ); | ); | ||||
| @@ -128,16 +131,14 @@ const AuthAllocation: React.FC<Props> = ({ auths }) => { | |||||
| }, []); | }, []); | ||||
| React.useEffect(() => { | 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)) | |||||
| // }) | |||||
| // ); | |||||
| setFilteredAuths( | |||||
| initialAuths.filter((a) => | |||||
| ( | |||||
| a.authority.toLowerCase().includes(query.toLowerCase()) || | |||||
| a.name?.toLowerCase().includes(query.toLowerCase()) | |||||
| ) | |||||
| ) | |||||
| ); | |||||
| }, [auths, query]); | }, [auths, query]); | ||||
| const resetAuth = React.useCallback(() => { | const resetAuth = React.useCallback(() => { | ||||
| @@ -147,16 +148,16 @@ const AuthAllocation: React.FC<Props> = ({ auths }) => { | |||||
| const formProps = useForm({}); | const formProps = useForm({}); | ||||
| // Tab related | |||||
| const [tabIndex, setTabIndex] = React.useState(0); | |||||
| const handleTabChange = React.useCallback<NonNullable<TabsProps["onChange"]>>( | |||||
| (_e, newValue) => { | |||||
| setTabIndex(newValue); | |||||
| }, | |||||
| [] | |||||
| ); | |||||
| // Tab related | |||||
| const [tabIndex, setTabIndex] = React.useState(0); | |||||
| const handleTabChange = React.useCallback<NonNullable<TabsProps["onChange"]>>( | |||||
| (_e, newValue) => { | |||||
| setTabIndex(newValue); | |||||
| }, | |||||
| [] | |||||
| ); | |||||
| return ( | |||||
| return ( | |||||
| <> | <> | ||||
| <FormProvider {...formProps}> | <FormProvider {...formProps}> | ||||
| <Card sx={{ display: "block" }}> | <Card sx={{ display: "block" }}> | ||||
| @@ -175,7 +176,9 @@ return ( | |||||
| fullWidth | fullWidth | ||||
| onChange={onQueryInputChange} | onChange={onQueryInputChange} | ||||
| value={query} | value={query} | ||||
| placeholder={t("Search by staff ID, name or position.")} | |||||
| placeholder={t( | |||||
| "Search by Authority or description or position." | |||||
| )} | |||||
| InputProps={{ | InputProps={{ | ||||
| endAdornment: query && ( | endAdornment: query && ( | ||||
| <InputAdornment position="end"> | <InputAdornment position="end"> | ||||
| @@ -191,18 +194,20 @@ return ( | |||||
| <Tabs value={tabIndex} onChange={handleTabChange}> | <Tabs value={tabIndex} onChange={handleTabChange}> | ||||
| <Tab label={t("Authority Pool")} /> | <Tab label={t("Authority Pool")} /> | ||||
| <Tab | <Tab | ||||
| label={`${t("Allocated Authority")} (${selectedAuths.length})`} | |||||
| label={`${t("Allocated Authority")} (${ | |||||
| selectedAuths.length | |||||
| })`} | |||||
| /> | /> | ||||
| </Tabs> | </Tabs> | ||||
| <Box sx={{ marginInline: -3 }}> | <Box sx={{ marginInline: -3 }}> | ||||
| {tabIndex === 0 && ( | |||||
| {tabIndex === 0 && ( | |||||
| <SearchResults | <SearchResults | ||||
| noWrapper | noWrapper | ||||
| items={differenceBy(filteredAuths, selectedAuths, "id")} | items={differenceBy(filteredAuths, selectedAuths, "id")} | ||||
| columns={AuthPoolColumns} | columns={AuthPoolColumns} | ||||
| /> | /> | ||||
| )} | )} | ||||
| {tabIndex === 1 && ( | |||||
| {tabIndex === 1 && ( | |||||
| <SearchResults | <SearchResults | ||||
| noWrapper | noWrapper | ||||
| items={selectedAuths} | items={selectedAuths} | ||||
| @@ -216,6 +221,5 @@ return ( | |||||
| </FormProvider> | </FormProvider> | ||||
| </> | </> | ||||
| ); | ); | ||||
| } | |||||
| export default AuthAllocation | |||||
| }; | |||||
| export default AuthAllocation; | |||||
| @@ -1,6 +1,12 @@ | |||||
| "use client"; | "use client"; | ||||
| import { useRouter, useSearchParams } from "next/navigation"; | import { useRouter, useSearchParams } from "next/navigation"; | ||||
| import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react"; | |||||
| import React, { | |||||
| useCallback, | |||||
| useEffect, | |||||
| useLayoutEffect, | |||||
| useMemo, | |||||
| useState, | |||||
| } from "react"; | |||||
| import SearchResults, { Column } from "../SearchResults"; | import SearchResults, { Column } from "../SearchResults"; | ||||
| // import { TeamResult } from "@/app/api/team"; | // import { TeamResult } from "@/app/api/team"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| @@ -26,23 +32,24 @@ import { | |||||
| } from "react-hook-form"; | } from "react-hook-form"; | ||||
| import { Check, Close, Error, RestartAlt } from "@mui/icons-material"; | import { Check, Close, Error, RestartAlt } from "@mui/icons-material"; | ||||
| import { StaffResult } from "@/app/api/staff"; | import { StaffResult } from "@/app/api/staff"; | ||||
| import { UserInputs, adminChangePassword, editUser, fetchUserDetails } from "@/app/api/user/actions"; | |||||
| import { | |||||
| UserInputs, | |||||
| adminChangePassword, | |||||
| editUser, | |||||
| fetchUserDetails, | |||||
| } from "@/app/api/user/actions"; | |||||
| import UserDetail from "./UserDetail"; | import UserDetail from "./UserDetail"; | ||||
| import { UserResult, passwordRule } from "@/app/api/user"; | import { UserResult, passwordRule } from "@/app/api/user"; | ||||
| import { auth, fetchAuth } from "@/app/api/group/actions"; | import { auth, fetchAuth } from "@/app/api/group/actions"; | ||||
| import AuthAllocation from "./AuthAllocation"; | import AuthAllocation from "./AuthAllocation"; | ||||
| interface Props { | interface Props { | ||||
| user: UserResult, | |||||
| rules: passwordRule, | |||||
| auths: auth[] | |||||
| } | |||||
| user: UserResult; | |||||
| rules: passwordRule; | |||||
| auths: auth[]; | |||||
| } | |||||
| const EditUser: React.FC<Props> = async ({ | |||||
| user, | |||||
| rules, | |||||
| auths | |||||
| }) => { | |||||
| const EditUser: React.FC<Props> = async ({ user, rules, auths }) => { | |||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const formProps = useForm<UserInputs>(); | const formProps = useForm<UserInputs>(); | ||||
| const searchParams = useSearchParams(); | const searchParams = useSearchParams(); | ||||
| @@ -50,6 +57,13 @@ const EditUser: React.FC<Props> = async ({ | |||||
| const [tabIndex, setTabIndex] = useState(0); | const [tabIndex, setTabIndex] = useState(0); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const [serverError, setServerError] = useState(""); | const [serverError, setServerError] = useState(""); | ||||
| const addAuthIds = | |||||
| auths && auths.length > 0 | |||||
| ? auths | |||||
| .filter((item) => item.v === 1) | |||||
| .map((item) => item.id) | |||||
| .sort((a, b) => a - b) | |||||
| : []; | |||||
| const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>( | const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>( | ||||
| (_e, newValue) => { | (_e, newValue) => { | ||||
| @@ -60,22 +74,27 @@ const EditUser: React.FC<Props> = async ({ | |||||
| const errors = formProps.formState.errors; | const errors = formProps.formState.errors; | ||||
| useEffect(() => { | |||||
| const resetForm = React.useCallback(() => { | |||||
| console.log("triggerred"); | |||||
| console.log(addAuthIds); | |||||
| try { | try { | ||||
| const addAuthIds = auths && auths.length > 0 | |||||
| ? auths.filter((item) => item.v === 1).map((item) => item.id).sort((a, b) => a - b) | |||||
| : [] | |||||
| formProps.reset({ | formProps.reset({ | ||||
| name: user.username, | name: user.username, | ||||
| email: user.email, | email: user.email, | ||||
| addAuthIds: addAuthIds | |||||
| addAuthIds: addAuthIds, | |||||
| removeAuthIds: [], | |||||
| password: "", | |||||
| }); | }); | ||||
| console.log(formProps.formState.defaultValues); | |||||
| } catch (error) { | } catch (error) { | ||||
| console.log(error); | console.log(error); | ||||
| setServerError(t("An error has occurred. Please try again later.")); | setServerError(t("An error has occurred. Please try again later.")); | ||||
| } | } | ||||
| }, [user, auths]); | |||||
| }, [auths, user]); | |||||
| useEffect(() => { | |||||
| resetForm(); | |||||
| }, []); | |||||
| const hasErrorsInTab = ( | const hasErrorsInTab = ( | ||||
| tabIndex: number, | tabIndex: number, | ||||
| @@ -96,22 +115,33 @@ const EditUser: React.FC<Props> = async ({ | |||||
| const onSubmit = useCallback<SubmitHandler<UserInputs>>( | const onSubmit = useCallback<SubmitHandler<UserInputs>>( | ||||
| async (data) => { | async (data) => { | ||||
| try { | try { | ||||
| let haveError = false | |||||
| let regex_pw = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,20}$/ | |||||
| let pw = '' | |||||
| let haveError = false; | |||||
| let regex_pw = | |||||
| /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,20}$/; | |||||
| let pw = ""; | |||||
| if (data.password && data.password.length > 0) { | if (data.password && data.password.length > 0) { | ||||
| pw = data.password | |||||
| pw = data.password; | |||||
| if (pw.length < rules.min) { | if (pw.length < rules.min) { | ||||
| haveError = true | |||||
| formProps.setError("password", { message: t("The password requires 8-20 characters."), type: "required" }) | |||||
| haveError = true; | |||||
| formProps.setError("password", { | |||||
| message: t("The password requires 8-20 characters."), | |||||
| type: "required", | |||||
| }); | |||||
| } | } | ||||
| if (pw.length > rules.max) { | if (pw.length > rules.max) { | ||||
| haveError = true | |||||
| formProps.setError("password", { message: t("The password requires 8-20 characters."), type: "required" }) | |||||
| haveError = true; | |||||
| formProps.setError("password", { | |||||
| message: t("The password requires 8-20 characters."), | |||||
| type: "required", | |||||
| }); | |||||
| } | } | ||||
| if (!regex_pw.test(pw)) { | if (!regex_pw.test(pw)) { | ||||
| haveError = true | |||||
| formProps.setError("password", { message: "A combination of uppercase letters, lowercase letters, numbers, and symbols is required.", type: "required" }) | |||||
| haveError = true; | |||||
| formProps.setError("password", { | |||||
| message: | |||||
| "A combination of uppercase letters, lowercase letters, numbers, and symbols is required.", | |||||
| type: "required", | |||||
| }); | |||||
| } | } | ||||
| } | } | ||||
| const userData = { | const userData = { | ||||
| @@ -119,16 +149,16 @@ const EditUser: React.FC<Props> = async ({ | |||||
| locked: false, | locked: false, | ||||
| addAuthIds: data.addAuthIds || [], | addAuthIds: data.addAuthIds || [], | ||||
| removeAuthIds: data.removeAuthIds || [], | removeAuthIds: data.removeAuthIds || [], | ||||
| } | |||||
| }; | |||||
| const pwData = { | const pwData = { | ||||
| id: id, | id: id, | ||||
| password: "", | password: "", | ||||
| newPassword: pw | |||||
| } | |||||
| newPassword: pw, | |||||
| }; | |||||
| if (haveError) { | if (haveError) { | ||||
| return | |||||
| return; | |||||
| } | } | ||||
| console.log("passed") | |||||
| console.log("passed"); | |||||
| await editUser(id, userData); | await editUser(id, userData); | ||||
| if (data.password && data.password.length > 0) { | if (data.password && data.password.length > 0) { | ||||
| await adminChangePassword(pwData); | await adminChangePassword(pwData); | ||||
| @@ -185,12 +215,12 @@ const EditUser: React.FC<Props> = async ({ | |||||
| </Tabs> | </Tabs> | ||||
| </Stack> | </Stack> | ||||
| {tabIndex == 0 && <UserDetail />} | {tabIndex == 0 && <UserDetail />} | ||||
| {tabIndex === 1 && <AuthAllocation auths={auths!}/>} | |||||
| {tabIndex === 1 && <AuthAllocation auths={auths!} />} | |||||
| <Stack direction="row" justifyContent="flex-end" gap={1}> | <Stack direction="row" justifyContent="flex-end" gap={1}> | ||||
| <Button | <Button | ||||
| variant="text" | variant="text" | ||||
| startIcon={<RestartAlt />} | startIcon={<RestartAlt />} | ||||
| // onClick={() => console.log("asdasd")} | |||||
| onClick={resetForm} | |||||
| > | > | ||||
| {t("Reset")} | {t("Reset")} | ||||
| </Button> | </Button> | ||||
| @@ -9,13 +9,13 @@ import { | |||||
| Stack, | Stack, | ||||
| TextField, | TextField, | ||||
| Typography, | Typography, | ||||
| makeStyles, | |||||
| } from "@mui/material"; | } from "@mui/material"; | ||||
| import { useFormContext } from "react-hook-form"; | import { useFormContext } from "react-hook-form"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| const UserDetail: React.FC = () => { | const UserDetail: React.FC = () => { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { | const { | ||||
| register, | register, | ||||
| @@ -45,6 +45,30 @@ const UserDetail: React.FC = () => { | |||||
| label={t("password")} | label={t("password")} | ||||
| fullWidth | fullWidth | ||||
| {...register("password")} | {...register("password")} | ||||
| // helperText={ | |||||
| // Boolean(errors.password) && | |||||
| // (errors.password?.message | |||||
| // ? t(errors.password.message) | |||||
| // : | |||||
| // (<> | |||||
| // - 8-20 characters | |||||
| // <br/> | |||||
| // - Uppercase letters | |||||
| // <br/> | |||||
| // - Lowercase letters | |||||
| // <br/> | |||||
| // - Numbers | |||||
| // <br/> | |||||
| // - Symbols | |||||
| // </>) | |||||
| // ) | |||||
| // } | |||||
| helperText={ | |||||
| Boolean(errors.password) && | |||||
| (errors.password?.message | |||||
| ? t(errors.password.message) | |||||
| : t("Please input correct password")) | |||||
| } | |||||
| error={Boolean(errors.password)} | error={Boolean(errors.password)} | ||||
| /> | /> | ||||
| </Grid> | </Grid> | ||||
| @@ -55,3 +79,16 @@ const UserDetail: React.FC = () => { | |||||
| }; | }; | ||||
| export default UserDetail; | export default UserDetail; | ||||
| {/* <> | |||||
| - 8-20 characters | |||||
| <br/> | |||||
| - Uppercase letters | |||||
| <br/> | |||||
| - Lowercase letters | |||||
| <br/> | |||||
| - Numbers | |||||
| <br/> | |||||
| - Symbols | |||||
| </> */} | |||||