diff --git a/src/app/api/projects/index.ts b/src/app/api/projects/index.ts
index 697ac98..90d1f4a 100644
--- a/src/app/api/projects/index.ts
+++ b/src/app/api/projects/index.ts
@@ -68,7 +68,6 @@ export interface AssignedProject extends ProjectWithTasks {
hoursSpent: number;
hoursSpentOther: number;
hoursAllocated: number;
- hoursAllocatedOther: number;
}
export const preloadProjects = () => {
diff --git a/src/app/utils/formatUtil.ts b/src/app/utils/formatUtil.ts
index 4d773e9..150b350 100644
--- a/src/app/utils/formatUtil.ts
+++ b/src/app/utils/formatUtil.ts
@@ -21,41 +21,52 @@ export const OUTPUT_DATE_FORMAT = "YYYY/MM/DD";
export const OUTPUT_TIME_FORMAT = "HH:mm:ss";
-export const convertDateToString = (date: Date, format: string = OUTPUT_DATE_FORMAT) => {
- return dayjs(date).format(format)
-}
+export const convertDateToString = (
+ date: Date,
+ format: string = OUTPUT_DATE_FORMAT,
+) => {
+ return dayjs(date).format(format);
+};
-export const convertDateArrayToString = (dateArray: number[], format: string = OUTPUT_DATE_FORMAT, needTime: boolean = false) => {
+export const convertDateArrayToString = (
+ dateArray: number[],
+ format: string = OUTPUT_DATE_FORMAT,
+ needTime: boolean = false,
+) => {
if (dateArray.length === 6) {
if (!needTime) {
- const dateString = `${dateArray[0]}-${dateArray[1]}-${dateArray[2]}`
- return dayjs(dateString).format(format)
+ const dateString = `${dateArray[0]}-${dateArray[1]}-${dateArray[2]}`;
+ return dayjs(dateString).format(format);
}
}
if (dateArray.length === 3) {
if (!needTime) {
- const dateString = `${dateArray[0]}-${dateArray[1]}-${dateArray[2]}`
- return dayjs(dateString).format(format)
+ const dateString = `${dateArray[0]}-${dateArray[1]}-${dateArray[2]}`;
+ return dayjs(dateString).format(format);
}
}
-}
+};
-export const convertTimeArrayToString = (timeArray: number[], format: string = OUTPUT_TIME_FORMAT, needTime: boolean = false) => {
- let timeString = '';
+export const convertTimeArrayToString = (
+ timeArray: number[],
+ format: string = OUTPUT_TIME_FORMAT,
+ needTime: boolean = false,
+) => {
+ let timeString = "";
if (timeArray !== null && timeArray !== undefined) {
- const hour = timeArray[0] || 0;
- const minute = timeArray[1] || 0;
-
- timeString = dayjs()
- .set('hour', hour)
- .set('minute', minute)
- .set('second', 0)
- .format('HH:mm:ss');
+ const hour = timeArray[0] || 0;
+ const minute = timeArray[1] || 0;
+
+ timeString = dayjs()
+ .set("hour", hour)
+ .set("minute", minute)
+ .set("second", 0)
+ .format("HH:mm:ss");
}
-
- return timeString
-}
+
+ return timeString;
+};
const shortDateFormatter_en = new Intl.DateTimeFormat("en-HK", {
weekday: "short",
@@ -81,6 +92,36 @@ export const shortDateFormatter = (locale?: string) => {
}
};
+const clockFormatOptions: Intl.DateTimeFormatOptions = {
+ year: "numeric",
+ month: "long",
+ day: "numeric",
+ weekday: "long",
+ hour: "2-digit",
+ minute: "2-digit",
+ second: "2-digit",
+ hour12: true,
+};
+
+const clockTimeFormatter_en = new Intl.DateTimeFormat(
+ "en-HK",
+ clockFormatOptions,
+);
+const clockTimeformatter_zh = new Intl.DateTimeFormat(
+ "zh-HK",
+ clockFormatOptions,
+);
+
+export const clockTimeFormatter = (locale?: string) => {
+ switch (locale) {
+ case "zh":
+ return clockTimeformatter_zh;
+ case "en":
+ default:
+ return clockTimeFormatter_en;
+ }
+};
+
export function convertLocaleStringToNumber(numberString: string): number {
const numberWithoutCommas = numberString.replace(/,/g, "");
return parseFloat(numberWithoutCommas);
@@ -91,6 +132,6 @@ export function timestampToDateString(timestamp: string): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, "0");
const day = String(date.getDate()).padStart(2, "0");
- console.log(`${year}-${month}-${day}`)
+ console.log(`${year}-${month}-${day}`);
return `${year}-${month}-${day}`;
-}
\ No newline at end of file
+}
diff --git a/src/components/Breadcrumb/Breadcrumb.tsx b/src/components/Breadcrumb/Breadcrumb.tsx
index 1679019..516aca2 100644
--- a/src/components/Breadcrumb/Breadcrumb.tsx
+++ b/src/components/Breadcrumb/Breadcrumb.tsx
@@ -7,7 +7,7 @@ import MUILink from "@mui/material/Link";
import { usePathname } from "next/navigation";
import { useTranslation } from "react-i18next";
import Clock from "./Clock";
-import { Grid } from "@mui/material";
+import { Box, Grid } from "@mui/material";
import { I18nProvider } from "@/i18n";
const pathToLabelMap: { [path: string]: string } = {
@@ -46,42 +46,43 @@ const Breadcrumb = () => {
// const { t } = useTranslation("customer");
-
return (
-
-
-
- {segments.map((segment, index) => {
- const href = segments.slice(0, index + 1).join("/");
- const label = pathToLabelMap[href] || segment;
+
+
+ {segments.map((segment, index) => {
+ const href = segments.slice(0, index + 1).join("/");
+ const label = pathToLabelMap[href] || segment;
- if (index === segments.length - 1) {
- return (
-
- {label}
- {/* {t(label)} */}
-
- );
- } else {
- return (
-
- {label}
-
- );
- }
- })}
-
-
-
-
-
-
+ if (index === segments.length - 1) {
+ return (
+
+ {label}
+ {/* {t(label)} */}
+
+ );
+ } else {
+ return (
+
+ {label}
+
+ );
+ }
+ })}
+
+
+
+
+
);
};
diff --git a/src/components/Breadcrumb/Clock.tsx b/src/components/Breadcrumb/Clock.tsx
index 8ddf42b..9e34340 100644
--- a/src/components/Breadcrumb/Clock.tsx
+++ b/src/components/Breadcrumb/Clock.tsx
@@ -1,32 +1,33 @@
-"use client"
-import { useState, useEffect, useLayoutEffect } from 'react';
-import Typography from "@mui/material/Typography";
-import { useTranslation } from 'react-i18next';
+"use client";
+import React, { useState, useLayoutEffect } from "react";
+import Typography, { TypographyProps } from "@mui/material/Typography";
+import { useTranslation } from "react-i18next";
+import { clockTimeFormatter } from "@/app/utils/formatUtil";
+import { NoSsr } from "@mui/material";
-const Clock = () => {
- const {
- i18n: { language },
- } = useTranslation();
- const [currentDateTime, setCurrentDateTime] = useState(new Date());
+const Clock: React.FC = (props) => {
+ const {
+ i18n: { language },
+ } = useTranslation();
+ const [currentDateTime, setCurrentDateTime] = useState(new Date());
- useLayoutEffect(() => {
- const timer = setInterval(() => {
- setCurrentDateTime(new Date());
- }, 1000);
+ useLayoutEffect(() => {
+ const timer = setInterval(() => {
+ setCurrentDateTime(new Date());
+ }, 1000);
- return () => {
- clearInterval(timer);
- };
- }, []);
+ return () => {
+ clearInterval(timer);
+ };
+ }, []);
- const options: Intl.DateTimeFormatOptions = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: true };
- const formattedDateTime = new Intl.DateTimeFormat(language, options).format(currentDateTime)
-
- return (
-
- {formattedDateTime}
-
- );
+ return (
+
+
+ {clockTimeFormatter(language).format(currentDateTime)}
+
+
+ );
};
export default Clock;
diff --git a/src/components/CreateProject/MilestoneSection.tsx b/src/components/CreateProject/MilestoneSection.tsx
index a6d6ccc..969f0c5 100644
--- a/src/components/CreateProject/MilestoneSection.tsx
+++ b/src/components/CreateProject/MilestoneSection.tsx
@@ -58,8 +58,8 @@ const MilestoneSection: React.FC = ({ taskGroupId }) => {
const apiRef = useGridApiRef();
const addRow = useCallback(() => {
// const id = Date.now();
- const minId = Math.min(...payments.map((payment) => payment.id!!));
- const id = minId >= 0 ? -1 : minId - 1
+ const minId = Math.min(...payments.map((payment) => payment.id!));
+ const id = minId >= 0 ? -1 : minId - 1;
setPayments((p) => [...p, { id, _isNew: true }]);
setRowModesModel((model) => ({
...model,
@@ -241,26 +241,30 @@ const MilestoneSection: React.FC = ({ taskGroupId }) => {
- {
- if (!date) return;
- const milestones = getValues("milestones");
- setValue("milestones", {
- ...milestones,
- [taskGroupId]: {
- ...milestones[taskGroupId],
- startDate: date.format(INPUT_DATE_FORMAT),
- },
- });
- }}
- slotProps={{
- textField: {
- error: startDate === "Invalid Date" || new Date(startDate) > new Date(endDate) || (Boolean(formState.errors.milestones) && !Boolean(startDate)),
- },
- }}
- />
+ {
+ if (!date) return;
+ const milestones = getValues("milestones");
+ setValue("milestones", {
+ ...milestones,
+ [taskGroupId]: {
+ ...milestones[taskGroupId],
+ startDate: date.format(INPUT_DATE_FORMAT),
+ },
+ });
+ }}
+ slotProps={{
+ textField: {
+ error:
+ startDate === "Invalid Date" ||
+ new Date(startDate) > new Date(endDate) ||
+ (Boolean(formState.errors.milestones) &&
+ !Boolean(startDate)),
+ },
+ }}
+ />
@@ -281,7 +285,11 @@ const MilestoneSection: React.FC = ({ taskGroupId }) => {
}}
slotProps={{
textField: {
- error: endDate === "Invalid Date" || new Date(startDate) > new Date(endDate) || (Boolean(formState.errors.milestones) && !Boolean(endDate)),
+ error:
+ endDate === "Invalid Date" ||
+ new Date(startDate) > new Date(endDate) ||
+ (Boolean(formState.errors.milestones) &&
+ !Boolean(endDate)),
},
}}
/>
diff --git a/src/components/PastEntryCalendar/PastEntryCalendar.tsx b/src/components/PastEntryCalendar/PastEntryCalendar.tsx
new file mode 100644
index 0000000..a9e6a14
--- /dev/null
+++ b/src/components/PastEntryCalendar/PastEntryCalendar.tsx
@@ -0,0 +1,106 @@
+import React from "react";
+import {
+ RecordTimesheetInput,
+ RecordLeaveInput,
+} from "@/app/api/timesheets/actions";
+import {
+ DateCalendar,
+ LocalizationProvider,
+ PickersDay,
+ PickersDayProps,
+} from "@mui/x-date-pickers";
+import { useTranslation } from "react-i18next";
+import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
+import dayjs, { Dayjs } from "dayjs";
+import "dayjs/locale/zh-hk";
+import timezone from "dayjs/plugin/timezone";
+import utc from "dayjs/plugin/utc";
+import { INPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
+
+dayjs.extend(utc);
+dayjs.extend(timezone);
+
+dayjs.tz.guess();
+
+export interface Props {
+ timesheet: RecordTimesheetInput;
+ leaves: RecordLeaveInput;
+ onDateSelect: (date: string) => void;
+}
+
+const getColor = (
+ hasTimeInput: boolean,
+ hasLeave: boolean,
+): string | undefined => {
+ if (hasTimeInput && hasLeave) {
+ return "success.light";
+ } else if (hasTimeInput) {
+ return "info.light";
+ } else if (hasLeave) {
+ return "warning.light";
+ } else {
+ return undefined;
+ }
+};
+
+const EntryDay: React.FC & Props> = ({
+ timesheet,
+ leaves,
+ ...pickerProps
+}) => {
+ const timesheetDays = Object.keys(timesheet);
+ const leaveDays = Object.keys(leaves);
+
+ const hasTimesheetInput = timesheetDays.some((day) =>
+ dayjs(day).isSame(pickerProps.day, "day"),
+ );
+
+ const hasLeaveInput = leaveDays.some((day) =>
+ dayjs(day).isSame(pickerProps.day, "day"),
+ );
+
+ return (
+
+ );
+};
+
+const PastEntryCalendar: React.FC = ({
+ timesheet,
+ leaves,
+ onDateSelect,
+}) => {
+ const {
+ i18n: { language },
+ } = useTranslation("home");
+
+ const onChange = (day: Dayjs) => {
+ onDateSelect(day.format(INPUT_DATE_FORMAT));
+ };
+
+ return (
+
+
+
+ );
+};
+
+export default PastEntryCalendar;
diff --git a/src/components/PastEntryCalendar/PastEntryCalendarModal.tsx b/src/components/PastEntryCalendar/PastEntryCalendarModal.tsx
new file mode 100644
index 0000000..53fd8dc
--- /dev/null
+++ b/src/components/PastEntryCalendar/PastEntryCalendarModal.tsx
@@ -0,0 +1,99 @@
+import {
+ Box,
+ Button,
+ Dialog,
+ DialogActions,
+ DialogContent,
+ DialogTitle,
+ Stack,
+ Typography,
+ styled,
+} from "@mui/material";
+import PastEntryCalendar, {
+ Props as PastEntryCalendarProps,
+} from "./PastEntryCalendar";
+import { useCallback, useState } from "react";
+import { useTranslation } from "react-i18next";
+import { ArrowBack } from "@mui/icons-material";
+
+interface Props extends Omit {
+ open: boolean;
+ handleClose: () => void;
+}
+
+const Indicator = styled(Box)(() => ({
+ borderRadius: "50%",
+ width: "1rem",
+ height: "1rem",
+}));
+
+const PastEntryCalendarModal: React.FC = ({
+ handleClose,
+ open,
+ timesheet,
+ leaves,
+}) => {
+ const { t } = useTranslation("home");
+
+ const [selectedDate, setSelectedDate] = useState("");
+
+ const clearDate = useCallback(() => {
+ setSelectedDate("");
+ }, []);
+
+ const onClose = useCallback(() => {
+ handleClose();
+ }, [handleClose]);
+
+ return (
+
+ );
+};
+
+export default PastEntryCalendarModal;
diff --git a/src/components/PastEntryCalendar/index.ts b/src/components/PastEntryCalendar/index.ts
new file mode 100644
index 0000000..1c7ee56
--- /dev/null
+++ b/src/components/PastEntryCalendar/index.ts
@@ -0,0 +1 @@
+export { default } from "./PastEntryCalendar";
diff --git a/src/components/StyledDataGrid/StyledDataGrid.tsx b/src/components/StyledDataGrid/StyledDataGrid.tsx
index 743d288..3ea0dce 100644
--- a/src/components/StyledDataGrid/StyledDataGrid.tsx
+++ b/src/components/StyledDataGrid/StyledDataGrid.tsx
@@ -28,6 +28,10 @@ const StyledDataGrid = styled(DataGrid)(({ theme }) => ({
borderRadius: 0,
maxHeight: 50,
},
+ "& .MuiAutocomplete-root .MuiFilledInput-root": {
+ borderRadius: 0,
+ maxHeight: 50,
+ },
}));
export default StyledDataGrid;
diff --git a/src/components/TimesheetTable/MobileTimesheetEntry.tsx b/src/components/TimesheetTable/MobileTimesheetEntry.tsx
index 9f709d8..03a0487 100644
--- a/src/components/TimesheetTable/MobileTimesheetEntry.tsx
+++ b/src/components/TimesheetTable/MobileTimesheetEntry.tsx
@@ -17,6 +17,7 @@ import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import TimesheetEditModal, {
Props as TimesheetEditModalProps,
} from "./TimesheetEditModal";
+import TimeEntryCard from "./TimeEntryCard";
interface Props {
date: string;
@@ -119,91 +120,13 @@ const MobileTimesheetEntry: React.FC = ({
const task = project?.tasks.find((t) => t.id === entry.taskId);
return (
-
-
-
-
-
- {project
- ? `${project.code} - ${project.name}`
- : t("Non-billable Task")}
-
- {task && (
-
- {task.name}
-
- )}
-
-
-
-
-
-
-
-
- {t("Hours")}
-
-
- {manhourFormatter.format(entry.inputHours || 0)}
-
-
-
-
- {t("Other Hours")}
-
-
- {manhourFormatter.format(entry.otHours || 0)}
-
-
-
- {entry.remark && (
-
-
- {t("Remark")}
-
- {entry.remark}
-
- )}
-
-
+ project={project}
+ task={task}
+ entry={entry}
+ onEdit={openEditModal(entry)}
+ />
);
})
) : (
diff --git a/src/components/TimesheetTable/ProjectSelect.tsx b/src/components/TimesheetTable/ProjectSelect.tsx
index 762512c..3c1ab51 100644
--- a/src/components/TimesheetTable/ProjectSelect.tsx
+++ b/src/components/TimesheetTable/ProjectSelect.tsx
@@ -10,6 +10,7 @@ import {
import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import { useTranslation } from "react-i18next";
import differenceBy from "lodash/differenceBy";
+import { TFunction } from "i18next";
interface Props {
allProjects: ProjectWithTasks[];
@@ -18,119 +19,159 @@ interface Props {
onProjectSelect: (projectId: number | string) => void;
}
-// const AutocompleteProjectSelect: React.FC = ({
-// allProjects,
-// assignedProjects,
-// value,
-// onProjectSelect,
-// }) => {
-// const { t } = useTranslation("home");
-// const nonAssignedProjects = useMemo(() => {
-// return differenceBy(allProjects, assignedProjects, "id");
-// }, [allProjects, assignedProjects]);
-
-// const options = useMemo(() => {
-// return [
-// {
-// value: "",
-// label: t("None"),
-// group: "non-billable",
-// },
-// ...assignedProjects.map((p) => ({
-// value: p.id,
-// label: `${p.code} - ${p.name}`,
-// group: "assigned",
-// })),
-// ...nonAssignedProjects.map((p) => ({
-// value: p.id,
-// label: `${p.code} - ${p.name}`,
-// group: "non-assigned",
-// })),
-// ];
-// }, [assignedProjects, nonAssignedProjects, t]);
-
-// return (
-// option.group}
-// getOptionLabel={(option) => option.label}
-// options={options}
-// renderInput={(params) => }
-// />
-// );
-// };
+const getGroupName = (t: TFunction, groupName: string): string => {
+ switch (groupName) {
+ case "non-billable":
+ return t("Non-billable");
+ case "assigned":
+ return t("Assigned Projects");
+ case "non-assigned":
+ return t("Non-assigned Projects");
+ default:
+ return t("Ungrouped");
+ }
+};
-const ProjectSelect: React.FC = ({
+const AutocompleteProjectSelect: React.FC = ({
allProjects,
assignedProjects,
value,
onProjectSelect,
}) => {
const { t } = useTranslation("home");
-
const nonAssignedProjects = useMemo(() => {
return differenceBy(allProjects, assignedProjects, "id");
}, [allProjects, assignedProjects]);
+ const options = useMemo(() => {
+ return [
+ {
+ value: "",
+ label: t("None"),
+ group: "non-billable",
+ },
+ ...assignedProjects.map((p) => ({
+ value: p.id,
+ label: `${p.code} - ${p.name}`,
+ group: "assigned",
+ })),
+ ...nonAssignedProjects.map((p) => ({
+ value: p.id,
+ label: `${p.code} - ${p.name}`,
+ group: "non-assigned",
+ })),
+ ];
+ }, [assignedProjects, nonAssignedProjects, t]);
+
+ const currentValue = options.find((o) => o.value === value) || options[0];
+
const onChange = useCallback(
- (event: SelectChangeEvent) => {
- const newValue = event.target.value;
- onProjectSelect(newValue);
+ (event: React.SyntheticEvent, newValue: { value: number | string }) => {
+ onProjectSelect(newValue.value);
},
[onProjectSelect],
);
return (
-
+ renderInput={(params) => }
+ />
);
};
-export default ProjectSelect;
+// const ProjectSelect: React.FC = ({
+// allProjects,
+// assignedProjects,
+// value,
+// onProjectSelect,
+// }) => {
+// const { t } = useTranslation("home");
+
+// const nonAssignedProjects = useMemo(() => {
+// return differenceBy(allProjects, assignedProjects, "id");
+// }, [allProjects, assignedProjects]);
+
+// const onChange = useCallback(
+// (event: SelectChangeEvent) => {
+// const newValue = event.target.value;
+// onProjectSelect(newValue);
+// },
+// [onProjectSelect],
+// );
+
+// return (
+//
+// );
+// };
+
+export default AutocompleteProjectSelect;
diff --git a/src/components/TimesheetTable/TimeEntryCard.tsx b/src/components/TimesheetTable/TimeEntryCard.tsx
new file mode 100644
index 0000000..445e182
--- /dev/null
+++ b/src/components/TimesheetTable/TimeEntryCard.tsx
@@ -0,0 +1,87 @@
+import { ProjectWithTasks } from "@/app/api/projects";
+import { Task } from "@/app/api/tasks";
+import { TimeEntry } from "@/app/api/timesheets/actions";
+import { manhourFormatter } from "@/app/utils/formatUtil";
+import { Edit } from "@mui/icons-material";
+import { Box, Card, CardContent, IconButton, Typography } from "@mui/material";
+import React from "react";
+import { useTranslation } from "react-i18next";
+
+interface Props {
+ project?: ProjectWithTasks;
+ task?: Task;
+ entry: TimeEntry;
+ onEdit?: () => void;
+}
+
+const TimeEntryCard: React.FC = ({ project, task, entry, onEdit }) => {
+ const { t } = useTranslation("home");
+ return (
+
+
+
+
+
+ {project
+ ? `${project.code} - ${project.name}`
+ : t("Non-billable Task")}
+
+ {task && (
+
+ {task.name}
+
+ )}
+
+ {onEdit && (
+
+
+
+ )}
+
+
+
+
+ {t("Hours")}
+
+
+ {manhourFormatter.format(entry.inputHours || 0)}
+
+
+
+
+ {t("Other Hours")}
+
+
+ {manhourFormatter.format(entry.otHours || 0)}
+
+
+
+ {entry.remark && (
+
+
+ {t("Remark")}
+
+ {entry.remark}
+
+ )}
+
+
+ );
+};
+
+export default TimeEntryCard;
diff --git a/src/components/UserWorkspacePage/ProjectGrid.tsx b/src/components/UserWorkspacePage/ProjectGrid.tsx
index ad44116..275d48d 100644
--- a/src/components/UserWorkspacePage/ProjectGrid.tsx
+++ b/src/components/UserWorkspacePage/ProjectGrid.tsx
@@ -56,9 +56,6 @@ const ProjectGrid: React.FC = ({ projects }) => {
)})`}
{/* Hours Allocated */}
-
- {t("Hours Allocated:")}
-
= ({ projects }) => {
alignItems: "baseline",
}}
>
- {t("Normal")}
+
+ {t("Hours Allocated:")}
+
{manhourFormatter.format(project.hoursAllocated)}
-
- {t("(Others)")}
- {`(${manhourFormatter.format(
- project.hoursAllocatedOther,
- )})`}
-
diff --git a/src/components/UserWorkspacePage/UserWorkspacePage.tsx b/src/components/UserWorkspacePage/UserWorkspacePage.tsx
index 062e233..0c8615f 100644
--- a/src/components/UserWorkspacePage/UserWorkspacePage.tsx
+++ b/src/components/UserWorkspacePage/UserWorkspacePage.tsx
@@ -5,7 +5,7 @@ import { useTranslation } from "react-i18next";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import { Add } from "@mui/icons-material";
-import { Typography } from "@mui/material";
+import { Box, Typography } from "@mui/material";
import ButtonGroup from "@mui/material/ButtonGroup";
import AssignedProjects from "./AssignedProjects";
import TimesheetModal from "../TimesheetModal";
@@ -16,6 +16,8 @@ import {
} from "@/app/api/timesheets/actions";
import LeaveModal from "../LeaveModal";
import { LeaveType } from "@/app/api/timesheets";
+import { CalendarIcon } from "@mui/x-date-pickers";
+import PastEntryCalendarModal from "../PastEntryCalendar/PastEntryCalendarModal";
export interface Props {
leaveTypes: LeaveType[];
@@ -36,6 +38,7 @@ const UserWorkspacePage: React.FC = ({
}) => {
const [isTimeheetModalVisible, setTimeheetModalVisible] = useState(false);
const [isLeaveModalVisible, setLeaveModalVisible] = useState(false);
+ const [isPastEventModalVisible, setPastEventModalVisible] = useState(false);
const { t } = useTranslation("home");
const handleAddTimesheetButtonClick = useCallback(() => {
@@ -54,6 +57,14 @@ const UserWorkspacePage: React.FC = ({
setLeaveModalVisible(false);
}, []);
+ const handlePastEventClick = useCallback(() => {
+ setPastEventModalVisible(true);
+ }, []);
+
+ const handlePastEventClose = useCallback(() => {
+ setPastEventModalVisible(false);
+ }, []);
+
return (
<>
= ({
{t("User Workspace")}
-
+
+ }
+ variant="outlined"
+ onClick={handlePastEventClick}
+ >
+ {t("View Past Entries")}
+
} onClick={handleAddTimesheetButtonClick}>
{t("Enter Time")}
@@ -79,8 +92,14 @@ const UserWorkspacePage: React.FC = ({
{t("Record Leave")}
-
+
+