Преглед изворни кода

Remove unused components

tags/Baseline_30082024_FRONTEND_UAT
Wayne пре 1 година
родитељ
комит
59d318404d
8 измењених фајлова са 7 додато и 830 уклоњено
  1. +4
    -0
      src/components/TimesheetAmendment/TimesheetAmendment.tsx
  2. +2
    -0
      src/components/TimesheetAmendment/TimesheetAmendmentModal.tsx
  3. +0
    -535
      src/components/TimesheetTable/EntryInputTable.tsx
  4. +0
    -200
      src/components/TimesheetTable/MobileTimesheetEntry.tsx
  5. +0
    -51
      src/components/TimesheetTable/MobileTimesheetTable.tsx
  6. +0
    -43
      src/components/TimesheetTable/TimesheetTable.tsx
  7. +0
    -1
      src/components/TimesheetTable/index.ts
  8. +1
    -0
      src/components/UserWorkspacePage/UserWorkspacePage.tsx

+ 4
- 0
src/components/TimesheetAmendment/TimesheetAmendment.tsx Прегледај датотеку

@@ -42,6 +42,7 @@ import dayjs from "dayjs";
import { checkTotalHours } from "@/app/api/timesheets/utils"; import { checkTotalHours } from "@/app/api/timesheets/utils";
import unionBy from "lodash/unionBy"; import unionBy from "lodash/unionBy";
import { Luggage, MoreTime } from "@mui/icons-material"; import { Luggage, MoreTime } from "@mui/icons-material";
import { Task } from "@/app/api/tasks";


