| @@ -1,4 +1,10 @@ | |||
| import Holidays from "date-holidays"; | |||
| import { HolidaysResult } from "../api/holidays"; | |||
| import dayjs from "dayjs"; | |||
| import arraySupport from "dayjs/plugin/arraySupport"; | |||
| import { INPUT_DATE_FORMAT } from "./formatUtil"; | |||
| dayjs.extend(arraySupport); | |||
| const hd = new Holidays("HK"); | |||
| @@ -47,3 +53,20 @@ export const getPublicHolidaysForNYears = (years: number = 1) => { | |||
| }); | |||
| }); | |||
| }; | |||
| export const getHolidayForDate = ( | |||
| date: string, | |||
| companyHolidays: HolidaysResult[] = [], | |||
| ) => { | |||
| const currentYearHolidays: { date: string; title: string }[] = companyHolidays | |||
| .map((h) => ({ | |||
| title: h.name, | |||
| // Dayjs use 0-index for months, but not our API | |||
| date: dayjs([h.date[0], h.date[1] - 1, h.date[2]]).format( | |||
| INPUT_DATE_FORMAT, | |||
| ), | |||
| })) | |||
| .concat(getPublicHolidaysForNYears(1).concat()); | |||
| return currentYearHolidays.find((h) => h.date === date); | |||
| }; | |||
| @@ -0,0 +1,3 @@ | |||
| export const roundToNearestQuarter = (n: number): number => { | |||
| return Math.round(n / 0.25) * 0.25; | |||
| }; | |||
| @@ -20,9 +20,12 @@ import { | |||
| LEAVE_DAILY_MAX_HOURS, | |||
| TIMESHEET_DAILY_MAX_HOURS, | |||
| } from "@/app/api/timesheets/utils"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| import { getHolidayForDate } from "@/app/utils/holidayUtils"; | |||
| interface Props<EntryComponentProps = object> { | |||
| days: string[]; | |||
| companyHolidays: HolidaysResult[]; | |||
| leaveEntries: RecordLeaveInput; | |||
| timesheetEntries: RecordTimesheetInput; | |||
| EntryComponent: React.FunctionComponent< | |||
| @@ -37,6 +40,7 @@ function DateHoursList<EntryTableProps>({ | |||
| timesheetEntries, | |||
| EntryComponent, | |||
| entryComponentProps, | |||
| companyHolidays, | |||
| }: Props<EntryTableProps>) { | |||
| const { | |||
| t, | |||
| @@ -69,6 +73,11 @@ function DateHoursList<EntryTableProps>({ | |||
| <Box overflow="scroll" flex={1}> | |||
| {days.map((day, index) => { | |||
| const dayJsObj = dayjs(day); | |||
| const holiday = getHolidayForDate(day, companyHolidays); | |||
| const isHoliday = | |||
| holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6; | |||
| const leaves = leaveEntries[day]; | |||
| const leaveHours = | |||
| leaves?.reduce((acc, entry) => acc + entry.inputHours, 0) || 0; | |||
| @@ -97,10 +106,16 @@ function DateHoursList<EntryTableProps>({ | |||
| variant="overline" | |||
| component="div" | |||
| sx={{ | |||
| color: dayJsObj.day() === 0 ? "error.main" : undefined, | |||
| color: isHoliday ? "error.main" : undefined, | |||
| }} | |||
| > | |||
| {shortDateFormatter(language).format(dayJsObj.toDate())} | |||
| {holiday && ( | |||
| <Typography | |||
| marginInlineStart={1} | |||
| variant="caption" | |||
| >{`(${holiday.title})`}</Typography> | |||
| )} | |||
| </Typography> | |||
| <Stack spacing={1}> | |||
| <Box | |||
| @@ -15,6 +15,7 @@ import { | |||
| TableHead, | |||
| TableRow, | |||
| Tooltip, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import dayjs from "dayjs"; | |||
| import React, { useState } from "react"; | |||
| @@ -23,11 +24,14 @@ import { | |||
| LEAVE_DAILY_MAX_HOURS, | |||
| TIMESHEET_DAILY_MAX_HOURS, | |||
| } from "@/app/api/timesheets/utils"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| import { getHolidayForDate } from "@/app/utils/holidayUtils"; | |||
| interface Props<EntryTableProps = object> { | |||
| days: string[]; | |||
| leaveEntries: RecordLeaveInput; | |||
| timesheetEntries: RecordTimesheetInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| EntryTableComponent: React.FunctionComponent< | |||
| EntryTableProps & { day: string } | |||
| >; | |||
| @@ -40,6 +44,7 @@ function DateHoursTable<EntryTableProps>({ | |||
| entryTableProps, | |||
| leaveEntries, | |||
| timesheetEntries, | |||
| companyHolidays, | |||
| }: Props<EntryTableProps>) { | |||
| const { t } = useTranslation("home"); | |||
| @@ -61,6 +66,7 @@ function DateHoursTable<EntryTableProps>({ | |||
| <DayRow | |||
| key={`${day}${index}`} | |||
| day={day} | |||
| companyHolidays={companyHolidays} | |||
| leaveEntries={leaveEntries} | |||
| timesheetEntries={timesheetEntries} | |||
| EntryTableComponent={EntryTableComponent} | |||
| @@ -80,8 +86,10 @@ function DayRow<EntryTableProps>({ | |||
| timesheetEntries, | |||
| entryTableProps, | |||
| EntryTableComponent, | |||
| companyHolidays | |||
| }: { | |||
| day: string; | |||
| companyHolidays: HolidaysResult[]; | |||
| leaveEntries: RecordLeaveInput; | |||
| timesheetEntries: RecordTimesheetInput; | |||
| EntryTableComponent: React.FunctionComponent< | |||
| @@ -96,6 +104,9 @@ function DayRow<EntryTableProps>({ | |||
| const dayJsObj = dayjs(day); | |||
| const [open, setOpen] = useState(false); | |||
| const holiday = getHolidayForDate(day, companyHolidays); | |||
| const isHoliday = holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6; | |||
| const leaves = leaveEntries[day]; | |||
| const leaveHours = | |||
| leaves?.reduce((acc, entry) => acc + entry.inputHours, 0) || 0; | |||
| @@ -125,10 +136,14 @@ function DayRow<EntryTableProps>({ | |||
| {open ? <KeyboardArrowUp /> : <KeyboardArrowDown />} | |||
| </IconButton> | |||
| </TableCell> | |||
| <TableCell | |||
| sx={{ color: dayJsObj.day() === 0 ? "error.main" : undefined }} | |||
| > | |||
| <TableCell sx={{ color: isHoliday ? "error.main" : undefined }}> | |||
| {shortDateFormatter(language).format(dayJsObj.toDate())} | |||
| {holiday && ( | |||
| <Typography | |||
| display="block" | |||
| variant="caption" | |||
| >{`(${holiday.title})`}</Typography> | |||
| )} | |||
| </TableCell> | |||
| {/* Timesheet */} | |||
| <TableCell>{manhourFormatter.format(timesheetHours)}</TableCell> | |||
| @@ -25,6 +25,7 @@ import { LeaveType } from "@/app/api/timesheets"; | |||
| import FullscreenModal from "../FullscreenModal"; | |||
| import MobileLeaveTable from "../LeaveTable/MobileLeaveTable"; | |||
| import useIsMobile from "@/app/utils/useIsMobile"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| interface Props { | |||
| isOpen: boolean; | |||
| @@ -33,6 +34,7 @@ interface Props { | |||
| defaultLeaveRecords?: RecordLeaveInput; | |||
| leaveTypes: LeaveType[]; | |||
| timesheetRecords: RecordTimesheetInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const modalSx: SxProps = { | |||
| @@ -52,6 +54,7 @@ const LeaveModal: React.FC<Props> = ({ | |||
| defaultLeaveRecords, | |||
| timesheetRecords, | |||
| leaveTypes, | |||
| companyHolidays, | |||
| }) => { | |||
| const { t } = useTranslation("home"); | |||
| @@ -127,6 +130,7 @@ const LeaveModal: React.FC<Props> = ({ | |||
| }} | |||
| > | |||
| <LeaveTable | |||
| companyHolidays={companyHolidays} | |||
| leaveTypes={leaveTypes} | |||
| timesheetRecords={timesheetRecords} | |||
| /> | |||
| @@ -165,6 +169,7 @@ const LeaveModal: React.FC<Props> = ({ | |||
| {t("Record Leave")} | |||
| </Typography> | |||
| <MobileLeaveTable | |||
| companyHolidays={companyHolidays} | |||
| leaveTypes={leaveTypes} | |||
| timesheetRecords={timesheetRecords} | |||
| /> | |||
| @@ -1,5 +1,6 @@ | |||
| import { LeaveType } from "@/app/api/timesheets"; | |||
| import { LeaveEntry } from "@/app/api/timesheets/actions"; | |||
| import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | |||
| import { Check, Delete } from "@mui/icons-material"; | |||
| import { | |||
| Box, | |||
| @@ -98,7 +99,7 @@ const LeaveEditModal: React.FC<Props> = ({ | |||
| label={t("Hours")} | |||
| fullWidth | |||
| {...register("inputHours", { | |||
| valueAsNumber: true, | |||
| setValueAs: (value) => roundToNearestQuarter(parseFloat(value)), | |||
| validate: (value) => value > 0, | |||
| })} | |||
| error={Boolean(formState.errors.inputHours)} | |||
| @@ -22,6 +22,7 @@ import dayjs from "dayjs"; | |||
| import isBetween from "dayjs/plugin/isBetween"; | |||
| import { LeaveType } from "@/app/api/timesheets"; | |||
| import { isValidLeaveEntry } from "@/app/api/timesheets/utils"; | |||
| import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | |||
| dayjs.extend(isBetween); | |||
| @@ -173,6 +174,9 @@ const EntryInputTable: React.FC<Props> = ({ day, leaveTypes }) => { | |||
| width: 150, | |||
| editable: true, | |||
| type: "number", | |||
| valueParser(value) { | |||
| return value ? roundToNearestQuarter(value) : value; | |||
| }, | |||
| valueFormatter(params) { | |||
| return manhourFormatter.format(params.value); | |||
| }, | |||
| @@ -7,19 +7,26 @@ import { useFormContext } from "react-hook-form"; | |||
| import LeaveEntryTable from "./LeaveEntryTable"; | |||
| import { LeaveType } from "@/app/api/timesheets"; | |||
| import DateHoursTable from "../DateHoursTable"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| interface Props { | |||
| leaveTypes: LeaveType[]; | |||
| timesheetRecords: RecordTimesheetInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const LeaveTable: React.FC<Props> = ({ leaveTypes, timesheetRecords }) => { | |||
| const LeaveTable: React.FC<Props> = ({ | |||
| leaveTypes, | |||
| timesheetRecords, | |||
| companyHolidays, | |||
| }) => { | |||
| const { watch } = useFormContext<RecordLeaveInput>(); | |||
| const currentInput = watch(); | |||
| const days = Object.keys(currentInput); | |||
| return ( | |||
| <DateHoursTable | |||
| companyHolidays={companyHolidays} | |||
| days={days} | |||
| leaveEntries={currentInput} | |||
| timesheetEntries={timesheetRecords} | |||
| @@ -1,33 +1,35 @@ | |||
| import { LeaveType } from "@/app/api/timesheets"; | |||
| import { LeaveEntry, RecordLeaveInput } from "@/app/api/timesheets/actions"; | |||
| import { manhourFormatter, shortDateFormatter } from "@/app/utils/formatUtil"; | |||
| import { Add, Edit } from "@mui/icons-material"; | |||
| import { | |||
| Box, | |||
| Button, | |||
| Card, | |||
| CardContent, | |||
| IconButton, | |||
| Typography, | |||
| } from "@mui/material"; | |||
| import { shortDateFormatter } from "@/app/utils/formatUtil"; | |||
| import { Add } from "@mui/icons-material"; | |||
| import { Box, Button, Typography } from "@mui/material"; | |||
| import dayjs from "dayjs"; | |||
| import React, { useCallback, useMemo, useState } from "react"; | |||
| import { useFormContext } from "react-hook-form"; | |||
| import { useTranslation } from "react-i18next"; | |||
| import LeaveEditModal, { Props as LeaveEditModalProps } from "./LeaveEditModal"; | |||
| import LeaveEntryCard from "./LeaveEntryCard"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| import { getHolidayForDate } from "@/app/utils/holidayUtils"; | |||
| interface Props { | |||
| date: string; | |||
| leaveTypes: LeaveType[]; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const MobileLeaveEntry: React.FC<Props> = ({ date, leaveTypes }) => { | |||
| const MobileLeaveEntry: React.FC<Props> = ({ | |||
| date, | |||
| leaveTypes, | |||
| companyHolidays, | |||
| }) => { | |||
| const { | |||
| t, | |||
| i18n: { language }, | |||
| } = useTranslation("home"); | |||
| const dayJsObj = dayjs(date); | |||
| const holiday = getHolidayForDate(date, companyHolidays); | |||
| const isHoliday = holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6; | |||
| const leaveTypeMap = useMemo<{ [id: LeaveType["id"]]: LeaveType }>(() => { | |||
| return leaveTypes.reduce( | |||
| @@ -91,9 +93,15 @@ const MobileLeaveEntry: React.FC<Props> = ({ date, leaveTypes }) => { | |||
| <Typography | |||
| paddingInline={2} | |||
| variant="overline" | |||
| color={dayJsObj.day() === 0 ? "error.main" : undefined} | |||
| color={isHoliday ? "error.main" : undefined} | |||
| > | |||
| {shortDateFormatter(language).format(dayJsObj.toDate())} | |||
| {holiday && ( | |||
| <Typography | |||
| marginInlineStart={1} | |||
| variant="caption" | |||
| >{`(${holiday.title})`}</Typography> | |||
| )} | |||
| </Typography> | |||
| <Box | |||
| paddingInline={2} | |||
| @@ -7,15 +7,18 @@ import { useFormContext } from "react-hook-form"; | |||
| import { LeaveType } from "@/app/api/timesheets"; | |||
| import MobileLeaveEntry from "./MobileLeaveEntry"; | |||
| import DateHoursList from "../DateHoursTable/DateHoursList"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| interface Props { | |||
| leaveTypes: LeaveType[]; | |||
| timesheetRecords: RecordTimesheetInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const MobileLeaveTable: React.FC<Props> = ({ | |||
| timesheetRecords, | |||
| leaveTypes, | |||
| companyHolidays, | |||
| }) => { | |||
| const { watch } = useFormContext<RecordLeaveInput>(); | |||
| const currentInput = watch(); | |||
| @@ -24,10 +27,11 @@ const MobileLeaveTable: React.FC<Props> = ({ | |||
| return ( | |||
| <DateHoursList | |||
| days={days} | |||
| companyHolidays={companyHolidays} | |||
| leaveEntries={currentInput} | |||
| timesheetEntries={timesheetRecords} | |||
| EntryComponent={MobileLeaveEntry} | |||
| entryComponentProps={{ leaveTypes }} | |||
| entryComponentProps={{ leaveTypes, companyHolidays }} | |||
| /> | |||
| ); | |||
| }; | |||
| @@ -25,6 +25,7 @@ import { AssignedProject, ProjectWithTasks } from "@/app/api/projects"; | |||
| import FullscreenModal from "../FullscreenModal"; | |||
| import MobileTimesheetTable from "../TimesheetTable/MobileTimesheetTable"; | |||
| import useIsMobile from "@/app/utils/useIsMobile"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| interface Props { | |||
| isOpen: boolean; | |||
| @@ -34,6 +35,7 @@ interface Props { | |||
| username: string; | |||
| defaultTimesheets?: RecordTimesheetInput; | |||
| leaveRecords: RecordLeaveInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const modalSx: SxProps = { | |||
| @@ -54,6 +56,7 @@ const TimesheetModal: React.FC<Props> = ({ | |||
| username, | |||
| defaultTimesheets, | |||
| leaveRecords, | |||
| companyHolidays, | |||
| }) => { | |||
| const { t } = useTranslation("home"); | |||
| @@ -129,6 +132,7 @@ const TimesheetModal: React.FC<Props> = ({ | |||
| }} | |||
| > | |||
| <TimesheetTable | |||
| companyHolidays={companyHolidays} | |||
| assignedProjects={assignedProjects} | |||
| allProjects={allProjects} | |||
| leaveRecords={leaveRecords} | |||
| @@ -168,6 +172,7 @@ const TimesheetModal: React.FC<Props> = ({ | |||
| {t("Timesheet Input")} | |||
| </Typography> | |||
| <MobileTimesheetTable | |||
| companyHolidays={companyHolidays} | |||
| assignedProjects={assignedProjects} | |||
| allProjects={allProjects} | |||
| leaveRecords={leaveRecords} | |||
| @@ -28,6 +28,7 @@ import ProjectSelect from "./ProjectSelect"; | |||
| import TaskGroupSelect from "./TaskGroupSelect"; | |||
| import TaskSelect from "./TaskSelect"; | |||
| import { isValidTimeEntry } from "@/app/api/timesheets/utils"; | |||
| import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | |||
| dayjs.extend(isBetween); | |||
| @@ -308,6 +309,9 @@ const EntryInputTable: React.FC<Props> = ({ | |||
| width: 100, | |||
| editable: true, | |||
| type: "number", | |||
| valueParser(value) { | |||
| return value ? roundToNearestQuarter(value) : value; | |||
| }, | |||
| valueFormatter(params) { | |||
| return manhourFormatter.format(params.value || 0); | |||
| }, | |||
| @@ -318,6 +322,9 @@ const EntryInputTable: React.FC<Props> = ({ | |||
| width: 150, | |||
| editable: true, | |||
| type: "number", | |||
| valueParser(value) { | |||
| return value ? roundToNearestQuarter(value) : value; | |||
| }, | |||
| valueFormatter(params) { | |||
| return manhourFormatter.format(params.value || 0); | |||
| }, | |||
| @@ -18,17 +18,21 @@ import TimesheetEditModal, { | |||
| Props as TimesheetEditModalProps, | |||
| } from "./TimesheetEditModal"; | |||
| import TimeEntryCard from "./TimeEntryCard"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| import { getHolidayForDate } from "@/app/utils/holidayUtils"; | |||
| interface Props { | |||
| date: string; | |||
| allProjects: ProjectWithTasks[]; | |||
| assignedProjects: AssignedProject[]; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const MobileTimesheetEntry: React.FC<Props> = ({ | |||
| date, | |||
| allProjects, | |||
| assignedProjects, | |||
| companyHolidays, | |||
| }) => { | |||
| const { | |||
| t, | |||
| @@ -44,6 +48,9 @@ const MobileTimesheetEntry: React.FC<Props> = ({ | |||
| }, [allProjects]); | |||
| const dayJsObj = dayjs(date); | |||
| const holiday = getHolidayForDate(date, companyHolidays); | |||
| const isHoliday = holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6; | |||
| const { watch, setValue } = useFormContext<RecordTimesheetInput>(); | |||
| const currentEntries = watch(date); | |||
| @@ -99,9 +106,15 @@ const MobileTimesheetEntry: React.FC<Props> = ({ | |||
| <Typography | |||
| paddingInline={2} | |||
| variant="overline" | |||
| color={dayJsObj.day() === 0 ? "error.main" : undefined} | |||
| color={isHoliday ? "error.main" : undefined} | |||
| > | |||
| {shortDateFormatter(language).format(dayJsObj.toDate())} | |||
| {holiday && ( | |||
| <Typography | |||
| marginInlineStart={1} | |||
| variant="caption" | |||
| >{`(${holiday.title})`}</Typography> | |||
| )} | |||
| </Typography> | |||
| <Box | |||
| paddingInline={2} | |||
| @@ -7,17 +7,20 @@ import { useFormContext } from "react-hook-form"; | |||
| import DateHoursList from "../DateHoursTable/DateHoursList"; | |||
| import { AssignedProject, ProjectWithTasks } from "@/app/api/projects"; | |||
| import MobileTimesheetEntry from "./MobileTimesheetEntry"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| interface Props { | |||
| allProjects: ProjectWithTasks[]; | |||
| assignedProjects: AssignedProject[]; | |||
| leaveRecords: RecordLeaveInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const MobileTimesheetTable: React.FC<Props> = ({ | |||
| allProjects, | |||
| assignedProjects, | |||
| leaveRecords, | |||
| companyHolidays, | |||
| }) => { | |||
| const { watch } = useFormContext<RecordTimesheetInput>(); | |||
| const currentInput = watch(); | |||
| @@ -26,10 +29,11 @@ const MobileTimesheetTable: React.FC<Props> = ({ | |||
| return ( | |||
| <DateHoursList | |||
| days={days} | |||
| companyHolidays={companyHolidays} | |||
| leaveEntries={leaveRecords} | |||
| timesheetEntries={currentInput} | |||
| EntryComponent={MobileTimesheetEntry} | |||
| entryComponentProps={{ allProjects, assignedProjects }} | |||
| entryComponentProps={{ allProjects, assignedProjects, companyHolidays }} | |||
| /> | |||
| ); | |||
| }; | |||
| @@ -20,6 +20,7 @@ import TaskGroupSelect from "./TaskGroupSelect"; | |||
| import TaskSelect from "./TaskSelect"; | |||
| import { TaskGroup } from "@/app/api/tasks"; | |||
| import uniqBy from "lodash/uniqBy"; | |||
| import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | |||
| export interface Props extends Omit<ModalProps, "children"> { | |||
| onSave: (leaveEntry: TimeEntry) => void; | |||
| @@ -196,8 +197,9 @@ const TimesheetEditModal: React.FC<Props> = ({ | |||
| label={t("Hours")} | |||
| fullWidth | |||
| {...register("inputHours", { | |||
| valueAsNumber: true, | |||
| validate: (value) => Boolean(value || otHours), | |||
| setValueAs: (value) => roundToNearestQuarter(parseFloat(value)), | |||
| validate: (value) => | |||
| value ? value > 0 : Boolean(value || otHours), | |||
| })} | |||
| error={Boolean(formState.errors.inputHours)} | |||
| /> | |||
| @@ -206,7 +208,8 @@ const TimesheetEditModal: React.FC<Props> = ({ | |||
| label={t("Other Hours")} | |||
| fullWidth | |||
| {...register("otHours", { | |||
| valueAsNumber: true, | |||
| setValueAs: (value) => roundToNearestQuarter(parseFloat(value)), | |||
| validate: (value) => (value ? value > 0 : true), | |||
| })} | |||
| error={Boolean(formState.errors.otHours)} | |||
| /> | |||
| @@ -7,17 +7,20 @@ import { useFormContext } from "react-hook-form"; | |||
| import EntryInputTable from "./EntryInputTable"; | |||
| import { AssignedProject, ProjectWithTasks } from "@/app/api/projects"; | |||
| import DateHoursTable from "../DateHoursTable"; | |||
| import { HolidaysResult } from "@/app/api/holidays"; | |||
| interface Props { | |||
| allProjects: ProjectWithTasks[]; | |||
| assignedProjects: AssignedProject[]; | |||
| leaveRecords: RecordLeaveInput; | |||
| companyHolidays: HolidaysResult[]; | |||
| } | |||
| const TimesheetTable: React.FC<Props> = ({ | |||
| allProjects, | |||
| assignedProjects, | |||
| leaveRecords, | |||
| companyHolidays, | |||
| }) => { | |||
| const { watch } = useFormContext<RecordTimesheetInput>(); | |||
| const currentInput = watch(); | |||
| @@ -25,6 +28,7 @@ const TimesheetTable: React.FC<Props> = ({ | |||
| return ( | |||
| <DateHoursTable | |||
| companyHolidays={companyHolidays} | |||
| days={days} | |||
| leaveEntries={leaveRecords} | |||
| timesheetEntries={currentInput} | |||
| @@ -37,7 +37,7 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||
| username, | |||
| defaultLeaveRecords, | |||
| defaultTimesheets, | |||
| holidays | |||
| holidays, | |||
| }) => { | |||
| const [isTimeheetModalVisible, setTimeheetModalVisible] = useState(false); | |||
| const [isLeaveModalVisible, setLeaveModalVisible] = useState(false); | |||
| @@ -106,6 +106,7 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||
| leaveTypes={leaveTypes} | |||
| /> | |||
| <TimesheetModal | |||
| companyHolidays={holidays} | |||
| isOpen={isTimeheetModalVisible} | |||
| onClose={handleCloseTimesheetModal} | |||
| allProjects={allProjects} | |||
| @@ -115,6 +116,7 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||
| leaveRecords={defaultLeaveRecords} | |||
| /> | |||
| <LeaveModal | |||
| companyHolidays={holidays} | |||
| leaveTypes={leaveTypes} | |||
| isOpen={isLeaveModalVisible} | |||
| onClose={handleCloseLeaveModal} | |||