Selaa lähdekoodia

Merge branch 'main' of https://git.2fi-solutions.com/wayne.lee/tsms

tags/Baseline_30082024_FRONTEND_UAT
MSI\2Fi 1 vuosi sitten
vanhempi
commit
05e9d9cc89
15 muutettua tiedostoa jossa 320 lisäystä ja 83 poistoa
  1. +2
    -0
      src/app/(main)/home/page.tsx
  2. +3
    -1
      src/app/api/tasks/index.ts
  3. +24
    -0
      src/app/api/timesheets/actions.ts
  4. +3
    -1
      src/app/api/timesheets/utils.ts
  5. +1
    -0
      src/components/CompanyHoliday/CompanyHoliday.tsx
  6. +68
    -3
      src/components/ExcelFileImport/ExcelFileImport.tsx
  7. +73
    -28
      src/components/TimeLeaveModal/TimeLeaveInputTable.tsx
  8. +7
    -2
      src/components/TimeLeaveModal/TimeLeaveMobileEntry.tsx
  9. +6
    -1
      src/components/TimeLeaveModal/TimeLeaveModal.tsx
  10. +3
    -3
      src/components/TimesheetTable/FastTimeEntryModal.tsx
  11. +60
    -16
      src/components/TimesheetTable/TaskGroupSelect.tsx
  12. +7
    -4
      src/components/TimesheetTable/TaskSelect.tsx
  13. +53
    -24
      src/components/TimesheetTable/TimesheetEditModal.tsx
  14. +4
    -0
      src/components/UserWorkspacePage/UserWorkspacePage.tsx
  15. +6
    -0
      src/components/UserWorkspacePage/UserWorkspaceWrapper.tsx

+ 2
- 0
src/app/(main)/home/page.tsx Näytä tiedosto

@@ -13,6 +13,7 @@ import {
fetchProjectWithTasks,
} from "@/app/api/projects";
import { fetchHolidays } from "@/app/api/holidays";
import { fetchAllTasks } from "@/app/api/tasks";