export interface Props { export interface Props {
leaveTypes: LeaveType[]; leaveTypes: LeaveType[];
@@ -49,6 +50,7 @@ export interface Props {
teamTimesheets: TeamTimeSheets; teamTimesheets: TeamTimeSheets;
companyHolidays: HolidaysResult[]; companyHolidays: HolidaysResult[];
allProjects: ProjectWithTasks[]; allProjects: ProjectWithTasks[];
miscTasks: Task[];
} }


type MemberOption = TeamTimeSheets[0] & TeamLeaves[0] & { id: string }; type MemberOption = TeamTimeSheets[0] & TeamLeaves[0] & { id: string };
@@ -76,6 +78,7 @@ const TimesheetAmendment: React.FC<Props> = ({
companyHolidays, companyHolidays,
allProjects, allProjects,
leaveTypes, leaveTypes,
miscTasks,
}) => { }) => {
const { t } = useTranslation(["home", "common"]); const { t } = useTranslation(["home", "common"]);


@@ -459,6 +462,7 @@ const TimesheetAmendment: React.FC<Props> = ({
open={editModalOpen} open={editModalOpen}
onClose={closeEditModal} onClose={closeEditModal}
onSave={handleSave} onSave={handleSave}
miscTasks={miscTasks}
{...editModalProps} {...editModalProps}
/> />
<LeaveEditModal <LeaveEditModal


+ 2
- 0
src/components/TimesheetAmendment/TimesheetAmendmentModal.tsx Прегледај датотеку

@@ -37,6 +37,7 @@ export const TimesheetAmendmentModal: React.FC<Props> = ({
teamTimesheets, teamTimesheets,
companyHolidays, companyHolidays,
allProjects, allProjects,
miscTasks,
}) => { }) => {
const { t } = useTranslation("home"); const { t } = useTranslation("home");
const isMobile = useIsMobile(); const isMobile = useIsMobile();
@@ -49,6 +50,7 @@ export const TimesheetAmendmentModal: React.FC<Props> = ({
companyHolidays={companyHolidays} companyHolidays={companyHolidays}
teamTimesheets={teamTimesheets} teamTimesheets={teamTimesheets}
allProjects={allProjects} allProjects={allProjects}
miscTasks={miscTasks}
/> />
); );




+ 0
- 535
src/components/TimesheetTable/EntryInputTable.tsx Прегледај датотеку

@@ -1,535 +0,0 @@
import { Add, Check, Close, Delete } from "@mui/icons-material";
import { Box, Button, Tooltip, Typography } from "@mui/material";
import {
FooterPropsOverrides,
GridActionsCellItem,
GridCellParams,
GridColDef,
GridEditInputCell,
GridEventListener,
GridRenderEditCellParams,
GridRowId,
GridRowModel,
GridRowModes,
GridRowModesModel,
GridToolbarContainer,
useGridApiRef,
} from "@mui/x-data-grid";
import { useTranslation } from "react-i18next";
import StyledDataGrid from "../StyledDataGrid";
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useFormContext } from "react-hook-form";
import { RecordTimesheetInput, TimeEntry } from "@/app/api/timesheets/actions";
import { manhourFormatter } from "@/app/utils/formatUtil";
import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import uniqBy from "lodash/uniqBy";
import { TaskGroup } from "@/app/api/tasks";
import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
import ProjectSelect from "./ProjectSelect";
import TaskGroupSelect from "./TaskGroupSelect";
import TaskSelect from "./TaskSelect";
import {
DAILY_NORMAL_MAX_HOURS,
TimeEntryError,
validateTimeEntry,
} from "@/app/api/timesheets/utils";
import { roundToNearestQuarter } from "@/app/utils/manhourUtils";
import FastTimeEntryModal from "./FastTimeEntryModal";

dayjs.extend(isBetween);

interface Props {
day: string;
isHoliday: boolean;
allProjects: ProjectWithTasks[];
assignedProjects: AssignedProject[];
fastEntryEnabled?: boolean;
}

export type TimeEntryRow = Partial<
TimeEntry & {
_isNew: boolean;
_error: TimeEntryError;
isPlanned?: boolean;
}
>;

const EntryInputTable: React.FC<Props> = ({
day,
allProjects,
assignedProjects,
isHoliday,
fastEntryEnabled,
}) => {
const { t } = useTranslation("home");
const taskGroupsByProject = useMemo(() => {
return allProjects.reduce<{
[projectId: AssignedProject["id"]]: {
value: TaskGroup["id"];
label: string;
}[];
}>((acc, project) => {
return {
...acc,
[project.id]: uniqBy(
project.tasks.map((t) => ({
value: t.taskGroup.id,
label: t.taskGroup.name,
})),
"value",
),
};
}, {});
}, [allProjects]);

// To check for start / end planned dates
const milestonesByProject = useMemo(() => {
return assignedProjects.reduce<{
[projectId: AssignedProject["id"]]: AssignedProject["milestones"];
}>((acc, project) => {
return { ...acc, [project.id]: { ...project.milestones } };
}, {});
}, [assignedProjects]);

const { getValues, setValue, clearErrors } =
useFormContext<RecordTimesheetInput>();
const currentEntries = getValues(day);

const [entries, setEntries] = useState<TimeEntryRow[]>(currentEntries || []);

const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});

const apiRef = useGridApiRef();
const addRow = useCallback(() => {
const id = Date.now();
setEntries((e) => [...e, { id, _isNew: true }]);
setRowModesModel((model) => ({
...model,
[id]: { mode: GridRowModes.Edit, fieldToFocus: "projectId" },
}));
}, []);

const validateRow = useCallback(
(id: GridRowId) => {
const row = apiRef.current.getRowWithUpdatedValues(
id,
"",
) as TimeEntryRow;

const error = validateTimeEntry(row, isHoliday);

// Test for warnings
let isPlanned;
if (
row.projectId &&
row.taskGroupId &&
milestonesByProject[row.projectId]
) {
const milestone =
milestonesByProject[row.projectId][row.taskGroupId] || {};
const { startDate, endDate } = milestone;
// Check if the current day is between the start and end date inclusively
isPlanned = dayjs(day).isBetween(startDate, endDate, "day", "[]");
}

apiRef.current.updateRows([{ id, _error: error, isPlanned }]);
return !error;
},
[apiRef, day, isHoliday, milestonesByProject],
);

const handleCancel = useCallback(
(id: GridRowId) => () => {
setRowModesModel((model) => ({
...model,
[id]: { mode: GridRowModes.View, ignoreModifications: true },
}));
const editedRow = entries.find((entry) => entry.id === id);
if (editedRow?._isNew) {
setEntries((es) => es.filter((e) => e.id !== id));
}
},
[entries],
);

const handleDelete = useCallback(
(id: GridRowId) => () => {
setEntries((es) => es.filter((e) => e.id !== id));
},
[],
);

const handleSave = useCallback(
(id: GridRowId) => () => {
if (validateRow(id)) {
setRowModesModel((model) => ({
...model,
[id]: { mode: GridRowModes.View },
}));
}
},
[validateRow],
);

const handleEditStop = useCallback<GridEventListener<"rowEditStop">>(
(params, event) => {
if (!validateRow(params.id)) {
event.defaultMuiPrevented = true;
}
},
[validateRow],
);

const processRowUpdate = useCallback((newRow: GridRowModel) => {
const updatedRow = { ...newRow, _isNew: false };
setEntries((es) => es.map((e) => (e.id === newRow.id ? updatedRow : e)));
return updatedRow;
}, []);

const columns = useMemo<GridColDef[]>(
() => [
{
type: "actions",
field: "actions",
headerName: t("Actions"),
getActions: ({ id }) => {
if (rowModesModel[id]?.mode === GridRowModes.Edit) {
return [
<GridActionsCellItem
key="accpet-action"
icon={<Check />}
label={t("Save")}
onClick={handleSave(id)}
/>,
<GridActionsCellItem
key="cancel-action"
icon={<Close />}
label={t("Cancel")}
onClick={handleCancel(id)}
/>,
];
}

return [
<GridActionsCellItem
key="delete-action"
icon={<Delete />}
label={t("Remove")}
onClick={handleDelete(id)}
/>,
];
},
},
{
field: "projectId",
headerName: t("Project Code and Name"),
width: 300,
editable: true,
valueFormatter(params) {
const project = allProjects.find((p) => p.id === params.value);
return project ? `${project.code} - ${project.name}` : t("None");
},
renderEditCell(params: GridRenderEditCellParams<TimeEntryRow, number>) {
return (
<ProjectSelect
multiple={false}
allProjects={allProjects}
assignedProjects={assignedProjects}
value={params.value}
onProjectSelect={(projectId) => {
params.api.setEditCellValue({
id: params.id,
field: params.field,
value: projectId,
});
params.api.setCellFocus(params.id, "taskGroupId");
}}
/>
);
},
},
{
field: "taskGroupId",
headerName: t("Stage"),
width: 200,
editable: true,
renderEditCell(params: GridRenderEditCellParams<TimeEntryRow, number>) {
return (
<TaskGroupSelect
projectId={params.row.projectId}
value={params.value}
taskGroupsByProject={taskGroupsByProject}
onTaskGroupSelect={(taskGroupId) => {
params.api.setEditCellValue({
id: params.id,
field: params.field,
value: taskGroupId,
});
params.api.setCellFocus(params.id, "taskId");
}}
/>
);
},
valueFormatter(params) {
const taskGroups = params.id
? taskGroupsByProject[params.api.getRow(params.id).projectId] || []
: [];
const taskGroup = taskGroups.find((tg) => tg.value === params.value);
return taskGroup ? taskGroup.label : t("None");
},
},
{
field: "taskId",
headerName: t("Task"),
width: 200,
editable: true,
renderEditCell(params: GridRenderEditCellParams<TimeEntryRow, number>) {
return (
<TaskSelect
value={params.value}
projectId={params.row.projectId}
taskGroupId={params.row.taskGroupId}
allProjects={allProjects}
onTaskSelect={(taskId) => {
params.api.setEditCellValue({
id: params.id,
field: params.field,
value: taskId,
});
params.api.setCellFocus(params.id, "inputHours");
}}
/>
);
},
valueFormatter(params) {
const projectId = params.id
? params.api.getRow(params.id).projectId
: undefined;

const task = projectId
? allProjects
.find((p) => p.id === projectId)
?.tasks.find((t) => t.id === params.value)
: undefined;

return task ? task.name : t("None");
},
},
{
field: "inputHours",
headerName: t("Hours"),
width: 100,
editable: true,
type: "number",
renderEditCell(params: GridRenderEditCellParams<TimeEntryRow>) {
const errorMessage =
params.row._error?.[params.field as keyof TimeEntry];
const content = <GridEditInputCell {...params} />;
return errorMessage ? (
<Tooltip title={t(errorMessage, { DAILY_NORMAL_MAX_HOURS })}>
<Box width="100%">{content}</Box>
</Tooltip>
) : (
content
);
},
valueParser(value) {
return value ? roundToNearestQuarter(value) : value;
},
valueFormatter(params) {
return manhourFormatter.format(params.value || 0);
},
},
{
field: "otHours",
headerName: t("Other Hours"),
width: 150,
editable: true,
type: "number",
renderEditCell(params: GridRenderEditCellParams<TimeEntryRow>) {
const errorMessage =
params.row._error?.[params.field as keyof TimeEntry];
const content = <GridEditInputCell {...params} />;
return errorMessage ? (
<Tooltip title={t(errorMessage)}>
<Box width="100%">{content}</Box>
</Tooltip>
) : (
content
);
},
valueParser(value) {
return value ? roundToNearestQuarter(value) : value;
},
valueFormatter(params) {
return manhourFormatter.format(params.value || 0);
},
},
{
field: "remark",
headerName: t("Remark"),
sortable: false,
flex: 1,
editable: true,
renderEditCell(params: GridRenderEditCellParams<TimeEntryRow>) {
const errorMessage =
params.row._error?.[params.field as keyof TimeEntry];
const content = <GridEditInputCell {...params} />;
return errorMessage ? (
<Tooltip title={t(errorMessage)}>
<Box width="100%">{content}</Box>
</Tooltip>
) : (
content
);
},
},
],
[
t,
rowModesModel,
handleDelete,
handleSave,
handleCancel,
assignedProjects,
allProjects,
taskGroupsByProject,
],
);

useEffect(() => {
setValue(day, [
...entries
.filter((e) => !e._isNew && !e._error && e.id)
.map(({ isPlanned, _error, _isNew, ...entry }) => ({
id: entry.id!,
...entry,
})),
]);
clearErrors(day);
}, [getValues, entries, setValue, day, clearErrors]);

const hasOutOfPlannedStages = entries.some(
(entry) => entry.isPlanned !== undefined && !entry.isPlanned,
);

// Fast entry modal
const [fastEntryModalOpen, setFastEntryModalOpen] = useState(false);
const closeFastEntryModal = useCallback(() => {
setFastEntryModalOpen(false);
}, []);
const openFastEntryModal = useCallback(() => {
setFastEntryModalOpen(true);
}, []);
const onSaveFastEntry = useCallback(async (entries: TimeEntry[]) => {
setEntries((e) => [...e, ...entries]);
setFastEntryModalOpen(false);
}, []);

const footer = (
<Box display="flex" gap={2} alignItems="center">
<Button
disableRipple
variant="outlined"
startIcon={<Add />}
onClick={addRow}
size="small"
>
{t("Record time")}
</Button>
{fastEntryEnabled && <Button
disableRipple
variant="outlined"
startIcon={<Add />}
onClick={openFastEntryModal}
size="small"
>
{t("Fast time entry")}
</Button>}
{hasOutOfPlannedStages && (
<Typography color="warning.main" variant="body2">
{t("There are entries for stages out of planned dates!")}
</Typography>
)}
</Box>
);

return (
<>
<StyledDataGrid
apiRef={apiRef}
autoHeight
sx={{
"--DataGrid-overlayHeight": "100px",
".MuiDataGrid-row .MuiDataGrid-cell.hasError": {
border: "1px solid",
borderColor: "error.main",
},
".MuiDataGrid-row .MuiDataGrid-cell.hasWarning": {
border: "1px solid",
borderColor: "warning.main",
},
}}
disableColumnMenu
editMode="row"
rows={entries}
rowModesModel={rowModesModel}
onRowModesModelChange={setRowModesModel}
onRowEditStop={handleEditStop}
processRowUpdate={processRowUpdate}
columns={columns}
getCellClassName={(params: GridCellParams<TimeEntryRow>) => {
let classname = "";
if (params.row._error?.[params.field as keyof TimeEntry]) {
classname = "hasError";
} else if (
params.field === "taskGroupId" &&
params.row.isPlanned !== undefined &&
!params.row.isPlanned
) {
classname = "hasWarning";
}
return classname;
}}
slots={{
footer: FooterToolbar,
noRowsOverlay: NoRowsOverlay,
}}
slotProps={{
footer: { child: footer },
}}
/>
{fastEntryEnabled && (
<FastTimeEntryModal
allProjects={allProjects}
assignedProjects={assignedProjects}
open={fastEntryModalOpen}
isHoliday={Boolean(isHoliday)}
onClose={closeFastEntryModal}
onSave={onSaveFastEntry}
/>
)}
</>
);
};

