Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 

515 рядки
18 KiB

  1. "use client";
  2. import Stack from "@mui/material/Stack";
  3. import Box from "@mui/material/Box";
  4. import Card from "@mui/material/Card";
  5. import CardContent from "@mui/material/CardContent";
  6. import Grid from "@mui/material/Grid";
  7. import TextField from "@mui/material/TextField";
  8. import Typography from "@mui/material/Typography";
  9. import { CreateGroupInputs } from "@/app/api/group/actions";
  10. import { Controller, useFormContext } from "react-hook-form";
  11. import { useTranslation } from "react-i18next";
  12. import { useCallback, useEffect } from "react";
  13. import { CreateStaffInputs } from "@/app/api/staff/actions";
  14. import {
  15. Checkbox,
  16. FormControl,
  17. InputLabel,
  18. ListItemText,
  19. MenuItem,
  20. Select,
  21. } from "@mui/material";
  22. import { comboItem } from "./CreateStaff";
  23. import { DatePicker, LocalizationProvider } from "@mui/x-date-pickers";
  24. import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
  25. import { DemoItem } from "@mui/x-date-pickers/internals/demo";
  26. import dayjs from "dayjs";
  27. import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
  28. interface Props {
  29. combos: comboItem;
  30. }
  31. const StaffInfo: React.FC<Props> = ({ combos }) => {
  32. const {
  33. t,
  34. i18n: { language },
  35. } = useTranslation();
  36. const {
  37. register,
  38. formState: { errors, defaultValues },
  39. control,
  40. reset,
  41. resetField,
  42. setValue,
  43. getValues,
  44. clearErrors
  45. } = useFormContext<CreateStaffInputs>();
  46. const employType = [
  47. { id: 1, label: "FT" },
  48. { id: 2, label: "PT" },
  49. ];
  50. const skillIdNameMap = combos.skill.reduce<{ [id: number]: string }>(
  51. (acc, skill) => ({ ...acc, [skill.id]: skill.label }),
  52. {}
  53. );
  54. const resetStaff = useCallback(() => {
  55. console.log(defaultValues);
  56. if (defaultValues !== undefined) {
  57. // resetField("description");
  58. }
  59. }, [defaultValues]);
  60. const joinDate = getValues("joinDate");
  61. const departDate = getValues("departDate");
  62. useEffect(() => {
  63. if(joinDate)
  64. clearErrors("joinDate")
  65. if(departDate)
  66. clearErrors("departDate")
  67. }, [joinDate, departDate])
  68. return (
  69. <Card sx={{ display: "block" }}>
  70. <CardContent component={Stack} spacing={4}>
  71. <Box>
  72. <Typography variant="overline" display="block" marginBlockEnd={1}>
  73. {t("Staff")}
  74. </Typography>
  75. <Grid container spacing={2} columns={{ xs: 6, sm: 12 }}>
  76. <Grid item xs={6}>
  77. <TextField
  78. label={t("Staff ID")}
  79. fullWidth
  80. required
  81. {...register("staffId", {
  82. required: "Staff Id required!",
  83. })}
  84. error={Boolean(errors.name)}
  85. helperText={
  86. Boolean(errors.name) &&
  87. (errors.name?.message
  88. ? t(errors.name.message)
  89. : t("Please input correct staffId"))
  90. }
  91. />
  92. </Grid>
  93. <Grid item xs={6}>
  94. <TextField
  95. label={t("Staff Name")}
  96. fullWidth
  97. required
  98. {...register("name", {
  99. required: "Staff Name required!",
  100. })}
  101. error={Boolean(errors.name)}
  102. helperText={
  103. Boolean(errors.name) &&
  104. (errors.name?.message
  105. ? t(errors.name.message)
  106. : t("Please input correct name"))
  107. }
  108. />
  109. </Grid>
  110. <Grid item xs={6}>
  111. <FormControl fullWidth>
  112. <InputLabel required>{t("Company")}</InputLabel>
  113. <Controller
  114. control={control}
  115. name="companyId"
  116. render={({ field }) => (
  117. <Select
  118. label={t("Company")}
  119. {...field}
  120. error={Boolean(errors.companyId)}
  121. >
  122. {combos.company.map((company, index) => (
  123. <MenuItem
  124. key={`${company.id}-${index}`}
  125. value={company.id}
  126. >
  127. {t(company.label)}
  128. </MenuItem>
  129. ))}
  130. </Select>
  131. )}
  132. />
  133. </FormControl>
  134. </Grid>
  135. <Grid item xs={6}>
  136. <FormControl fullWidth>
  137. <InputLabel>{t("Team")}</InputLabel>
  138. <Controller
  139. control={control}
  140. name="teamId"
  141. render={({ field }) => (
  142. <Select
  143. label={t("Team")}
  144. {...field}
  145. // error={Boolean(errors.teamId)}
  146. >
  147. {combos.team.map((team, index) => (
  148. <MenuItem key={`${team.id}-${index}`} value={team.id}>
  149. {t(team.label)}
  150. </MenuItem>
  151. ))}
  152. </Select>
  153. )}
  154. />
  155. </FormControl>
  156. </Grid>
  157. <Grid item xs={6}>
  158. <FormControl fullWidth>
  159. <InputLabel>{t("Department")}</InputLabel>
  160. <Controller
  161. control={control}
  162. name="departmentId"
  163. render={({ field }) => (
  164. <Select
  165. label={t("Department")}
  166. {...field}
  167. error={Boolean(errors.departmentId)}
  168. >
  169. {combos.department.map((department, index) => (
  170. <MenuItem
  171. key={`${department.id}-${index}`}
  172. value={department.id}
  173. >
  174. {t(department.label)}
  175. </MenuItem>
  176. ))}
  177. </Select>
  178. )}
  179. />
  180. </FormControl>
  181. </Grid>
  182. <Grid item xs={6}>
  183. <FormControl fullWidth>
  184. <InputLabel required>{t("Grade")}</InputLabel>
  185. <Controller
  186. control={control}
  187. name="gradeId"
  188. render={({ field }) => (
  189. <Select
  190. label={t("Grade")}
  191. {...field}
  192. error={Boolean(errors.gradeId)}
  193. >
  194. {combos.grade.map((grade, index) => (
  195. <MenuItem key={`${grade.id}-${index}`} value={grade.id}>
  196. {t(grade.label)}
  197. </MenuItem>
  198. ))}
  199. </Select>
  200. )}
  201. />
  202. </FormControl>
  203. </Grid>
  204. <Grid item xs={6}>
  205. <FormControl fullWidth>
  206. <InputLabel>{t("Skillset")}</InputLabel>
  207. <Controller
  208. defaultValue={[]}
  209. control={control}
  210. name="skillSetId"
  211. render={({ field }) => (
  212. <Select
  213. // error={Boolean(errors.skillSetId)}
  214. renderValue={(types) =>
  215. types.map((type) => skillIdNameMap[type]).join(", ")
  216. }
  217. multiple
  218. label={t("Skillset")}
  219. {...field}
  220. >
  221. {combos.skill.map((skill, index) => {
  222. // console.log(field)
  223. return (
  224. <MenuItem
  225. key={`${skill.id}-${index}`}
  226. value={skill.id}
  227. >
  228. <Checkbox
  229. checked={field.value!.indexOf(skill.id) > -1}
  230. />
  231. <ListItemText primary={skill.label} />
  232. </MenuItem>
  233. );
  234. })}
  235. </Select>
  236. )}
  237. />
  238. </FormControl>
  239. </Grid>
  240. <Grid item xs={6}>
  241. <FormControl fullWidth>
  242. <InputLabel required>{t("Current Position")}</InputLabel>
  243. <Controller
  244. control={control}
  245. name="currentPositionId"
  246. render={({ field }) => (
  247. <Select
  248. label={t("Current Position")}
  249. {...field}
  250. error={Boolean(errors.currentPositionId)}
  251. >
  252. {combos.position.map((position, index) => (
  253. <MenuItem
  254. key={`${position.id}-${index}`}
  255. value={position.id}
  256. >
  257. {t(position.label)}
  258. </MenuItem>
  259. ))}
  260. </Select>
  261. )}
  262. />
  263. </FormControl>
  264. </Grid>
  265. <Grid item xs={6}>
  266. <FormControl fullWidth>
  267. <InputLabel>{t("Salary Point")}</InputLabel>
  268. <Controller
  269. control={control}
  270. name="salaryId"
  271. render={({ field }) => (
  272. <Select
  273. label={t("Salary Point")}
  274. {...field}
  275. error={Boolean(errors.salaryId)}
  276. >
  277. {combos.salary.map((salary, index) => (
  278. <MenuItem
  279. key={`${salary.id}-${index}`}
  280. value={salary.id}
  281. >
  282. {t(salary.label)}
  283. </MenuItem>
  284. ))}
  285. </Select>
  286. )}
  287. />
  288. </FormControl>
  289. </Grid>
  290. <Grid item xs={6}>
  291. <FormControl fullWidth>
  292. <InputLabel>{t("Employ Type")}</InputLabel>
  293. <Controller
  294. control={control}
  295. name="employType"
  296. render={({ field }) => (
  297. <Select
  298. label={t("Employ Type")}
  299. {...field}
  300. error={Boolean(errors.employType)}
  301. >
  302. {employType.map((type, index) => (
  303. <MenuItem
  304. key={`${type.id}-${index}`}
  305. value={type.label}
  306. >
  307. {t(type.label)}
  308. </MenuItem>
  309. ))}
  310. </Select>
  311. )}
  312. />
  313. </FormControl>
  314. </Grid>
  315. <Grid item xs={6}>
  316. <TextField
  317. label={t("Email")}
  318. fullWidth
  319. required
  320. {...register("email", {
  321. required: "Email required!",
  322. })}
  323. error={Boolean(errors.email)}
  324. helperText={
  325. Boolean(errors.email) &&
  326. (errors.email?.message
  327. ? t(errors.email.message)
  328. : t("Please input correct email"))
  329. }
  330. />
  331. </Grid>
  332. <Grid item xs={6}>
  333. <TextField
  334. label={t("Phone1")}
  335. fullWidth
  336. required
  337. {...register("phone1", {
  338. required: "phone1 required!",
  339. })}
  340. error={Boolean(errors.phone1)}
  341. helperText={
  342. Boolean(errors.phone1) &&
  343. (errors.phone1?.message
  344. ? t(errors.phone1.message)
  345. : t("Please input correct phone1"))
  346. }
  347. />
  348. </Grid>
  349. <Grid item xs={6}>
  350. <TextField
  351. label={t("Phone2")}
  352. fullWidth
  353. {...register("phone2")}
  354. error={Boolean(errors.phone2)}
  355. helperText={
  356. Boolean(errors.phone2) &&
  357. (errors.phone2?.message
  358. ? t(errors.phone2.message)
  359. : t("Please input correct phone2"))
  360. }
  361. />
  362. </Grid>
  363. </Grid>
  364. <Grid container spacing={2} columns={{ xs: 6, sm: 12 }} marginTop={3}>
  365. <Grid item xs={6}>
  366. <TextField
  367. label={t("Emergency Contact Name")}
  368. fullWidth
  369. required
  370. {...register("emergContactName", {
  371. required: "Emergency Contact Name required!",
  372. })}
  373. error={Boolean(errors.emergContactName)}
  374. helperText={
  375. Boolean(errors.emergContactName) &&
  376. (errors.emergContactName?.message
  377. ? t(errors.emergContactName.message)
  378. : t("Please input correct Emergency Contact Name"))
  379. }
  380. />
  381. </Grid>
  382. <Grid item xs={6}>
  383. <TextField
  384. label={t("Emergency Contact Phone")}
  385. fullWidth
  386. required
  387. {...register("emergContactPhone", {
  388. required: "Emergency Contact Phone required!",
  389. })}
  390. error={Boolean(errors.emergContactPhone)}
  391. helperText={
  392. Boolean(errors.emergContactPhone) &&
  393. (errors.emergContactPhone?.message
  394. ? t(errors.emergContactPhone.message)
  395. : t("Please input correct Emergency Contact Phone"))
  396. }
  397. />
  398. </Grid>
  399. <Grid item xs={6}>
  400. <LocalizationProvider
  401. dateAdapter={AdapterDayjs}
  402. adapterLocale={`${language}-hk`}
  403. >
  404. <DatePicker
  405. sx={{ width: "100%" }}
  406. label={t("Join Date")}
  407. value={joinDate ? dayjs(joinDate) : null}
  408. onChange={(date) => {
  409. if (!date) return;
  410. setValue("joinDate", date.format(INPUT_DATE_FORMAT));
  411. }}
  412. slotProps={{
  413. textField: {
  414. error:
  415. joinDate === "Invalid Date" || Boolean(errors.joinDate),
  416. // value: errors.joinDate?.message,
  417. },
  418. }}
  419. />
  420. </LocalizationProvider>
  421. </Grid>
  422. <Grid item xs={6}>
  423. <FormControl fullWidth>
  424. <InputLabel>{t("Join Position")}</InputLabel>
  425. <Controller
  426. control={control}
  427. name="joinPositionId"
  428. render={({ field }) => (
  429. <Select
  430. label={t("Join Position")}
  431. {...field}
  432. error={Boolean(errors.joinPositionId)}
  433. >
  434. {combos.position.map((position, index) => (
  435. <MenuItem
  436. key={`${position.id}-${index}`}
  437. value={position.label}
  438. >
  439. {t(position.label)}
  440. </MenuItem>
  441. ))}
  442. </Select>
  443. )}
  444. />
  445. </FormControl>
  446. </Grid>
  447. <Grid item xs={6}>
  448. <LocalizationProvider
  449. dateAdapter={AdapterDayjs}
  450. adapterLocale={`${language}-hk`}
  451. >
  452. <DatePicker
  453. sx={{ width: "100%" }}
  454. label={t("Depart Date")}
  455. value={departDate ? dayjs(departDate) : null}
  456. onChange={(date) => {
  457. if (!date) return;
  458. setValue("departDate", date.format(INPUT_DATE_FORMAT));
  459. }}
  460. slotProps={{
  461. textField: {
  462. error: departDate === "Invalid Date",
  463. // value: errors.departDate?.message,
  464. },
  465. }}
  466. />
  467. </LocalizationProvider>
  468. </Grid>
  469. <Grid item xs={6}>
  470. <TextField
  471. label={t("Depart Reason")}
  472. fullWidth
  473. {...register("departReason")}
  474. error={Boolean(errors.departReason)}
  475. helperText={
  476. Boolean(errors.departReason) &&
  477. (errors.departReason?.message
  478. ? t(errors.departReason.message)
  479. : t("Please input correct departReason"))
  480. }
  481. />
  482. </Grid>
  483. <Grid item xs={12}>
  484. <TextField
  485. label={t("Remark")}
  486. fullWidth
  487. multiline
  488. rows={4}
  489. {...register("remark")}
  490. error={Boolean(errors.remark)}
  491. helperText={
  492. Boolean(errors.remark) &&
  493. (errors.remark?.message
  494. ? t(errors.remark.message)
  495. : t("Please input correct remark"))
  496. }
  497. />
  498. </Grid>
  499. </Grid>
  500. </Box>
  501. </CardContent>
  502. </Card>
  503. );
  504. };
  505. export default StaffInfo;