export const metadata: Metadata = {
title: "User Workspace",
@@ -27,6 +28,7 @@ const Home: React.FC = async () => {
fetchHolidays();
fetchTeamMemberTimesheets();
fetchTeamMemberLeaves();
fetchAllTasks();

return (
<I18nProvider namespaces={["home", "common"]}>


+ 3
- 1
src/app/api/tasks/index.ts Näytä tiedosto

@@ -51,7 +51,9 @@ export const preloadAllTasks = () => {
};

export const fetchAllTasks = cache(async () => {
return serverFetchJson<Task[]>(`${BASE_API_URL}/tasks`);
return serverFetchJson<Task[]>(`${BASE_API_URL}/tasks`, {
next: { tags: ["tasks"] },
});
});

export const fetchTaskTemplateDetail = cache(async (id: string) => {


+ 24
- 0
src/app/api/timesheets/actions.ts Näytä tiedosto

@@ -158,3 +158,27 @@ export const importTimesheets = async (data: FormData) => {

return importTimesheets;
};

export const importLeaves = async (data: FormData) => {
const importLeaves = await serverFetchString<string>(
`${BASE_API_URL}/timesheets/import-leave`,
{
method: "POST",
body: data,
},
);

return importLeaves;
};

export const rearrangeTimesheets = async () => {
const importLeaves = await serverFetchString<string>(
`${BASE_API_URL}/timesheets/rearrange`,
{
method: "POST",
// body: data,
},
);

return importLeaves;
};

+ 3
- 1
src/app/api/timesheets/utils.ts Näytä tiedosto

@@ -43,7 +43,9 @@ export const validateTimeEntry = (
error.taskId = "Required";
}
} else {
if (!entry.remark) {
if (entry.taskGroupId && !entry.taskId) {
error.taskId = "Required";
} else if (!entry.remark) {
error.remark = "Required for non-billable tasks";
}
}


+ 1
- 0
src/components/CompanyHoliday/CompanyHoliday.tsx Näytä tiedosto

@@ -133,6 +133,7 @@ const CompanyHoliday: React.FC<Props> = ({ holidays, abilities }) => {
eventClick={handleEventClick}
headerToolbar={{
start: "today prev next",
center: "title",
end: "dayGridMonth listMonth",
}}
buttonText={{


+ 68
- 3
src/components/ExcelFileImport/ExcelFileImport.tsx Näytä tiedosto

@@ -5,8 +5,8 @@ import { FileUpload } from "@mui/icons-material";
import { Button, Grid, Stack } from "@mui/material";
import React, { ChangeEvent, useCallback } from "react";
import { useTranslation } from "react-i18next";
import { errorDialogWithContent, successDialog, successDialogWithContent } from "../Swal/CustomAlerts";
import { importTimesheets } from "@/app/api/timesheets/actions";
import { errorDialogWithContent, submitDialog, successDialog, successDialogWithContent } from "../Swal/CustomAlerts";
import { importLeaves, importTimesheets, rearrangeTimesheets } from "@/app/api/timesheets/actions";

interface Props {
}
@@ -34,9 +34,12 @@ const ExcelFileImport: React.FC<Props> = async ({ }) => {
case "importTimesheet":
response = await importTimesheets(formData)
break;
case "importLeave":
response = await importLeaves(formData)
break;
}

if (response === "Import Excel success") {
if (response.includes("Import Excel success")) {
successDialogWithContent(t("Import Success"), t(`${response}`), t)
} else {
errorDialogWithContent(t("Import Fail"), t(`${response}`), t)
@@ -52,6 +55,37 @@ const ExcelFileImport: React.FC<Props> = async ({ }) => {
return
}, [])

const handleButtonClick = useCallback(async (event: React.MouseEvent<HTMLElement>) => {
try {

const targetId = event.currentTarget.id
submitDialog(async () => {
let response: String = ""

switch (targetId) {
case "rearrangeTimesheet":
response = await rearrangeTimesheets()
break;
}
if (response.includes("Rearrange success")) {
successDialogWithContent(t("Rearrange Success"), t(`${response}`), t)
} else {
errorDialogWithContent(t("Rearrange Fail"), t(`${response}`), t)
}
}, t,
{
title: "Do you want to rearrange?",
confirmButtonText: "Rearrange"
})

} catch (err) {
console.log(err)
return false
}
}, [])

return (
<>
<Grid container rowGap={1.5}>
@@ -93,6 +127,37 @@ const ExcelFileImport: React.FC<Props> = async ({ }) => {
{t("Import Timesheet")}
</Button>
</Grid>
<Grid container>
<Button
id="rearrangeTimesheet"
variant="contained"
color="error"
startIcon={<FileUpload />}
component="label"
onClick={handleButtonClick}
>
{t("Rearrange Timesheet")}
</Button>
</Grid>
<Grid container>
<Button
variant="contained"
color="info"
startIcon={<FileUpload />}
component="label"
>
<input
id='importLeave'
type='file'
accept='.xlsx, .csv'
hidden
onChange={(event) => {
handleExcelFileImportClick(event)
}}
/>
{t("Import Leave")}
</Button>
</Grid>
</Grid>
</>
);


+ 73
- 28
src/components/TimeLeaveModal/TimeLeaveInputTable.tsx Näytä tiedosto

@@ -27,11 +27,13 @@ import {
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 { Task, TaskGroup } from "@/app/api/tasks";
import dayjs from "dayjs";
import isBetween from "dayjs/plugin/isBetween";
import ProjectSelect from "../TimesheetTable/ProjectSelect";
import TaskGroupSelect from "../TimesheetTable/TaskGroupSelect";
import TaskGroupSelect, {
TaskGroupSelectWithoutProject,
} from "../TimesheetTable/TaskGroupSelect";
import TaskSelect from "../TimesheetTable/TaskSelect";
import {
DAILY_NORMAL_MAX_HOURS,
@@ -54,6 +56,7 @@ interface Props {
assignedProjects: AssignedProject[];
fastEntryEnabled?: boolean;
leaveTypes: LeaveType[];
miscTasks: Task[];
}

export type TimeLeaveRow = Partial<
@@ -71,6 +74,7 @@ const TimeLeaveInputTable: React.FC<Props> = ({
isHoliday,
fastEntryEnabled,
leaveTypes,
miscTasks,
}) => {
const { t } = useTranslation("home");
const taskGroupsByProject = useMemo(() => {
@@ -92,6 +96,14 @@ const TimeLeaveInputTable: React.FC<Props> = ({
};
}, {});
}, [allProjects]);
const taskGroupsWithoutProject = useMemo(
() =>
uniqBy(
miscTasks.map((t) => t.taskGroup),
"id",
),
[miscTasks],
);

// To check for start / end planned dates
const milestonesByProject = useMemo(() => {
@@ -314,31 +326,62 @@ const TimeLeaveInputTable: React.FC<Props> = ({
editable: true,
renderEditCell(params: GridRenderEditCellParams<TimeLeaveRow, number>) {
if (params.row.type === "timeEntry") {
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");
}}
/>
);
if (params.row.projectId) {
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");
}}
/>
);
} else {
return (
<TaskGroupSelectWithoutProject
value={params.value}
onTaskGroupSelect={(taskGroupId) => {
params.api.setEditCellValue({
id: params.id,
field: params.field,
value: taskGroupId,
});
params.api.setCellFocus(params.id, "taskId");
}}
taskGroups={taskGroupsWithoutProject}
/>
);
}
} else {
return <DisabledEdit />;
}
},
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");
if (!params.id) {
return null;
}

const projectId = params.api.getRow(params.id).projectId;
if (projectId) {
const taskGroups =
taskGroupsByProject[params.api.getRow(params.id).projectId] || [];
const taskGroup = taskGroups.find(
(tg) => tg.value === params.value,
);
return taskGroup ? taskGroup.label : t("None");
} else {
const taskGroupId = params.value;
return (
taskGroupsWithoutProject.find((tg) => tg.id === taskGroupId)
?.name || t("None")
);
}
},
},
{
@@ -362,6 +405,7 @@ const TimeLeaveInputTable: React.FC<Props> = ({
});
params.api.setCellFocus(params.id, "inputHours");
}}
miscTasks={miscTasks}
/>
);
} else {
@@ -373,12 +417,11 @@ const TimeLeaveInputTable: React.FC<Props> = ({
? params.api.getRow(params.id).projectId
: undefined;

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

const task = (
projectId
? allProjects.find((p) => p.id === projectId)?.tasks || []
: miscTasks
).find((t) => t.id === params.value);
return task ? task.name : t("None");
},
},
@@ -475,6 +518,8 @@ const TimeLeaveInputTable: React.FC<Props> = ({
leaveTypes,
assignedProjects,
taskGroupsByProject,
taskGroupsWithoutProject,
miscTasks,
],
);



+ 7
- 2
src/components/TimeLeaveModal/TimeLeaveMobileEntry.tsx Näytä tiedosto

@@ -23,6 +23,7 @@ import { getHolidayForDate } from "@/app/utils/holidayUtils";
import FastTimeEntryModal from "../TimesheetTable/FastTimeEntryModal";
import { LeaveType } from "@/app/api/timesheets";
import LeaveEntryCard from "../LeaveTable/LeaveEntryCard";
import { Task } from "@/app/api/tasks";

interface Props {
date: string;
@@ -31,6 +32,7 @@ interface Props {
companyHolidays: HolidaysResult[];
fastEntryEnabled?: boolean;
leaveTypes: LeaveType[];
miscTasks: Task[];
}

const TimeLeaveMobileEntry: React.FC<Props> = ({
@@ -40,6 +42,7 @@ const TimeLeaveMobileEntry: React.FC<Props> = ({
companyHolidays,
fastEntryEnabled,
leaveTypes,
miscTasks,
}) => {
const {
t,
@@ -222,7 +225,9 @@ const TimeLeaveMobileEntry: React.FC<Props> = ({
? projectMap[entry.projectId]
: undefined;

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

return (
<TimeEntryCard
@@ -269,7 +274,7 @@ const TimeLeaveMobileEntry: React.FC<Props> = ({
onClose={closeEditTimeModal}
onSave={onSaveTimeEntry}
isHoliday={Boolean(isHoliday)}
fastEntryEnabled={fastEntryEnabled}
miscTasks={miscTasks}
{...editTimeModalProps}
/>
<LeaveEditModal


+ 6
- 1
src/components/TimeLeaveModal/TimeLeaveModal.tsx Näytä tiedosto

@@ -38,6 +38,7 @@ import mapValues from "lodash/mapValues";
import DateHoursList from "../DateHoursTable/DateHoursList";
import TimeLeaveInputTable from "./TimeLeaveInputTable";
import TimeLeaveMobileEntry from "./TimeLeaveMobileEntry";
import { Task } from "@/app/api/tasks";

interface Props {
isOpen: boolean;
@@ -50,6 +51,7 @@ interface Props {
fastEntryEnabled?: boolean;
leaveTypes: LeaveType[];
isFullTime: boolean;
miscTasks: Task[];
}

const modalSx: SxProps = {
@@ -72,7 +74,8 @@ const TimeLeaveModal: React.FC<Props> = ({
companyHolidays,
fastEntryEnabled,
leaveTypes,
isFullTime
isFullTime,
miscTasks,
}) => {
const { t } = useTranslation("home");

@@ -212,6 +215,7 @@ const TimeLeaveModal: React.FC<Props> = ({
allProjects,
fastEntryEnabled,
leaveTypes,
miscTasks,
}}
/>
</Box>
@@ -261,6 +265,7 @@ const TimeLeaveModal: React.FC<Props> = ({
companyHolidays,
fastEntryEnabled,
leaveTypes,
miscTasks,
}}
errorComponent={errorComponent}
/>


+ 3
- 3
src/components/TimesheetTable/FastTimeEntryModal.tsx Näytä tiedosto

@@ -68,7 +68,7 @@ const getID = () => {
};

const MISC_TASK_GROUP_ID = 5;
const FAST_ENTRY_TASK_ID = 40;
const FAST_ENTRY_TASK_ID = 43;

const FastTimeEntryModal: React.FC<Props> = ({
onSave,
@@ -140,8 +140,8 @@ const FastTimeEntryModal: React.FC<Props> = ({
projectId,
inputHours: hour,
otHours: othour,
taskGroupId: projectId ? MISC_TASK_GROUP_ID : undefined,
taskId: projectId ? FAST_ENTRY_TASK_ID : undefined,
taskGroupId: MISC_TASK_GROUP_ID,
taskId: FAST_ENTRY_TASK_ID,
remark,
};
}),


+ 60
- 16
src/components/TimesheetTable/TaskGroupSelect.tsx Näytä tiedosto

@@ -1,5 +1,5 @@
import React, { useCallback } from "react";
import { MenuItem, Select, SelectChangeEvent } from "@mui/material";
import { MenuItem, MenuProps, Select, SelectChangeEvent } from "@mui/material";
import { useTranslation } from "react-i18next";
import { TaskGroup } from "@/app/api/tasks";

@@ -16,6 +16,22 @@ interface Props {
error?: boolean;
}

const menuProps: Partial<MenuProps> = {
slotProps: {
paper: {
sx: { maxHeight: 400 },
},
},
anchorOrigin: {
vertical: "bottom",
horizontal: "left",
},
transformOrigin: {
vertical: "top",
horizontal: "left",
},
};

const TaskGroupSelect: React.FC<Props> = ({
value,
projectId,
@@ -43,21 +59,7 @@ const TaskGroupSelect: React.FC<Props> = ({
value={value || ""}
onChange={onChange}
sx={{ width: "100%" }}
MenuProps={{
slotProps: {
paper: {
sx: { maxHeight: 400 },
},
},
anchorOrigin: {
vertical: "bottom",
horizontal: "left",
},
transformOrigin: {
vertical: "top",
horizontal: "left",
},
}}
MenuProps={menuProps}
>
{taskGroups.length === 0 && <MenuItem value={""}>{t("None")}</MenuItem>}
{taskGroups.map((taskGroup) => (
@@ -73,4 +75,46 @@ const TaskGroupSelect: React.FC<Props> = ({
);
};

type TaskGroupSelectWithoutProjectProps = Pick<
Props,
"value" | "onTaskGroupSelect" | "error"
> & { taskGroups: TaskGroup[] };

export const TaskGroupSelectWithoutProject: React.FC<
TaskGroupSelectWithoutProjectProps
> = ({ value, onTaskGroupSelect, error, taskGroups }) => {
const { t } = useTranslation("home");

const onChange = useCallback(
(event: SelectChangeEvent<number>) => {
const newValue = event.target.value;
onTaskGroupSelect(newValue);
},
[onTaskGroupSelect],
);

return (
<Select
error={error}
displayEmpty
disabled={taskGroups.length === 0}
value={value || ""}
onChange={onChange}
sx={{ width: "100%" }}
MenuProps={menuProps}
>
{<MenuItem value={""}>{t("None")}</MenuItem>}
{taskGroups.map((taskGroup) => (
<MenuItem
key={taskGroup.id}
value={taskGroup.id}
sx={{ whiteSpace: "wrap" }}
>
{taskGroup.name}
</MenuItem>
))}
</Select>
);
};

export default TaskGroupSelect;

+ 7
- 4
src/components/TimesheetTable/TaskSelect.tsx Näytä tiedosto

@@ -2,6 +2,7 @@ import React, { useCallback } from "react";
import { MenuItem, Select, SelectChangeEvent } from "@mui/material";
import { useTranslation } from "react-i18next";
import { ProjectWithTasks } from "@/app/api/projects";
import { Task } from "@/app/api/tasks";

interface Props {
allProjects: ProjectWithTasks[];
@@ -10,6 +11,7 @@ interface Props {
taskGroupId: number | undefined;
onTaskSelect: (taskId: number | string) => void;
error?: boolean;
miscTasks?: Task[];
}

const TaskSelect: React.FC<Props> = ({
@@ -18,14 +20,15 @@ const TaskSelect: React.FC<Props> = ({
projectId,
taskGroupId,
onTaskSelect,
error
error,
miscTasks,
}) => {
const { t } = useTranslation("home");

const project = allProjects.find((p) => p.id === projectId);
const tasks = project
? project.tasks.filter((task) => task.taskGroup.id === taskGroupId)
: [];
const tasks = (project ? project.tasks : miscTasks || []).filter(
(task) => task.taskGroup.id === taskGroupId,
);

const onChange = useCallback(
(event: SelectChangeEvent<number>) => {


+ 53
- 24
src/components/TimesheetTable/TimesheetEditModal.tsx Näytä tiedosto

@@ -17,9 +17,11 @@ import { Controller, useForm } from "react-hook-form";
import { useTranslation } from "react-i18next";
import ProjectSelect from "./ProjectSelect";
import { AssignedProject, ProjectWithTasks } from "@/app/api/projects";
import TaskGroupSelect from "./TaskGroupSelect";
import TaskGroupSelect, {
TaskGroupSelectWithoutProject,
} from "./TaskGroupSelect";
import TaskSelect from "./TaskSelect";
import { TaskGroup } from "@/app/api/tasks";
import { Task, TaskGroup } from "@/app/api/tasks";
import uniqBy from "lodash/uniqBy";
import { roundToNearestQuarter } from "@/app/utils/manhourUtils";
import { shortDateFormatter } from "@/app/utils/formatUtil";
@@ -37,7 +39,7 @@ export interface Props extends Omit<ModalProps, "children"> {
modalSx?: SxProps;
recordDate?: string;
isHoliday?: boolean;
fastEntryEnabled?: boolean;
miscTasks: Task[];
}

const modalSx: SxProps = {
@@ -63,7 +65,7 @@ const TimesheetEditModal: React.FC<Props> = ({
modalSx: mSx,
recordDate,
isHoliday,
fastEntryEnabled,
miscTasks,
}) => {
const {
t,
@@ -90,6 +92,15 @@ const TimesheetEditModal: React.FC<Props> = ({
}, {});
}, [allProjects]);

const taskGroupsWithoutProject = useMemo(
() =>
uniqBy(
miscTasks.map((t) => t.taskGroup),
"id",
),
[miscTasks],
);

const {
register,
control,
@@ -174,23 +185,35 @@ const TimesheetEditModal: React.FC<Props> = ({
<Controller
control={control}
name="taskGroupId"
render={({ field }) => (
<TaskGroupSelect
error={Boolean(formState.errors.taskGroupId)}
projectId={projectId}
taskGroupsByProject={taskGroupsByProject}
value={field.value}
onTaskGroupSelect={(newId) => {
field.onChange(newId ?? null);
}}
/>
)}
render={({ field }) =>
projectId ? (
<TaskGroupSelect
error={Boolean(formState.errors.taskGroupId)}
projectId={projectId}
taskGroupsByProject={taskGroupsByProject}
value={field.value}
onTaskGroupSelect={(newId) => {
field.onChange(newId ?? null);
}}
/>
) : (
<TaskGroupSelectWithoutProject
value={field.value}
onTaskGroupSelect={(newId) => {
field.onChange(newId ?? null);
if (!newId) {
setValue("taskId", undefined);
}
}}
taskGroups={taskGroupsWithoutProject}
/>
)
}
rules={{
validate: (id) => {
if (!projectId) {
return !id;
return true;
}
if (fastEntryEnabled) return true;
const taskGroups = taskGroupsByProject[projectId];
return taskGroups.some((tg) => tg.value === id);
},
@@ -213,17 +236,23 @@ const TimesheetEditModal: React.FC<Props> = ({
onTaskSelect={(newId) => {
field.onChange(newId ?? null);
}}
miscTasks={miscTasks}
/>
)}
rules={{
validate: (id) => {
if (!projectId) {
return !id;
}
if (fastEntryEnabled) return true;
const projectTasks = allProjects.find((p) => p.id === projectId)
?.tasks;
return Boolean(projectTasks?.some((task) => task.id === id));
const tasks = projectId
? allProjects.find((p) => p.id === projectId)?.tasks
: miscTasks;

return taskGroupId
? Boolean(
tasks?.some(
(task) =>
task.id === id && task.taskGroup.id === taskGroupId,
),
)
: !id;
},
}}
/>


+ 4
- 0
src/components/UserWorkspacePage/UserWorkspacePage.tsx Näytä tiedosto

@@ -25,6 +25,7 @@ import { HolidaysResult } from "@/app/api/holidays";
import { TimesheetAmendmentModal } from "../TimesheetAmendment/TimesheetAmendmentModal";
import TimeLeaveModal from "../TimeLeaveModal/TimeLeaveModal";
import LeaveModal from "../LeaveModal";
import { Task } from "@/app/api/tasks";

export interface Props {
leaveTypes: LeaveType[];
@@ -39,6 +40,7 @@ export interface Props {
maintainNormalStaffWorkspaceAbility: boolean;
maintainManagementStaffWorkspaceAbility: boolean;
isFullTime: boolean;
miscTasks: Task[];
}

const menuItemSx: SxProps = {
@@ -59,6 +61,7 @@ const UserWorkspacePage: React.FC<Props> = ({
maintainNormalStaffWorkspaceAbility,
maintainManagementStaffWorkspaceAbility,
isFullTime,
miscTasks
}) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);

@@ -189,6 +192,7 @@ const UserWorkspacePage: React.FC<Props> = ({
timesheetRecords={defaultTimesheets}
leaveRecords={defaultLeaveRecords}
isFullTime={isFullTime}
miscTasks={miscTasks}
/>
<LeaveModal
open={isLeaveCalendarVisible}


+ 6
- 0
src/components/UserWorkspacePage/UserWorkspaceWrapper.tsx Näytä tiedosto

@@ -17,6 +17,7 @@ import {
MAINTAIN_NORMAL_STAFF_WORKSPACE,
MAINTAIN_MANAGEMENT_STAFF_WORKSPACE,
} from "@/middleware";
import { fetchAllTasks } from "@/app/api/tasks";

const UserWorkspaceWrapper: React.FC = async () => {
const [
@@ -30,6 +31,7 @@ const UserWorkspaceWrapper: React.FC = async () => {
holidays,
abilities,
userStaff,
allTasks,
] = await Promise.all([
fetchTeamMemberLeaves(),
fetchTeamMemberTimesheets(),
@@ -41,6 +43,7 @@ const UserWorkspaceWrapper: React.FC = async () => {
fetchHolidays(),
getUserAbilities(),
getUserStaff(),
fetchAllTasks(),
]);

const fastEntryEnabled = abilities.includes(
@@ -54,6 +57,8 @@ const UserWorkspaceWrapper: React.FC = async () => {
);
const isFullTime = userStaff?.employType === "FT";

const miscTasks = allTasks.filter((t) => t.taskGroup.id === 5);

return (
<UserWorkspacePage
isFullTime={isFullTime}
@@ -65,6 +70,7 @@ const UserWorkspaceWrapper: React.FC = async () => {
defaultLeaveRecords={leaves}
leaveTypes={leaveTypes}
holidays={holidays}
miscTasks={miscTasks}
// Change to access check
fastEntryEnabled={fastEntryEnabled}
maintainNormalStaffWorkspaceAbility={maintainNormalStaffWorkspaceAbility}


Ladataan…
Peruuta
Tallenna