const NoRowsOverlay: React.FC = () => {
const { t } = useTranslation("home");
return (
<Box
display="flex"
justifyContent="center"
alignItems="center"
height="100%"
>
<Typography variant="caption">{t("Add some time entries!")}</Typography>
</Box>
);
};

const FooterToolbar: React.FC<FooterPropsOverrides> = ({ child }) => {
return <GridToolbarContainer sx={{ p: 2 }}>{child}</GridToolbarContainer>;
};

export default EntryInputTable;

+ 0
- 200
src/components/TimesheetTable/MobileTimesheetEntry.tsx Прегледај датотеку

@@ -1,200 +0,0 @@
import { TimeEntry, RecordTimesheetInput } from "@/app/api/timesheets/actions";
import { shortDateFormatter } from "@/app/utils/formatUtil";
import { Add } from "@mui/icons-material";
import { Box, Button, Stack, 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 { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import TimesheetEditModal, {
Props as TimesheetEditModalProps,
} from "./TimesheetEditModal";
import TimeEntryCard from "./TimeEntryCard";
import { HolidaysResult } from "@/app/api/holidays";
import { getHolidayForDate } from "@/app/utils/holidayUtils";
import FastTimeEntryModal from "./FastTimeEntryModal";

interface Props {
date: string;
allProjects: ProjectWithTasks[];
assignedProjects: AssignedProject[];
companyHolidays: HolidaysResult[];
fastEntryEnabled?: boolean;
}

const MobileTimesheetEntry: React.FC<Props> = ({
date,
allProjects,
assignedProjects,
companyHolidays,
fastEntryEnabled,
}) => {
const {
t,
i18n: { language },
} = useTranslation("home");

const projectMap = useMemo(() => {
return allProjects.reduce<{
[id: ProjectWithTasks["id"]]: ProjectWithTasks;
}>((acc, project) => {
return { ...acc, [project.id]: project };
}, {});
}, [allProjects]);

const dayJsObj = dayjs(date);
const holiday = getHolidayForDate(date, companyHolidays);
const isHoliday = holiday || dayJsObj.day() === 0 || dayJsObj.day() === 6;

const { watch, setValue, clearErrors } =
useFormContext<RecordTimesheetInput>();
const currentEntries = watch(date);

// Edit modal
const [editModalProps, setEditModalProps] = useState<
Partial<TimesheetEditModalProps>
>({});
const [editModalOpen, setEditModalOpen] = useState(false);

const openEditModal = useCallback(
(defaultValues?: TimeEntry) => () => {
setEditModalProps({
defaultValues: defaultValues ? { ...defaultValues } : undefined,
onDelete: defaultValues
? async () => {
setValue(
date,
currentEntries.filter((entry) => entry.id !== defaultValues.id),
);
clearErrors(date);
setEditModalOpen(false);
}
: undefined,
});
setEditModalOpen(true);
},
[clearErrors, currentEntries, date, setValue],
);

const closeEditModal = useCallback(() => {
setEditModalOpen(false);
}, []);

const onSaveEntry = useCallback(
async (entry: TimeEntry) => {
const existingEntry = currentEntries.find((e) => e.id === entry.id);
if (existingEntry) {
setValue(
date,
currentEntries.map((e) => ({
...(e.id === existingEntry.id ? entry : e),
})),
);
clearErrors(date);
} else {
setValue(date, [...currentEntries, entry]);
}
setEditModalOpen(false);
},
[clearErrors, currentEntries, date, setValue],
);

// Fast entry modal
const [fastEntryModalOpen, setFastEntryModalOpen] = useState(false);
const closeFastEntryModal = useCallback(() => {
setFastEntryModalOpen(false);
}, []);
const openFastEntryModal = useCallback(() => {
setFastEntryModalOpen(true);
}, []);
const onSaveFastEntry = useCallback(
async (entries: TimeEntry[]) => {
setValue(date, [...currentEntries, ...entries]);
setFastEntryModalOpen(false);
},
[currentEntries, date, setValue],
);

return (
<>
<Typography
paddingInline={2}
variant="overline"
color={isHoliday ? "error.main" : undefined}
>
{shortDateFormatter(language).format(dayJsObj.toDate())}
{holiday && (
<Typography
marginInlineStart={1}
variant="caption"
>{`(${holiday.title})`}</Typography>
)}
</Typography>
<Box
paddingInline={2}
flex={1}
display="flex"
flexDirection="column"
gap={2}
overflow="scroll"
>
{currentEntries.length ? (
currentEntries.map((entry, index) => {
const project = entry.projectId
? projectMap[entry.projectId]
: undefined;

const task = project?.tasks.find((t) => t.id === entry.taskId);

return (
<TimeEntryCard
key={`${entry.id}-${index}`}
project={project}
task={task}
entry={entry}
onEdit={openEditModal(entry)}
/>
);
})
) : (
<Typography variant="body2" display="block">
{t("Add some time entries!")}
</Typography>
)}
<Stack alignItems={"flex-start"} spacing={1}>
<Button startIcon={<Add />} onClick={openEditModal()}>
{t("Record time")}
</Button>
{fastEntryEnabled && (
<Button startIcon={<Add />} onClick={openFastEntryModal}>
{t("Fast time entry")}
</Button>
)}
</Stack>
<TimesheetEditModal
allProjects={allProjects}
assignedProjects={assignedProjects}
open={editModalOpen}
onClose={closeEditModal}
onSave={onSaveEntry}
isHoliday={Boolean(isHoliday)}
fastEntryEnabled={fastEntryEnabled}
{...editModalProps}
/>
{fastEntryEnabled && (
<FastTimeEntryModal
allProjects={allProjects}
assignedProjects={assignedProjects}
open={fastEntryModalOpen}
isHoliday={Boolean(isHoliday)}
onClose={closeFastEntryModal}
onSave={onSaveFastEntry}
/>
)}
</Box>
</>
);
};

export default MobileTimesheetEntry;

+ 0
- 51
src/components/TimesheetTable/MobileTimesheetTable.tsx Прегледај датотеку

@@ -1,51 +0,0 @@
import {
RecordLeaveInput,
RecordTimesheetInput,
} from "@/app/api/timesheets/actions";
import React from "react";
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[];
errorComponent?: React.ReactNode;
fastEntryEnabled?: boolean;
}

const MobileTimesheetTable: React.FC<Props> = ({
allProjects,
assignedProjects,
leaveRecords,
companyHolidays,
errorComponent,
fastEntryEnabled,
}) => {
const { watch } = useFormContext<RecordTimesheetInput>();
const currentInput = watch();
const days = Object.keys(currentInput);

return (
<DateHoursList
days={days}
companyHolidays={companyHolidays}
leaveEntries={leaveRecords}
timesheetEntries={currentInput}
EntryComponent={MobileTimesheetEntry}
entryComponentProps={{
allProjects,
assignedProjects,
companyHolidays,
fastEntryEnabled,
}}
errorComponent={errorComponent}
/>
);
};

export default MobileTimesheetTable;

+ 0
- 43
src/components/TimesheetTable/TimesheetTable.tsx Прегледај датотеку

@@ -1,43 +0,0 @@
import {
RecordLeaveInput,
RecordTimesheetInput,
} from "@/app/api/timesheets/actions";
import React from "react";
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[];
fastEntryEnabled?: boolean;
}

