No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 

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