|
- "use client";
- import Grid from "@mui/material/Grid";
- import Paper from "@mui/material/Paper";
- import { useState, useEffect } from "react";
- import { useTranslation } from "react-i18next";
- import PageTitle from "../PageTitle/PageTitle";
- import { Suspense } from "react";
- import Button from "@mui/material/Button";
- import Stack from "@mui/material/Stack";
- import Link from "next/link";
- import { t } from "i18next";
- import {
- Box,
- Container,
- Modal,
- Select,
- SelectChangeEvent,
- Typography,
- } from "@mui/material";
- import { Close } from "@mui/icons-material";
- import AddIcon from "@mui/icons-material/Add";
- import EditIcon from "@mui/icons-material/Edit";
- import DeleteIcon from "@mui/icons-material/DeleteOutlined";
- import SaveIcon from "@mui/icons-material/Save";
- import CancelIcon from "@mui/icons-material/Close";
- import ArrowForwardIcon from "@mui/icons-material/ArrowForward";
- import ArrowBackIcon from "@mui/icons-material/ArrowBack";
- import Swal from "sweetalert2";
- import { msg } from "../Swal/CustomAlerts";
- import React from "react";
- import { DatePicker } from "@mui/x-date-pickers/DatePicker";
- import {
- GridRowsProp,
- GridRowModesModel,
- GridRowModes,
- DataGrid,
- GridColDef,
- GridToolbarContainer,
- GridFooterContainer,
- GridActionsCellItem,
- GridEventListener,
- GridRowId,
- GridRowModel,
- GridRowEditStopReasons,
- GridEditInputCell,
- GridValueSetterParams,
- } from "@mui/x-data-grid";
- import { LocalizationProvider } from "@mui/x-date-pickers";
- import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
- import dayjs from "dayjs";
- import { Props } from "react-intl/src/components/relative";
-
- const weekdays = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
-
- interface BottomBarProps {
- getHoursTotal: (column: string) => number;
- setLockConfirm: (newLock: (oldLock: boolean) => boolean) => void;
- setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void;
- setRowModesModel: (
- newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
- ) => void;
- }
-
- interface EditToolbarProps {
- // setDay: (newDay : dayjs.Dayjs) => void;
- setDay: (newDay: (oldDay: dayjs.Dayjs) => dayjs.Dayjs) => void;
- setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void;
- setRowModesModel: (
- newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
- ) => void;
- }
-
- interface EditFooterProps {
- setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void;
- setRowModesModel: (
- newModel: (oldModel: GridRowModesModel) => GridRowModesModel,
- ) => void;
- }
-
- const EditToolbar = (props: EditToolbarProps) => {
- const { setDay } = props;
- const [selectedDate, setSelectedDate] = useState<dayjs.Dayjs>(dayjs());
-
- const handleClickLeft = () => {
- if (selectedDate) {
- const newDate = selectedDate.add(-7, "day");
- setSelectedDate(newDate);
- }
- };
- const handleClickRight = () => {
- if (selectedDate) {
- const newDate =
- selectedDate.add(7, "day") > dayjs()
- ? dayjs()
- : selectedDate.add(7, "day");
- setSelectedDate(newDate);
- }
- };
-
- const handleDateChange = (date: dayjs.Dayjs | Date | null) => {
- const newDate = dayjs(date);
- setSelectedDate(newDate);
- };
-
- useEffect(() => {
- setDay((oldDay) => selectedDate);
- }, [selectedDate]);
-
- return (
- <LocalizationProvider dateAdapter={AdapterDayjs}>
- <div
- style={{
- display: "flex",
- justifyContent: "flex-end",
- width: "100%",
- paddingBottom: "20px",
- }}
- >
- <Typography variant="h5" id="modal-title" sx={{ flex: 1 }}>
- Timesheet Input
- </Typography>
- <Button
- sx={{ "border-radius": "30%", marginRight: "20px" }}
- variant="contained"
- onClick={handleClickLeft}
- >
- <ArrowBackIcon />
- </Button>
- <DatePicker
- value={selectedDate}
- onChange={handleDateChange}
- disableFuture={true}
- />
- <Button
- sx={{ "border-radius": "30%", margin: "0px 20px 0px 20px" }}
- variant="contained"
- onClick={handleClickRight}
- >
- <ArrowForwardIcon />
- </Button>
- </div>
- </LocalizationProvider>
- );
- };
-
- const BottomBar = (props: BottomBarProps) => {
- const { setRows, setRowModesModel, getHoursTotal, setLockConfirm } = props;
- // const getHoursTotal = props.getHoursTotal;
- const [newId, setNewId] = useState(-1);
- const [invalidDays, setInvalidDays] = useState(0);
-
- const handleAddClick = () => {
- const id = newId;
- setNewId(newId - 1);
- setRows((oldRows) => [
- ...oldRows,
- { id, projectCode: "", task: "", isNew: true },
- ]);
- setRowModesModel((oldModel) => ({
- ...oldModel,
- [id]: { mode: GridRowModes.Edit, fieldToFocus: "projectCode" },
- }));
- };
-
- const totalColDef = {
- flex: 1,
- // style: {color:getHoursTotal('mon')>24?"red":"black"}
- };
-
- const TotalCell = ({ value }: Props) => {
- const [invalid, setInvalid] = useState(false);
-
- useEffect(() => {
- const newInvalid = (value ?? 0) > 24;
- setInvalid(newInvalid);
- }, [value]);
-
- return (
- <Box flex={1} style={{ color: invalid ? "red" : "black" }}>
- {value}
- </Box>
- );
- };
-
- const checkUnlockConfirmBtn = () => {
- // setLockConfirm((oldLock)=> valid);
- setLockConfirm((oldLock) =>
- weekdays.every((weekday) => {
- getHoursTotal(weekday) <= 24;
- }),
- );
- };
-
- return (
- <div>
- <div style={{ display: "flex", justifyContent: "flex", width: "100%" }}>
- <Box flex={5.7} textAlign={"right"} marginRight="4rem">
- <b>Total:</b>
- </Box>
- <TotalCell value={getHoursTotal("mon")} />
- <TotalCell value={getHoursTotal("tue")} />
- <TotalCell value={getHoursTotal("wed")} />
- <TotalCell value={getHoursTotal("thu")} />
- <TotalCell value={getHoursTotal("fri")} />
- <TotalCell value={getHoursTotal("sat")} />
- <TotalCell value={getHoursTotal("sun")} />
- </div>
- <Button
- variant="outlined"
- color="primary"
- startIcon={<AddIcon />}
- onClick={handleAddClick}
- >
- Add record
- </Button>
- </div>
- );
- };
-
- const EditFooter = (props: EditFooterProps) => {
- return (
- <div style={{ display: "flex", justifyContent: "flex", width: "100%" }}>
- <Box flex={1}>
- <b>Total: </b>
- </Box>
- <Box flex={2}>ssss</Box>
- </div>
- );
- };
-
- interface TimesheetInputGridProps {
- setLockConfirm: (newLock: (oldLock: boolean) => boolean) => void;
- onClose?: () => void;
- }
-
- const initialRows: GridRowsProp = [
- {
- id: 1,
- projectCode: "M1001",
- task: "1.2",
- mon: 2.5,
- },
- {
- id: 2,
- projectCode: "M1002",
- task: "1.3",
- mon: 3.25,
- },
- ];
-
- const options = ["M1001", "M1301", "M1354", "M1973"];
- const options2 = [
- "1.1 - Preparation of preliminary Cost Estimate / Cost Plan",
- "1.2 - Cash flow forecast",
- "1.3 - Cost studies fo alterative design solutions",
- "1.4 = Attend design co-ordination / project review meetings",
- "1.5 - Prepare / Review RIC",
- ];
-
- const getDateForHeader = (date: dayjs.Dayjs, weekday: number) => {
- if (date.day() == 0) {
- return date.add(weekday - date.day() - 7, "day").format("DD MMM");
- } else {
- return date.add(weekday - date.day(), "day").format("DD MMM");
- }
- };
-
- const TimesheetInputGrid: React.FC<TimesheetInputGridProps> = ({
- ...props
- }) => {
- const [rows, setRows] = useState(initialRows);
- const [day, setDay] = useState(dayjs());
- const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>(
- {},
- );
- const { setLockConfirm } = props;
-
- const handleRowEditStop: GridEventListener<"rowEditStop"> = (
- params,
- event,
- ) => {
- if (params.reason === GridRowEditStopReasons.rowFocusOut) {
- event.defaultMuiPrevented = true;
- }
- };
-
- const handleEditClick = (id: GridRowId) => () => {
- setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.Edit } });
- };
-
- const handleSaveClick = (id: GridRowId) => () => {
- setRowModesModel({ ...rowModesModel, [id]: { mode: GridRowModes.View } });
- };
-
- const handleDeleteClick = (id: GridRowId) => () => {
- setRows(rows.filter((row) => row.id !== id));
- };
-
- const handleCancelClick = (id: GridRowId) => () => {
- setRowModesModel({
- ...rowModesModel,
- [id]: { mode: GridRowModes.View, ignoreModifications: true },
- });
-
- const editedRow = rows.find((row) => row.id === id);
- if (editedRow!.isNew) {
- setRows(rows.filter((row) => row.id !== id));
- }
- };
-
- const processRowUpdate = (newRow: GridRowModel) => {
- const updatedRow = { ...newRow, isNew: false };
- setRows(rows.map((row) => (row.id === newRow.id ? updatedRow : row)));
- return updatedRow;
- };
-
- const handleRowModesModelChange = (newRowModesModel: GridRowModesModel) => {
- setRowModesModel(newRowModesModel);
- };
-
- const getHoursTotal = (column: any) => {
- let sum = 0;
- rows.forEach((row) => {
- sum += row[column] ?? 0;
- });
- return sum;
- };
-
- const weekdayColConfig: any = {
- type: "number",
- // sortable: false,
- //width: 100,
- flex: 1,
- align: "left",
- headerAlign: "left",
- editable: true,
- renderEditCell: (value: any) => (
- <GridEditInputCell
- {...value}
- inputProps={{
- max: 24,
- min: 0,
- step: 0.25,
- }}
- />
- ),
- };
-
- const columns: GridColDef[] = [
- {
- field: "actions",
- type: "actions",
- headerName: "Actions",
- width: 100,
- cellClassName: "actions",
- getActions: ({ id }) => {
- const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
-
- if (isInEditMode) {
- return [
- <GridActionsCellItem
- key={`actions-${id}-save`}
- icon={<SaveIcon />}
- title="Save"
- label="Save"
- sx={{
- color: "primary.main",
- }}
- onClick={handleSaveClick(id)}
- />,
- <GridActionsCellItem
- key={`actions-${id}-cancel`}
- icon={<CancelIcon />}
- title="Cancel"
- label="Cancel"
- className="textPrimary"
- onClick={handleCancelClick(id)}
- color="inherit"
- />,
- ];
- }
-
- return [
- <GridActionsCellItem
- key={`actions-${id}-edit`}
- icon={<EditIcon />}
- title="Edit"
- label="Edit"
- className="textPrimary"
- onClick={handleEditClick(id)}
- color="inherit"
- />,
- <GridActionsCellItem
- key={`actions-${id}-delete`}
- title="Delete"
- label="Delete"
- icon={<DeleteIcon />}
- onClick={handleDeleteClick(id)}
- sx={{ color: "red" }}
- />,
- ];
- },
- },
- {
- field: "projectCode",
- headerName: "Project Code",
- // width: 220,
- flex: 2,
- editable: true,
- type: "singleSelect",
- valueOptions: options,
- },
- {
- field: "task",
- headerName: "Task",
- // width: 220,
- flex: 3,
- editable: true,
- type: "singleSelect",
- valueOptions: options2,
- },
- {
- // Mon
- field: "mon",
- ...weekdayColConfig,
- renderHeader: () => {
- return <div>Mon - {getDateForHeader(day, 1)}</div>;
- },
- },
- {
- // Tue
- field: "tue",
- ...weekdayColConfig,
- renderHeader: () => {
- return <div>Tue - {getDateForHeader(day, 2)}</div>;
- },
- },
- {
- // Wed
- field: "wed",
- ...weekdayColConfig,
- renderHeader: () => {
- return <div>Wed - {getDateForHeader(day, 3)}</div>;
- },
- },
- {
- // Thu
- field: "thu",
- ...weekdayColConfig,
- renderHeader: () => {
- return <div>Thu - {getDateForHeader(day, 4)}</div>;
- },
- },
- {
- // Fri
- field: "fri",
- ...weekdayColConfig,
- renderHeader: () => {
- return <div>Fri - {getDateForHeader(day, 5)}</div>;
- },
- },
- {
- // Sat
- field: "sat",
- ...weekdayColConfig,
- renderHeader: () => {
- return <div>Sat - {getDateForHeader(day, 6)}</div>;
- },
- },
- {
- // Sun
- field: "sun",
- ...weekdayColConfig,
- renderHeader: () => {
- return (
- <div style={{ color: "red" }}>Sun - {getDateForHeader(day, 7)}</div>
- );
- },
- },
- // {
- // field: 'joinDate',
- // headerName: 'Join date',
- // type: 'date',
- // width: 180,
- // editable: true,
- // },
- ];
-
- return (
- <Box
- sx={{
- // marginBottom: '-5px',
- display: "flex",
- "flex-direction": "column",
- // 'justify-content': 'flex-end',
- padding: "20px",
- height: "100%", //'30rem',
- width: "100%",
- "& .actions": {
- color: "text.secondary",
- },
- "& .header": {
- // border: 1,
- // 'border-width': '1px',
- // 'border-color': 'grey',
- },
- "& .textPrimary": {
- color: "text.primary",
- },
- }}
- >
- <DataGrid
- rows={rows}
- columns={columns}
- editMode="row"
- rowModesModel={rowModesModel}
- onRowModesModelChange={handleRowModesModelChange}
- onRowEditStop={handleRowEditStop}
- processRowUpdate={processRowUpdate}
- disableRowSelectionOnClick={true}
- disableColumnMenu={true}
- hideFooterPagination={true}
- slots={{
- toolbar: EditToolbar,
- // footer: EditFooter,
- }}
- slotProps={{
- toolbar: { setDay, setRows, setRowModesModel },
- // footer: { setDay, setRows, setRowModesModel },
- }}
- initialState={{
- pagination: { paginationModel: { pageSize: 100 } },
- }}
- sx={{ flex: 1 }}
- />
-
- <BottomBar
- getHoursTotal={getHoursTotal}
- setRows={setRows}
- setRowModesModel={setRowModesModel}
- setLockConfirm={setLockConfirm}
- // sx={{flex:3}}
- />
- </Box>
- );
- };
-
- export default TimesheetInputGrid;
|