const TimesheetTable: React.FC<Props> = ({
allProjects,
assignedProjects,
leaveRecords,
companyHolidays,
fastEntryEnabled,
}) => {
const { watch } = useFormContext<RecordTimesheetInput>();
const currentInput = watch();
const days = Object.keys(currentInput);

return (
<DateHoursTable
companyHolidays={companyHolidays}
days={days}
leaveEntries={leaveRecords}
timesheetEntries={currentInput}
EntryTableComponent={EntryInputTable}
entryTableProps={{ assignedProjects, allProjects, fastEntryEnabled }}
/>
);
};

export default TimesheetTable;

+ 0
- 1
src/components/TimesheetTable/index.ts Прегледај датотеку

@@ -1 +0,0 @@
export { default } from "./TimesheetTable";

+ 1
- 0
src/components/UserWorkspacePage/UserWorkspacePage.tsx Прегледај датотеку

@@ -228,6 +228,7 @@ const UserWorkspacePage: React.FC<Props> = ({
teamTimesheets={teamTimesheets} teamTimesheets={teamTimesheets}
open={isTimesheetAmendmentVisible} open={isTimesheetAmendmentVisible}
onClose={handleAmendmentClose} onClose={handleAmendmentClose}
miscTasks={miscTasks}
/> />
)} )}
</> </>


Loading…
Откажи
Сачувај