Преглед на файлове

update salary point input edit

tags/Baseline_30082024_FRONTEND_UAT
MSI\derek преди 1 година
родител
ревизия
bcee64d0a1
променени са 5 файла, в които са добавени 295 реда и са изтрити 63 реда
  1. +2
    -2
      src/app/api/staff/index.ts
  2. +68
    -32
      src/components/EditStaff/EditStaff.tsx
  3. +3
    -1
      src/components/EditStaff/EditStaffWrapper.tsx
  4. +197
    -27
      src/components/EditStaff/SalaryEffectiveModel.tsx
  5. +25
    -1
      src/components/EditStaff/StaffInfo.tsx

+ 2
- 2
src/app/api/staff/index.ts Целия файл

@@ -80,8 +80,8 @@ export interface searchInput {

export interface SalaryEffectiveInfo {
id: number;
date: string;
salaryPoint: number;
date: string | Date;
salaryPoint: number | string;
}

export const preloadTeamLeads = () => {


+ 68
- 32
src/components/EditStaff/EditStaff.tsx Целия файл

@@ -28,6 +28,7 @@ import { IndividualStaff, SalaryEffectiveInfo } from "@/app/api/staff";
import dayjs from "dayjs";
import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import { List, differenceBy } from "lodash";
// import { useGridApiContext } from '@mui/x-data-grid';

export interface comboItem {
company: comboProp[];
@@ -47,6 +48,8 @@ interface formProps {


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 { t } = useTranslation();
const searchParams = useSearchParams()
@@ -74,7 +77,12 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo })
departDate: dayjs(Staff.departDate).toString() || "",
departReason: Staff.departReason,
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 router = useRouter();
@@ -147,6 +155,11 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo })
const postData = {
id: id,
...data,
salaryEffectiveInfo: SalaryEffectiveInfo.map(item => ({
id: item.id,
salaryPoint: item.salaryPoint,
date: dayjs(item.date).format('YYYY-MM-DD')
}))
}
console.log(postData)
await saveStaff(postData)
@@ -168,37 +181,60 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo })
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 (
<>
@@ -218,7 +254,7 @@ const EditStaff: React.FC<formProps> = ({ Staff, combos, SalaryEffectiveInfo })
<Button
variant="text"
startIcon={<RestartAlt />}
onClick={resetStaff}
onClick={()=> window.location.reload()}
>
{t("Reset")}
</Button>


+ 3
- 1
src/components/EditStaff/EditStaffWrapper.tsx Целия файл

@@ -42,6 +42,8 @@ const EditStaffWrapper: React.FC<Props> & SubComponents = async ({
fetchSkillCombo(),
fetchSalaryCombo(),
]);

console.log(SalaryCombo.records)
const combos: comboItem = {
company: CompanyCombo.records,
team: TeamCombo.records,
@@ -54,7 +56,7 @@ const EditStaffWrapper: React.FC<Props> & SubComponents = async ({

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;


+ 197
- 27
src/components/EditStaff/SalaryEffectiveModel.tsx Целия файл

@@ -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 { useForm, Controller } from 'react-hook-form';
import { useForm, Controller, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { INPUT_DATE_FORMAT, OUTPUT_DATE_FORMAT } from '@/app/utils/formatUtil';
import dayjs from 'dayjs';
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 {
open: boolean;
onClose: () => void;
modalSx?: SxProps;
onSave: () => void;
columns: any[]
}

const modalSx: SxProps = {
@@ -20,17 +28,57 @@ const modalSx: SxProps = {
left: "50%",
transform: "translate(-50%, -50%)",
width: "90%",
maxWidth: "sm",
maxHeight: "90%",
maxWidth: "auto",
maxHeight: "auto",
padding: 3,
display: "flex",
flexDirection: "column",
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 { 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.

@@ -38,14 +86,133 @@ const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClo
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(() => {
console.log(formValues)
}, [open])
@@ -56,30 +223,33 @@ const SalaryEffectiveModel: React.FC<SalaryEffectiveModelProps> = ({ open, onClo
<Typography variant="h6" component="h2">
{t('Salary Effective Date Change')}
</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}>
<Button variant="text" onClick={handleClose}>
{t('Cancel')}
</Button>
<Button variant="contained" onClick={handleSave}>
<Button variant="contained" onClick={handleClose}>
{t("Save")}
</Button>
</Box>
</FormControl>
{/* </FormControl> */}
</Paper>
</Modal>
);
};

export default SalaryEffectiveModel;
export default SalaryEffectiveModel;

+ 25
- 1
src/components/EditStaff/StaffInfo.tsx Целия файл

@@ -9,7 +9,7 @@ import Typography from "@mui/material/Typography";
import { CreateGroupInputs } from "@/app/api/group/actions";
import { Controller, useFormContext } from "react-hook-form";
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 {
Button,
@@ -95,6 +95,28 @@ const StaffInfo: React.FC<Props> = ({ combos }) => {
if (departDate) clearErrors("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 (
<Card sx={{ display: "block" }}>
<CardContent component={Stack} spacing={4}>
@@ -305,6 +327,7 @@ const StaffInfo: React.FC<Props> = ({ combos }) => {
{...field}
error={Boolean(errors.salaryId)}
style={{ flex: 1, marginRight: '8px' }}
disabled
>
{combos.salary.map((salary, index) => (
<MenuItem
@@ -544,6 +567,7 @@ const StaffInfo: React.FC<Props> = ({ combos }) => {
open={salaryEffectiveModelOpen}
onClose={closeSalaryEffectiveModel}
onSave={onSalaryEffectiveSave}
columns={salaryCols}
/>
</Card>
);


Зареждане…
Отказ
Запис