You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

203 line
5.5 KiB

  1. "use client";
  2. import { useRouter, useSearchParams } from "next/navigation";
  3. import { useCallback, useEffect, useLayoutEffect, useMemo, useState } from "react";
  4. import SearchResults, { Column } from "../SearchResults";
  5. // import { TeamResult } from "@/app/api/team";
  6. import { useTranslation } from "react-i18next";
  7. import {
  8. Button,
  9. Card,
  10. CardContent,
  11. Grid,
  12. Stack,
  13. Tab,
  14. Tabs,
  15. TabsProps,
  16. TextField,
  17. Typography,
  18. } from "@mui/material";
  19. import {
  20. FieldErrors,
  21. FormProvider,
  22. SubmitErrorHandler,
  23. SubmitHandler,
  24. useForm,
  25. useFormContext,
  26. } from "react-hook-form";
  27. import { Check, Close, Error, RestartAlt } from "@mui/icons-material";
  28. import { StaffResult } from "@/app/api/staff";
  29. import { UserInputs, editUser, fetchUserDetails } from "@/app/api/user/actions";
  30. import UserDetail from "./UserDetail";
  31. import { UserResult } from "@/app/api/user";
  32. import { auth, fetchAuth } from "@/app/api/group/actions";
  33. import AuthAllocation from "./AuthAllocation";
  34. interface Props {
  35. // users: UserResult[]
  36. }
  37. const EditUser: React.FC<Props> = async ({ }) => {
  38. const { t } = useTranslation();
  39. const formProps = useForm<UserInputs>();
  40. const searchParams = useSearchParams();
  41. const id = parseInt(searchParams.get("id") || "0");
  42. const [tabIndex, setTabIndex] = useState(0);
  43. const router = useRouter();
  44. const [serverError, setServerError] = useState("");
  45. const [data, setData] = useState<UserResult>();
  46. const [auths, setAuths] = useState<auth[]>();
  47. const handleTabChange = useCallback<NonNullable<TabsProps["onChange"]>>(
  48. (_e, newValue) => {
  49. setTabIndex(newValue);
  50. },
  51. []
  52. );
  53. const errors = formProps.formState.errors;
  54. const fetchUserDetail = async () => {
  55. console.log(id);
  56. try {
  57. // fetch user info
  58. const userDetail = await fetchUserDetails(id);
  59. console.log(userDetail);
  60. const _data = userDetail.data as UserResult;
  61. console.log(_data);
  62. setData(_data);
  63. //fetch user auths
  64. const authDetail = await fetchAuth("user", id);
  65. setAuths(authDetail.records)
  66. const addAuthIds = authDetail.records.filter((item) => item.v === 1).map((item) => item.id).sort((a, b) => a - b);
  67. formProps.reset({
  68. name: _data.username,
  69. email: _data.email,
  70. addAuthIds: addAuthIds || []
  71. });
  72. } catch (error) {
  73. console.log(error);
  74. setServerError(t("An error has occurred. Please try again later."));
  75. }
  76. }
  77. useEffect(() => {
  78. fetchUserDetail();
  79. }, []);
  80. // useEffect(() => {
  81. // const thisUser = users.filter((item) => item.id === id)
  82. // formProps.reset({
  83. // username: thisUser[0].username,
  84. // email: thisUser[0].email,
  85. // });
  86. // }, []);
  87. const hasErrorsInTab = (
  88. tabIndex: number,
  89. errors: FieldErrors<UserResult>
  90. ) => {
  91. switch (tabIndex) {
  92. case 0:
  93. return Object.keys(errors).length > 0;
  94. default:
  95. false;
  96. }
  97. };
  98. const handleCancel = () => {
  99. router.back();
  100. };
  101. const onSubmit = useCallback<SubmitHandler<UserInputs>>(
  102. async (data) => {
  103. try {
  104. console.log(data);
  105. const tempData = {
  106. name: data.name,
  107. email: data.email,
  108. locked: false,
  109. addAuthIds: data.addAuthIds || [],
  110. removeAuthIds: data.removeAuthIds || [],
  111. }
  112. console.log(tempData);
  113. await editUser(id, tempData);
  114. router.replace("/settings/staff");
  115. } catch (e) {
  116. console.log(e);
  117. setServerError(t("An error has occurred. Please try again later."));
  118. }
  119. },
  120. [router]
  121. );
  122. const onSubmitError = useCallback<SubmitErrorHandler<UserInputs>>(
  123. (errors) => {
  124. console.log(errors);
  125. },
  126. []
  127. );
  128. return (
  129. <>
  130. {serverError && (
  131. <Typography variant="body2" color="error" alignSelf="flex-end">
  132. {serverError}
  133. </Typography>
  134. )}
  135. <FormProvider {...formProps}>
  136. <Stack
  137. spacing={2}
  138. component="form"
  139. onSubmit={formProps.handleSubmit(onSubmit, onSubmitError)}
  140. >
  141. <Stack
  142. direction="row"
  143. justifyContent="space-between"
  144. flexWrap="wrap"
  145. rowGap={2}
  146. >
  147. <Tabs
  148. value={tabIndex}
  149. onChange={handleTabChange}
  150. variant="scrollable"
  151. >
  152. <Tab
  153. label={t("User Detail")}
  154. icon={
  155. hasErrorsInTab(0, errors) ? (
  156. <Error sx={{ marginInlineEnd: 1 }} color="error" />
  157. ) : undefined
  158. }
  159. iconPosition="end"
  160. />
  161. <Tab label={t("User Authority")} iconPosition="end" />
  162. </Tabs>
  163. </Stack>
  164. {tabIndex == 0 && <UserDetail data={data!} />}
  165. {tabIndex === 1 && <AuthAllocation auths={auths!}/>}
  166. <Stack direction="row" justifyContent="flex-end" gap={1}>
  167. <Button
  168. variant="text"
  169. startIcon={<RestartAlt />}
  170. // onClick={() => console.log("asdasd")}
  171. >
  172. {t("Reset")}
  173. </Button>
  174. <Button
  175. variant="outlined"
  176. startIcon={<Close />}
  177. onClick={handleCancel}
  178. >
  179. {t("Cancel")}
  180. </Button>
  181. <Button variant="contained" startIcon={<Check />} type="submit">
  182. {t("Confirm")}
  183. </Button>
  184. </Stack>
  185. </Stack>
  186. </FormProvider>
  187. </>
  188. );
  189. };
  190. export default EditUser;