| @@ -80,8 +80,8 @@ export interface searchInput { | |||||
| export interface SalaryEffectiveInfo { | export interface SalaryEffectiveInfo { | ||||
| id: number; | id: number; | ||||
| date: string; | |||||
| salaryPoint: number; | |||||
| date: string | Date; | |||||
| salaryPoint: number | string; | |||||
| } | } | ||||
| export const preloadTeamLeads = () => { | export const preloadTeamLeads = () => { | ||||
| @@ -28,6 +28,7 @@ import { IndividualStaff, SalaryEffectiveInfo } from "@/app/api/staff"; | |||||
| import dayjs from "dayjs"; | import dayjs from "dayjs"; | ||||
| import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil"; | ||||
| import { List, differenceBy } from "lodash"; | import { List, differenceBy } from "lodash"; | ||||
| // import { useGridApiContext } from '@mui/x-data-grid'; | |||||
| export interface comboItem { | export interface comboItem { | ||||
| company: comboProp[]; | company: comboProp[]; | ||||
| @@ -47,6 +48,8 @@ interface formProps { | |||||
| const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo }) => { | const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo }) => { | ||||
| console.log(combos.salary) | |||||
| console.log(SalaryEffectiveInfo) | |||||
| const defaultSkillset = Staff.skillset.map((s: any) => s.skill.id) | const defaultSkillset = Staff.skillset.map((s: any) => s.skill.id) | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const searchParams = useSearchParams() | const searchParams = useSearchParams() | ||||
| @@ -74,7 +77,12 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo }) | |||||
| departDate: dayjs(Staff.departDate).toString() || "", | departDate: dayjs(Staff.departDate).toString() || "", | ||||
| departReason: Staff.departReason, | departReason: Staff.departReason, | ||||
| remark: Staff.remark, | remark: Staff.remark, | ||||
| salaryEffectiveInfo: SalaryEffectiveInfo | |||||
| salaryEffectiveInfo: SalaryEffectiveInfo.map(item => { | |||||
| return ({ | |||||
| id: Math.random(), | |||||
| salaryPoint: combos.salary.filter(sal => sal.id === item.salaryPoint)[0].label, | |||||
| date: dayjs(item.date).toDate(), | |||||
| })}) | |||||
| }}); | }}); | ||||
| const [serverError, setServerError] = useState(""); | const [serverError, setServerError] = useState(""); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| @@ -147,6 +155,11 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo }) | |||||
| const postData = { | const postData = { | ||||
| id: id, | id: id, | ||||
| ...data, | ...data, | ||||
| salaryEffectiveInfo: SalaryEffectiveInfo.map(item => ({ | |||||
| id: item.id, | |||||
| salaryPoint: item.salaryPoint, | |||||
| date: dayjs(item.date).format('YYYY-MM-DD') | |||||
| })) | |||||
| } | } | ||||
| console.log(postData) | console.log(postData) | ||||
| await saveStaff(postData) | await saveStaff(postData) | ||||
| @@ -168,37 +181,60 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo }) | |||||
| router.back(); | router.back(); | ||||
| }; | }; | ||||
| const resetStaff = useCallback(() => { | |||||
| console.log(dayjs(Staff.joinDate).format(INPUT_DATE_FORMAT)) | |||||
| console.log(formProps.getValues("joinDate")) | |||||
| formProps.reset({ | |||||
| staffId: Staff.staffId, | |||||
| name: Staff.name, | |||||
| companyId: Staff.company.id, | |||||
| teamId: Staff.team?.id, | |||||
| departmentId: Staff.department?.id, | |||||
| gradeId: Staff.grade?.id, | |||||
| skillSetId: defaultSkillset, | |||||
| currentPositionId: Staff.currentPosition?.id, | |||||
| salaryId: Staff.salary.salaryPoint, | |||||
| employType: Staff.employType, | |||||
| email: Staff.email, | |||||
| phone1: Staff.phone1, | |||||
| phone2: Staff.phone2, | |||||
| emergContactName: Staff.emergContactName, | |||||
| emergContactPhone: Staff.emergContactPhone, | |||||
| joinDate: Staff.joinDate ? dayjs(Staff.joinDate).format(INPUT_DATE_FORMAT) : "", | |||||
| joinPositionId: Staff.joinPosition?.id, | |||||
| departDate: !Staff.departDate ? "" : dayjs(Staff.departDate).format(INPUT_DATE_FORMAT), | |||||
| departReason: Staff.departReason, | |||||
| remark: Staff.remark, | |||||
| salaryEffectiveInfo: SalaryEffectiveInfo | |||||
| }); | |||||
| }, [Staff,formProps]); | |||||
| // const resetStaff = useCallback(() => { | |||||
| // window.location.reload() | |||||
| // console.log(dayjs(Staff.joinDate).format(INPUT_DATE_FORMAT)) | |||||
| // console.log(formProps.getValues("joinDate")) | |||||
| // formProps.setValue('salaryEffectiveInfo', SalaryEffectiveInfo.map(item => { | |||||
| // return ({ | |||||
| // id: item.id, | |||||
| // salaryPoint: combos.salary.filter(sal => sal.id === item.salaryPoint)[0].label, | |||||
| // date: dayjs(item.date).toDate(), | |||||
| // })})) | |||||
| // formProps.reset({ | |||||
| // staffId: Staff.staffId, | |||||
| // name: Staff.name, | |||||
| // companyId: Staff.company.id, | |||||
| // teamId: Staff.team?.id, | |||||
| // departmentId: Staff.department?.id, | |||||
| // gradeId: Staff.grade?.id, | |||||
| // skillSetId: defaultSkillset, | |||||
| // currentPositionId: Staff.currentPosition?.id, | |||||
| // salaryId: Staff.salary.salaryPoint, | |||||
| // employType: Staff.employType, | |||||
| // email: Staff.email, | |||||
| // phone1: Staff.phone1, | |||||
| // phone2: Staff.phone2, | |||||
| // emergContactName: Staff.emergContactName, | |||||
| // emergContactPhone: Staff.emergContactPhone, | |||||
| // joinDate: Staff.joinDate ? dayjs(Staff.joinDate).format(INPUT_DATE_FORMAT) : "", | |||||
| // joinPositionId: Staff.joinPosition?.id, | |||||
| // departDate: !Staff.departDate ? "" : dayjs(Staff.departDate).format(INPUT_DATE_FORMAT), | |||||
| // departReason: Staff.departReason, | |||||
| // remark: Staff.remark, | |||||
| // salaryEffectiveInfo: SalaryEffectiveInfo.map(item => { | |||||
| // return ({ | |||||
| // id: item.id, | |||||
| // salaryPoint: combos.salary.filter(sal => sal.id === item.salaryPoint)[0].label, | |||||
| // date: dayjs(item.date).toDate(), | |||||
| // })}) | |||||
| // }); | |||||
| // }, []); | |||||
| // useEffect(() => { | |||||
| // formProps.setValue('salaryEffectiveInfo', SalaryEffectiveInfo.map(item => { | |||||
| // return ({ | |||||
| // id: item.id, | |||||
| // salaryPoint: combos.salary.filter(sal => sal.id === item.salaryPoint)[0].label, | |||||
| // date: dayjs(item.date).toDate(), | |||||
| // })}) | |||||
| // ) | |||||
| // }, []); | |||||
| useEffect(() => { | |||||
| resetStaff() | |||||
| }, [Staff, formProps, combos]); | |||||
| // useEffect(() => { | |||||
| // resetStaff() | |||||
| // }, [Staff, formProps, combos]); | |||||
| return ( | return ( | ||||
| <> | <> | ||||
| @@ -218,7 +254,7 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo }) | |||||
| <Button | <Button | ||||
| variant="text" | variant="text" | ||||
| startIcon={<RestartAlt />} | startIcon={<RestartAlt />} | ||||
| onClick={resetStaff} | |||||
| onClick={()=> window.location.reload()} | |||||
| > | > | ||||
| {t("Reset")} | {t("Reset")} | ||||
| </Button> | </Button> | ||||
| @@ -42,6 +42,8 @@ const EditStaffWrapper: React.FC<Props> & SubComponents = async ({ | |||||
| fetchSkillCombo(), | fetchSkillCombo(), | ||||
| fetchSalaryCombo(), | fetchSalaryCombo(), | ||||
| ]); | ]); | ||||
| console.log(SalaryCombo.records) | |||||
| const combos: comboItem = { | const combos: comboItem = { | ||||
| company: CompanyCombo.records, | company: CompanyCombo.records, | ||||
| team: TeamCombo.records, | team: TeamCombo.records, | ||||
| @@ -54,7 +56,7 @@ const EditStaffWrapper: React.FC<Props> & SubComponents = async ({ | |||||
| console.log(Staff.data) | console.log(Staff.data) | ||||
| return <EditStaff Staff={Staff.data} combos={combos} SalaryEffectiveInfo={[{id:0, salaryPoint: 1, date:"2021-05-05"}]}/>; | |||||
| return <EditStaff Staff={Staff.data} combos={combos} SalaryEffectiveInfo={[{id:0, salaryPoint: 1, date:"2021-05-05"}, {id:1, salaryPoint: 43, date:"2024-05-05"}]}/>; | |||||
| }; | }; | ||||
| EditStaffWrapper.Loading = EditStaffLoading; | EditStaffWrapper.Loading = EditStaffLoading; | ||||
| @@ -1,17 +1,25 @@ | |||||
| import React, { useEffect } from 'react'; | |||||
| import React, { useCallback, useEffect, useMemo, useState } from 'react'; | |||||
| import { Modal, Box, Typography, Button, TextField, FormControl, InputLabel, Select, MenuItem, Paper, SxProps } from '@mui/material'; | import { Modal, Box, Typography, Button, TextField, FormControl, InputLabel, Select, MenuItem, Paper, SxProps } from '@mui/material'; | ||||
| import { useForm, Controller } from 'react-hook-form'; | |||||
| import { useForm, Controller, useFormContext } from 'react-hook-form'; | |||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil'; | ||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| import { DatePicker } from '@mui/x-date-pickers'; | import { DatePicker } from '@mui/x-date-pickers'; | ||||
| import { DataGrid, GridEventListener, GridRowEditStopParams, GridRowEditStopReasons, GridRowModel, GridRowModes, GridRowModesModel, GridToolbarContainer } from '@mui/x-data-grid'; | |||||
| import StyledDataGrid from '../StyledDataGrid'; | |||||
| import AddIcon from '@mui/icons-material/Add'; | |||||
| import SaveIcon from '@mui/icons-material/Save'; | |||||
| import DeleteIcon from '@mui/icons-material/Delete'; | |||||
| import CancelIcon from '@mui/icons-material/Cancel'; | |||||
| import EditIcon from '@mui/icons-material/Edit'; | |||||
| import { GridActionsCellItem } from '@mui/x-data-grid'; | |||||
| interface SalaryEffectiveModelProps { | interface SalaryEffectiveModelProps { | ||||
| open: boolean; | open: boolean; | ||||
| onClose: () => void; | onClose: () => void; | ||||
| modalSx?: SxProps; | modalSx?: SxProps; | ||||
| onSave: () => void; | onSave: () => void; | ||||
| columns: any[] | |||||
| } | } | ||||
| const modalSx: SxProps = { | const modalSx: SxProps = { | ||||
| @@ -20,17 +28,57 @@ const modalSx: SxProps = { | |||||
| left: "50%", | left: "50%", | ||||
| transform: "translate(-50%, -50%)", | transform: "translate(-50%, -50%)", | ||||
| width: "90%", | width: "90%", | ||||
| maxWidth: "sm", | |||||
| maxHeight: "90%", | |||||
| maxWidth: "auto", | |||||
| maxHeight: "auto", | |||||
| padding: 3, | padding: 3, | ||||
| display: "flex", | display: "flex", | ||||
| flexDirection: "column", | flexDirection: "column", | ||||
| gap: 2, | gap: 2, | ||||
| }; | }; | ||||
| const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClose, modalSx: mSx, onSave }) => { | |||||
| function EditToolbar(props: React.JSXElementConstructor<any> | null | undefined | any) { | |||||
| // const intl = useIntl(); | |||||
| // const addRecordBtn = intl.formatMessage({ id: 'add' }); | |||||
| const { count, setCount, setRows, setRowModesModel, _columns } = props; | |||||
| let obj: { [key: string]: string } = {}; | |||||
| for (let i = 0; i < _columns.length - 1; i++) { | |||||
| obj[_columns[i].field as string] = ''; | |||||
| } | |||||
| const handleClick = React.useCallback(() => { | |||||
| const id = Math.random(); | |||||
| setRows((oldRows: any) => [...oldRows, { id, ...obj, isNew: true }]); | |||||
| setRowModesModel((oldModel: any) => ({ | |||||
| ...oldModel, | |||||
| [id]: { mode: GridRowModes.Edit, | |||||
| // fieldToFocus: 'material' | |||||
| } | |||||
| })); | |||||
| setCount((prev: number) => prev+1) | |||||
| }, [count, setCount, setRowModesModel, setRows]) | |||||
| return ( | |||||
| <GridToolbarContainer> | |||||
| <Button disabled={count>=1} color="primary" startIcon={<AddIcon />} onClick={handleClick}> | |||||
| {"addRecordBtn"} | |||||
| </Button> | |||||
| {/* <Button color="primary" startIcon={<AddIcon />} onClick={handleSave}> | |||||
| SAVE | |||||
| </Button> */} | |||||
| </GridToolbarContainer> | |||||
| ); | |||||
| } | |||||
| const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClose, modalSx: mSx, onSave, columns }) => { | |||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| const { control, register, formState, trigger, watch, setValue } = useForm({}); | |||||
| const { control, register, formState, trigger, watch, setValue, getValues } = useFormContext(); | |||||
| const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({}); | |||||
| const [count, setCount] = useState(0); | |||||
| const [_rows, setRows] = useState(() => { | |||||
| const list = getValues('salaryEffectiveInfo') | |||||
| console.log(list) | |||||
| return list && list.length > 0 ? list : [] | |||||
| }); | |||||
| const formValues = watch(); // This line of code is using the watch function from react-hook-form to get the current values of the form fields. | const formValues = watch(); // This line of code is using the watch function from react-hook-form to get the current values of the form fields. | ||||
| @@ -38,14 +86,133 @@ const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClo | |||||
| onClose(); | onClose(); | ||||
| }; | }; | ||||
| const handleSave = async () => { | |||||
| const isValid = await trigger(); | |||||
| if (isValid) { | |||||
| onSave(); | |||||
| onClose(); | |||||
| // const handleSave = async () => { | |||||
| // const isValid = await trigger(); | |||||
| // // if (isValid) { | |||||
| // // onSave(); | |||||
| // // onClose(); | |||||
| // // } | |||||
| // }; | |||||
| const handleRowEditStop: GridEventListener<"rowEditStop"> = ( | |||||
| params, | |||||
| event, | |||||
| ) => { | |||||
| if (params.reason === GridRowEditStopReasons.rowFocusOut) { | |||||
| event.defaultMuiPrevented = true; | |||||
| } | } | ||||
| }; | }; | ||||
| const processRowUpdate = useCallback((newRow: GridRowModel) => { | |||||
| console.log(newRow) | |||||
| const updatedRow = { ...newRow, updated: true }; | |||||
| console.log(_rows) | |||||
| if (_rows.length != 0) { | |||||
| setRows(_rows?.map((row: any) => (row.id === newRow.id ? updatedRow : row))); | |||||
| } | |||||
| return updatedRow; | |||||
| }, [_rows, setValue, setRows]) | |||||
| useEffect(()=> { | |||||
| setValue('salaryEffectiveInfo', _rows) | |||||
| }, [_rows]) | |||||
| const handleSaveClick = useCallback( | |||||
| (id: any) => () => { | |||||
| setRowModesModel((prevRowModesModel) => ({ | |||||
| ...prevRowModesModel, | |||||
| [id]: { mode: GridRowModes.View } | |||||
| })); | |||||
| }, | |||||
| [setRowModesModel] | |||||
| ); | |||||
| const handleCancelClick = useCallback( | |||||
| (id: any) => () => { | |||||
| setRowModesModel((prevRowModesModel) => ({ | |||||
| ...prevRowModesModel, | |||||
| [id]: { mode: GridRowModes.View, ignoreModifications: true } | |||||
| })); | |||||
| }, | |||||
| [setRowModesModel] | |||||
| ); | |||||
| const handleEditClick = useCallback( | |||||
| (id: any) => () => { | |||||
| setRowModesModel((prevRowModesModel) => ({ | |||||
| ...prevRowModesModel, | |||||
| [id]: { mode: GridRowModes.Edit } | |||||
| })); | |||||
| }, | |||||
| [setRowModesModel] | |||||
| ); | |||||
| const handleDeleteClick = useCallback( | |||||
| (id: any) => () => { | |||||
| setRows((prevRows: any) => prevRows.filter((row: any) => row.id !== id)); | |||||
| setCount((prev: number) => prev - 1) | |||||
| }, | |||||
| [setRows, setCount] | |||||
| ); | |||||
| const defaultCol = useMemo( | |||||
| () => ( | |||||
| { | |||||
| field: 'actions', | |||||
| type: 'actions', | |||||
| headerName: 'edit', | |||||
| width: 100, | |||||
| cellClassName: 'actions', | |||||
| getActions: ({ id }: { id: number }) => { | |||||
| const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit; | |||||
| if (isInEditMode) { | |||||
| return [ | |||||
| <GridActionsCellItem | |||||
| icon={<SaveIcon />} | |||||
| label="Save" | |||||
| key="edit" | |||||
| sx={{ | |||||
| color: 'primary.main' | |||||
| }} | |||||
| onClick={handleSaveClick(id)} | |||||
| />, | |||||
| <GridActionsCellItem | |||||
| icon={<CancelIcon />} | |||||
| label="Cancel" | |||||
| key="edit" | |||||
| onClick={handleCancelClick(id)} | |||||
| /> | |||||
| ]; | |||||
| } | |||||
| return [ | |||||
| <GridActionsCellItem | |||||
| icon={<EditIcon />} | |||||
| label="Edit" | |||||
| className="textPrimary" | |||||
| onClick={handleEditClick(id)} | |||||
| color="inherit" | |||||
| key="edit" | |||||
| />, | |||||
| <GridActionsCellItem | |||||
| icon={<DeleteIcon />} | |||||
| label="Delete" | |||||
| sx={{ | |||||
| color: 'error.main' | |||||
| }} | |||||
| onClick={handleDeleteClick(id)} color="inherit" key="edit" /> | |||||
| ]; | |||||
| } | |||||
| } | |||||
| ), [rowModesModel, handleSaveClick, handleCancelClick, handleEditClick, handleDeleteClick] | |||||
| ) | |||||
| let _columns: any[] = [] | |||||
| if (columns) { | |||||
| _columns = [...columns, defaultCol] | |||||
| } | |||||
| useEffect(() => { | useEffect(() => { | ||||
| console.log(formValues) | console.log(formValues) | ||||
| }, [open]) | }, [open]) | ||||
| @@ -56,30 +223,33 @@ const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClo | |||||
| <Typography variant="h6" component="h2"> | <Typography variant="h6" component="h2"> | ||||
| {t('Salary Effective Date Change')} | {t('Salary Effective Date Change')} | ||||
| </Typography> | </Typography> | ||||
| <FormControl> | |||||
| <TextField | |||||
| label={t('Salary')} | |||||
| type="number" | |||||
| fullWidth | |||||
| {...register('salary', { | |||||
| valueAsNumber: true, | |||||
| required: t('Salary is required'), | |||||
| })} | |||||
| error={Boolean(formState.errors.salary)} | |||||
| // helperText={formState.errors.salary?.message} | |||||
| /> | |||||
| <StyledDataGrid | |||||
| rows={_rows} | |||||
| columns={_columns} | |||||
| editMode="row" | |||||
| rowModesModel={rowModesModel} | |||||
| onRowModesModelChange={setRowModesModel} | |||||
| onRowEditStop={handleRowEditStop} | |||||
| processRowUpdate={processRowUpdate} | |||||
| slots={{ | |||||
| toolbar: EditToolbar | |||||
| }} | |||||
| slotProps={{ | |||||
| toolbar: {count, setCount, setRows, setRowModesModel, _columns} | |||||
| }} | |||||
| /> | |||||
| <Box display="flex" justifyContent="flex-end" gap={2}> | <Box display="flex" justifyContent="flex-end" gap={2}> | ||||
| <Button variant="text" onClick={handleClose}> | <Button variant="text" onClick={handleClose}> | ||||
| {t('Cancel')} | {t('Cancel')} | ||||
| </Button> | </Button> | ||||
| <Button variant="contained" onClick={handleSave}> | |||||
| <Button variant="contained" onClick={handleClose}> | |||||
| {t("Save")} | {t("Save")} | ||||
| </Button> | </Button> | ||||
| </Box> | </Box> | ||||
| </FormControl> | |||||
| {/* </FormControl> */} | |||||
| </Paper> | </Paper> | ||||
| </Modal> | </Modal> | ||||
| ); | ); | ||||
| }; | }; | ||||
| export default SalaryEffectiveModel; | |||||
| export default SalaryEffectiveModel; | |||||
| @@ -9,7 +9,7 @@ import Typography from "@mui/material/Typography"; | |||||
| import { CreateGroupInputs } from "@/app/api/group/actions"; | import { CreateGroupInputs } from "@/app/api/group/actions"; | ||||
| import { Controller, useFormContext } from "react-hook-form"; | import { Controller, useFormContext } from "react-hook-form"; | ||||
| import { useTranslation } from "react-i18next"; | import { useTranslation } from "react-i18next"; | ||||
| import { useCallback, useEffect, useState } from "react"; | |||||
| import { useCallback, useEffect, useMemo, useState } from "react"; | |||||
| import { CreateStaffInputs } from "@/app/api/staff/actions"; | import { CreateStaffInputs } from "@/app/api/staff/actions"; | ||||
| import { | import { | ||||
| Button, | Button, | ||||
| @@ -95,6 +95,28 @@ const StaffInfo: React.FC<Props> = ({ combos }) => { | |||||
| if (departDate) clearErrors("departDate"); | if (departDate) clearErrors("departDate"); | ||||
| }, [joinDate, departDate]); | }, [joinDate, departDate]); | ||||
| const salaryCols = useMemo( | |||||
| () => [ | |||||
| { | |||||
| field: 'salaryPoint', | |||||
| headerName: 'salaryPoint', | |||||
| flex: 1, | |||||
| editable: true, | |||||
| type: 'singleSelect', | |||||
| valueOptions: combos?.salary.map(item => item.label), | |||||
| // valueOptions: [], | |||||
| // width: 150 | |||||
| }, | |||||
| { | |||||
| field: 'date', | |||||
| headerName: 'date', | |||||
| flex: 1, | |||||
| editable: true, | |||||
| type: 'date', | |||||
| // width: 150 | |||||
| }, | |||||
| ], [combos]) | |||||
| return ( | return ( | ||||
| <Card sx={{ display: "block" }}> | <Card sx={{ display: "block" }}> | ||||
| <CardContent component={Stack} spacing={4}> | <CardContent component={Stack} spacing={4}> | ||||
| @@ -305,6 +327,7 @@ const StaffInfo: React.FC<Props> = ({ combos }) => { | |||||
| {...field} | {...field} | ||||
| error={Boolean(errors.salaryId)} | error={Boolean(errors.salaryId)} | ||||
| style={{ flex: 1, marginRight: '8px' }} | style={{ flex: 1, marginRight: '8px' }} | ||||
| disabled | |||||
| > | > | ||||
| {combos.salary.map((salary, index) => ( | {combos.salary.map((salary, index) => ( | ||||
| <MenuItem | <MenuItem | ||||
| @@ -544,6 +567,7 @@ const StaffInfo: React.FC<Props> = ({ combos }) => { | |||||
| open={salaryEffectiveModelOpen} | open={salaryEffectiveModelOpen} | ||||
| onClose={closeSalaryEffectiveModel} | onClose={closeSalaryEffectiveModel} | ||||
| onSave={onSalaryEffectiveSave} | onSave={onSalaryEffectiveSave} | ||||
| columns={salaryCols} | |||||
| /> | /> | ||||
| </Card> | </Card> | ||||
| ); | ); | ||||