({});
+ 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) => (
+
+ ),
+ };
+
+ const columns: GridColDef[] = [
+ {
+ field: 'actions',
+ type: 'actions',
+ headerName: '',
+ width: 100,
+ cellClassName: 'actions',
+ getActions: ({ id }) => {
+ const isInEditMode = rowModesModel[id]?.mode === GridRowModes.Edit;
+
+ if (isInEditMode) {
+ return [
+ }
+ title="Save"
+ label="Save"
+ sx={{
+ color: 'primary.main',
+ }}
+ onClick={handleSaveClick(id)}
+ />,
+ }
+ title="Cancel"
+ label="Cancel"
+ className="textPrimary"
+ onClick={handleCancelClick(id)}
+ color="inherit"
+ />,
+ ];
+ }
+
+ return [
+ }
+ title="Edit"
+ label="Edit"
+ className="textPrimary"
+ onClick={handleEditClick(id)}
+ color="inherit"
+ />,
+ }
+ 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 (
+ Mon - {getDateForHeader(day, 1)}
+ );
+ },
+ },
+ {
+ // Tue
+ field: 'tue',
+ ...weekdayColConfig,
+ renderHeader: () => {
+ return (
+ Tue - {getDateForHeader(day, 2)}
+ );
+ },
+ },
+ {
+ // Wed
+ field: 'wed',
+ ...weekdayColConfig,
+ renderHeader: () => {
+ return (
+ Wed - {getDateForHeader(day, 3)}
+ );
+ },
+ },
+ {
+ // Thu
+ field: 'thu',
+ ...weekdayColConfig,
+ renderHeader: () => {
+ return (
+ Thu - {getDateForHeader(day, 4)}
+ );
+ },
+ },
+ {
+ // Fri
+ field: 'fri',
+ ...weekdayColConfig,
+ renderHeader: () => {
+ return (
+ Fri - {getDateForHeader(day, 5)}
+ );
+ },
+ },
+ {
+ // Sat
+ field: 'sat',
+ ...weekdayColConfig,
+ renderHeader: () => {
+ return (
+ Sat - {getDateForHeader(day, 6)}
+ );
+ },
+ },
+ {
+ // Sun
+ field: 'sun',
+ ...weekdayColConfig,
+ renderHeader: () => {
+ return (
+ Sun - {getDateForHeader(day, 7)}
+ );
+ },
+ },
+ // {
+ // field: 'joinDate',
+ // headerName: 'Join date',
+ // type: 'date',
+ // width: 180,
+ // editable: true,
+ // },
+ ];
+
+ return (
+
+
+
+
+
+ );
+}
+
+export default TimesheetInputGrid;
diff --git a/src/components/EnterTimesheet/index.ts b/src/components/EnterTimesheet/index.ts
new file mode 100644
index 0000000..e070291
--- /dev/null
+++ b/src/components/EnterTimesheet/index.ts
@@ -0,0 +1 @@
+export { default } from "./EnterTimesheetModal";
diff --git a/src/components/Swal/CustomAlerts.js b/src/components/Swal/CustomAlerts.js
new file mode 100644
index 0000000..d8d5cdd
--- /dev/null
+++ b/src/components/Swal/CustomAlerts.js
@@ -0,0 +1,23 @@
+import Swal from "sweetalert2";
+
+
+export const msg = (text) => {
+ Swal.mixin({
+ toast: true,
+ position: "bottom-end",
+ showConfirmButton: false,
+ timer: 3000,
+ timerProgressBar: true,
+ didOpen: (toast) => {
+ toast.onmouseenter = Swal.stopTimer;
+ toast.onmouseleave = Swal.resumeTimer;
+ }
+ }).fire({
+ icon: "Success",
+ title: text
+ });
+}
+
+export const popup = (text) => {
+ Swal.fire(text);
+}
\ No newline at end of file
diff --git a/src/components/UserWorkspacePage/ProjectGrid.tsx b/src/components/UserWorkspacePage/ProjectGrid.tsx
new file mode 100644
index 0000000..53cc264
--- /dev/null
+++ b/src/components/UserWorkspacePage/ProjectGrid.tsx
@@ -0,0 +1,62 @@
+"use client";
+import * as React from "react";
+import Grid from "@mui/material/Grid";
+import { useEffect, useState } from 'react'
+import { TFunction } from "i18next";
+import { useTranslation } from "react-i18next";
+import {Card,CardContent,CardHeader} from '@mui/material';
+import CustomCardGrid from '../CustomCardGrid/CustomCardGrid';
+import '../../app/global.css';
+import { PROJECT_CARD_STYLE } from "@/theme/colorConst";
+
+interface ProjectGridProps {
+ tab: number;
+}
+
+
+const ProjectGrid: React.FC = (props) => {
+ const [items, setItems] = React.useState