| @@ -8,8 +8,6 @@ import { | |||||
| fetchTeamMemberTimesheets, | fetchTeamMemberTimesheets, | ||||
| fetchTimesheets, | fetchTimesheets, | ||||
| } from "@/app/api/timesheets"; | } from "@/app/api/timesheets"; | ||||
| import { authOptions } from "@/config/authConfig"; | |||||
| import { getServerSession } from "next-auth"; | |||||
| import { | import { | ||||
| fetchAssignedProjects, | fetchAssignedProjects, | ||||
| fetchProjectWithTasks, | fetchProjectWithTasks, | ||||
| @@ -21,22 +19,18 @@ export const metadata: Metadata = { | |||||
| }; | }; | ||||
| const Home: React.FC = async () => { | const Home: React.FC = async () => { | ||||
| const session = await getServerSession(authOptions); | |||||
| // Get name for caching | |||||
| const username = session!.user!.name!; | |||||
| fetchTimesheets(username); | |||||
| fetchAssignedProjects(username); | |||||
| fetchLeaves(username); | |||||
| fetchTimesheets(); | |||||
| fetchAssignedProjects(); | |||||
| fetchLeaves(); | |||||
| fetchLeaveTypes(); | fetchLeaveTypes(); | ||||
| fetchProjectWithTasks(); | fetchProjectWithTasks(); | ||||
| fetchHolidays(); | fetchHolidays(); | ||||
| fetchTeamMemberTimesheets(username); | |||||
| fetchTeamMemberLeaves(username); | |||||
| fetchTeamMemberTimesheets(); | |||||
| fetchTeamMemberLeaves(); | |||||
| return ( | return ( | ||||
| <I18nProvider namespaces={["home", "common"]}> | <I18nProvider namespaces={["home", "common"]}> | ||||
| <UserWorkspacePage username={username} /> | |||||
| <UserWorkspacePage /> | |||||
| </I18nProvider> | </I18nProvider> | ||||
| ); | ); | ||||
| }; | }; | ||||
| @@ -170,11 +170,11 @@ export const fetchProjectWorkNatures = cache(async () => { | |||||
| }); | }); | ||||
| }); | }); | ||||
| export const fetchAssignedProjects = cache(async (username: string) => { | |||||
| export const fetchAssignedProjects = cache(async () => { | |||||
| return serverFetchJson<AssignedProject[]>( | return serverFetchJson<AssignedProject[]>( | ||||
| `${BASE_API_URL}/projects/assignedProjects`, | `${BASE_API_URL}/projects/assignedProjects`, | ||||
| { | { | ||||
| next: { tags: [`assignedProjects__${username}`] }, | |||||
| next: { tags: [`assignedProjects`] }, | |||||
| }, | }, | ||||
| ); | ); | ||||
| }); | }); | ||||
| @@ -31,10 +31,7 @@ export interface RecordLeaveInput { | |||||
| [date: string]: LeaveEntry[]; | [date: string]: LeaveEntry[]; | ||||
| } | } | ||||
| export const saveTimesheet = async ( | |||||
| data: RecordTimesheetInput, | |||||
| username: string, | |||||
| ) => { | |||||
| export const saveTimesheet = async (data: RecordTimesheetInput) => { | |||||
| const savedRecords = await serverFetchJson<RecordTimesheetInput>( | const savedRecords = await serverFetchJson<RecordTimesheetInput>( | ||||
| `${BASE_API_URL}/timesheets/save`, | `${BASE_API_URL}/timesheets/save`, | ||||
| { | { | ||||
| @@ -44,12 +41,12 @@ export const saveTimesheet = async ( | |||||
| }, | }, | ||||
| ); | ); | ||||
| revalidateTag(`timesheets_${username}`); | |||||
| revalidateTag(`timesheets`); | |||||
| return savedRecords; | return savedRecords; | ||||
| }; | }; | ||||
| export const saveLeave = async (data: RecordLeaveInput, username: string) => { | |||||
| export const saveLeave = async (data: RecordLeaveInput) => { | |||||
| const savedRecords = await serverFetchJson<RecordLeaveInput>( | const savedRecords = await serverFetchJson<RecordLeaveInput>( | ||||
| `${BASE_API_URL}/timesheets/saveLeave`, | `${BASE_API_URL}/timesheets/saveLeave`, | ||||
| { | { | ||||
| @@ -59,7 +56,7 @@ export const saveLeave = async (data: RecordLeaveInput, username: string) => { | |||||
| }, | }, | ||||
| ); | ); | ||||
| revalidateTag(`leaves_${username}`); | |||||
| revalidateTag(`leaves`); | |||||
| return savedRecords; | return savedRecords; | ||||
| }; | }; | ||||
| @@ -24,17 +24,17 @@ export type TeamLeaves = { | |||||
| }; | }; | ||||
| }; | }; | ||||
| export const fetchTimesheets = cache(async (username: string) => { | |||||
| export const fetchTimesheets = cache(async () => { | |||||
| return serverFetchJson<RecordTimesheetInput>(`${BASE_API_URL}/timesheets`, { | return serverFetchJson<RecordTimesheetInput>(`${BASE_API_URL}/timesheets`, { | ||||
| next: { tags: [`timesheets_${username}`] }, | |||||
| next: { tags: [`timesheets`] }, | |||||
| }); | }); | ||||
| }); | }); | ||||
| export const fetchLeaves = cache(async (username: string) => { | |||||
| export const fetchLeaves = cache(async () => { | |||||
| return serverFetchJson<RecordLeaveInput>( | return serverFetchJson<RecordLeaveInput>( | ||||
| `${BASE_API_URL}/timesheets/leaves`, | `${BASE_API_URL}/timesheets/leaves`, | ||||
| { | { | ||||
| next: { tags: [`leaves_${username}`] }, | |||||
| next: { tags: [`leaves`] }, | |||||
| }, | }, | ||||
| ); | ); | ||||
| }); | }); | ||||
| @@ -45,17 +45,17 @@ export const fetchLeaveTypes = cache(async () => { | |||||
| }); | }); | ||||
| }); | }); | ||||
| export const fetchTeamMemberTimesheets = cache(async (username: string) => { | |||||
| export const fetchTeamMemberTimesheets = cache(async () => { | |||||
| return serverFetchJson<TeamTimeSheets>( | return serverFetchJson<TeamTimeSheets>( | ||||
| `${BASE_API_URL}/timesheets/teamTimesheets`, | `${BASE_API_URL}/timesheets/teamTimesheets`, | ||||
| { | { | ||||
| next: { tags: [`team_timesheets_${username}`] }, | |||||
| next: { tags: [`team_timesheets`] }, | |||||
| }, | }, | ||||
| ); | ); | ||||
| }); | }); | ||||
| export const fetchTeamMemberLeaves = cache(async (username: string) => { | |||||
| export const fetchTeamMemberLeaves = cache(async () => { | |||||
| return serverFetchJson<TeamLeaves>(`${BASE_API_URL}/timesheets/teamLeaves`, { | return serverFetchJson<TeamLeaves>(`${BASE_API_URL}/timesheets/teamLeaves`, { | ||||
| next: { tags: [`team_leaves_${username}`] }, | |||||
| next: { tags: [`team_leaves`] }, | |||||
| }); | }); | ||||
| }); | }); | ||||
| @@ -36,7 +36,6 @@ import ErrorAlert from "../ErrorAlert"; | |||||
| interface Props { | interface Props { | ||||
| isOpen: boolean; | isOpen: boolean; | ||||
| onClose: () => void; | onClose: () => void; | ||||
| username: string; | |||||
| defaultLeaveRecords?: RecordLeaveInput; | defaultLeaveRecords?: RecordLeaveInput; | ||||
| leaveTypes: LeaveType[]; | leaveTypes: LeaveType[]; | ||||
| timesheetRecords: RecordTimesheetInput; | timesheetRecords: RecordTimesheetInput; | ||||
| @@ -56,7 +55,6 @@ const modalSx: SxProps = { | |||||
| const LeaveModal: React.FC<Props> = ({ | const LeaveModal: React.FC<Props> = ({ | ||||
| isOpen, | isOpen, | ||||
| onClose, | onClose, | ||||
| username, | |||||
| defaultLeaveRecords, | defaultLeaveRecords, | ||||
| timesheetRecords, | timesheetRecords, | ||||
| leaveTypes, | leaveTypes, | ||||
| @@ -97,7 +95,7 @@ const LeaveModal: React.FC<Props> = ({ | |||||
| ); | ); | ||||
| return; | return; | ||||
| } | } | ||||
| const savedRecords = await saveLeave(data, username); | |||||
| const savedRecords = await saveLeave(data); | |||||
| const today = dayjs(); | const today = dayjs(); | ||||
| const newFormValues = Array(7) | const newFormValues = Array(7) | ||||
| @@ -113,7 +111,7 @@ const LeaveModal: React.FC<Props> = ({ | |||||
| formProps.reset(newFormValues); | formProps.reset(newFormValues); | ||||
| onClose(); | onClose(); | ||||
| }, | }, | ||||
| [companyHolidays, formProps, onClose, timesheetRecords, username], | |||||
| [companyHolidays, formProps, onClose, timesheetRecords], | |||||
| ); | ); | ||||
| const onCancel = useCallback(() => { | const onCancel = useCallback(() => { | ||||
| @@ -1,6 +1,9 @@ | |||||
| import { LeaveType } from "@/app/api/timesheets"; | import { LeaveType } from "@/app/api/timesheets"; | ||||
| import { LeaveEntry } from "@/app/api/timesheets/actions"; | import { LeaveEntry } from "@/app/api/timesheets/actions"; | ||||
| import { DAILY_NORMAL_MAX_HOURS } from "@/app/api/timesheets/utils"; | |||||
| import { | |||||
| DAILY_NORMAL_MAX_HOURS, | |||||
| TIMESHEET_DAILY_MAX_HOURS, | |||||
| } from "@/app/api/timesheets/utils"; | |||||
| import { shortDateFormatter } from "@/app/utils/formatUtil"; | import { shortDateFormatter } from "@/app/utils/formatUtil"; | ||||
| import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | ||||
| import { Check, Delete } from "@mui/icons-material"; | import { Check, Delete } from "@mui/icons-material"; | ||||
| @@ -153,7 +156,10 @@ const LeaveEditModal: React.FC<Props> = ({ | |||||
| /> | /> | ||||
| {formState.errors.root?.message && ( | {formState.errors.root?.message && ( | ||||
| <Typography variant="caption" color="error"> | <Typography variant="caption" color="error"> | ||||
| {t(formState.errors.root.message, { DAILY_NORMAL_MAX_HOURS })} | |||||
| {t(formState.errors.root.message, { | |||||
| DAILY_NORMAL_MAX_HOURS, | |||||
| TIMESHEET_DAILY_MAX_HOURS, | |||||
| })} | |||||
| </Typography> | </Typography> | ||||
| )} | )} | ||||
| <Box display="flex" justifyContent="flex-end" gap={1}> | <Box display="flex" justifyContent="flex-end" gap={1}> | ||||
| @@ -38,7 +38,6 @@ interface Props { | |||||
| onClose: () => void; | onClose: () => void; | ||||
| allProjects: ProjectWithTasks[]; | allProjects: ProjectWithTasks[]; | ||||
| assignedProjects: AssignedProject[]; | assignedProjects: AssignedProject[]; | ||||
| username: string; | |||||
| defaultTimesheets?: RecordTimesheetInput; | defaultTimesheets?: RecordTimesheetInput; | ||||
| leaveRecords: RecordLeaveInput; | leaveRecords: RecordLeaveInput; | ||||
| companyHolidays: HolidaysResult[]; | companyHolidays: HolidaysResult[]; | ||||
| @@ -60,7 +59,6 @@ const TimesheetModal: React.FC<Props> = ({ | |||||
| onClose, | onClose, | ||||
| allProjects, | allProjects, | ||||
| assignedProjects, | assignedProjects, | ||||
| username, | |||||
| defaultTimesheets, | defaultTimesheets, | ||||
| leaveRecords, | leaveRecords, | ||||
| companyHolidays, | companyHolidays, | ||||
| @@ -97,7 +95,7 @@ const TimesheetModal: React.FC<Props> = ({ | |||||
| ); | ); | ||||
| return; | return; | ||||
| } | } | ||||
| const savedRecords = await saveTimesheet(data, username); | |||||
| const savedRecords = await saveTimesheet(data); | |||||
| const today = dayjs(); | const today = dayjs(); | ||||
| const newFormValues = Array(7) | const newFormValues = Array(7) | ||||
| @@ -113,7 +111,7 @@ const TimesheetModal: React.FC<Props> = ({ | |||||
| formProps.reset(newFormValues); | formProps.reset(newFormValues); | ||||
| onClose(); | onClose(); | ||||
| }, | }, | ||||
| [companyHolidays, formProps, leaveRecords, onClose, username], | |||||
| [companyHolidays, formProps, leaveRecords, onClose], | |||||
| ); | ); | ||||
| const onCancel = useCallback(() => { | const onCancel = useCallback(() => { | ||||
| @@ -23,7 +23,10 @@ import { TaskGroup } from "@/app/api/tasks"; | |||||
| import uniqBy from "lodash/uniqBy"; | import uniqBy from "lodash/uniqBy"; | ||||
| import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | import { roundToNearestQuarter } from "@/app/utils/manhourUtils"; | ||||
| import { shortDateFormatter } from "@/app/utils/formatUtil"; | import { shortDateFormatter } from "@/app/utils/formatUtil"; | ||||
| import { DAILY_NORMAL_MAX_HOURS } from "@/app/api/timesheets/utils"; | |||||
| import { | |||||
| DAILY_NORMAL_MAX_HOURS, | |||||
| TIMESHEET_DAILY_MAX_HOURS, | |||||
| } from "@/app/api/timesheets/utils"; | |||||
| export interface Props extends Omit<ModalProps, "children"> { | export interface Props extends Omit<ModalProps, "children"> { | ||||
| onSave: (timeEntry: TimeEntry, recordDate?: string) => Promise<void>; | onSave: (timeEntry: TimeEntry, recordDate?: string) => Promise<void>; | ||||
| @@ -277,7 +280,10 @@ const TimesheetEditModal: React.FC<Props> = ({ | |||||
| /> | /> | ||||
| {formState.errors.root?.message && ( | {formState.errors.root?.message && ( | ||||
| <Typography variant="caption" color="error"> | <Typography variant="caption" color="error"> | ||||
| {t(formState.errors.root.message, { DAILY_NORMAL_MAX_HOURS })} | |||||
| {t(formState.errors.root.message, { | |||||
| DAILY_NORMAL_MAX_HOURS, | |||||
| TIMESHEET_DAILY_MAX_HOURS, | |||||
| })} | |||||
| </Typography> | </Typography> | ||||
| )} | )} | ||||
| <Box display="flex" justifyContent="flex-end" gap={1}> | <Box display="flex" justifyContent="flex-end" gap={1}> | ||||
| @@ -30,7 +30,6 @@ export interface Props { | |||||
| leaveTypes: LeaveType[]; | leaveTypes: LeaveType[]; | ||||
| allProjects: ProjectWithTasks[]; | allProjects: ProjectWithTasks[]; | ||||
| assignedProjects: AssignedProject[]; | assignedProjects: AssignedProject[]; | ||||
| username: string; | |||||
| defaultLeaveRecords: RecordLeaveInput; | defaultLeaveRecords: RecordLeaveInput; | ||||
| defaultTimesheets: RecordTimesheetInput; | defaultTimesheets: RecordTimesheetInput; | ||||
| holidays: HolidaysResult[]; | holidays: HolidaysResult[]; | ||||
| @@ -48,7 +47,6 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||||
| leaveTypes, | leaveTypes, | ||||
| allProjects, | allProjects, | ||||
| assignedProjects, | assignedProjects, | ||||
| username, | |||||
| defaultLeaveRecords, | defaultLeaveRecords, | ||||
| defaultTimesheets, | defaultTimesheets, | ||||
| holidays, | holidays, | ||||
| @@ -180,7 +178,6 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||||
| onClose={handleCloseTimesheetModal} | onClose={handleCloseTimesheetModal} | ||||
| allProjects={allProjects} | allProjects={allProjects} | ||||
| assignedProjects={assignedProjects} | assignedProjects={assignedProjects} | ||||
| username={username} | |||||
| defaultTimesheets={defaultTimesheets} | defaultTimesheets={defaultTimesheets} | ||||
| leaveRecords={defaultLeaveRecords} | leaveRecords={defaultLeaveRecords} | ||||
| /> | /> | ||||
| @@ -191,7 +188,6 @@ const UserWorkspacePage: React.FC<Props> = ({ | |||||
| onClose={handleCloseLeaveModal} | onClose={handleCloseLeaveModal} | ||||
| defaultLeaveRecords={defaultLeaveRecords} | defaultLeaveRecords={defaultLeaveRecords} | ||||
| timesheetRecords={defaultTimesheets} | timesheetRecords={defaultTimesheets} | ||||
| username={username} | |||||
| /> | /> | ||||
| {assignedProjects.length > 0 ? ( | {assignedProjects.length > 0 ? ( | ||||
| <AssignedProjects assignedProjects={assignedProjects} /> | <AssignedProjects assignedProjects={assignedProjects} /> | ||||
| @@ -12,11 +12,7 @@ import { | |||||
| } from "@/app/api/timesheets"; | } from "@/app/api/timesheets"; | ||||
| import { fetchHolidays } from "@/app/api/holidays"; | import { fetchHolidays } from "@/app/api/holidays"; | ||||
| interface Props { | |||||
| username: string; | |||||
| } | |||||
| const UserWorkspaceWrapper: React.FC<Props> = async ({ username }) => { | |||||
| const UserWorkspaceWrapper: React.FC = async () => { | |||||
| const [ | const [ | ||||
| teamLeaves, | teamLeaves, | ||||
| teamTimesheets, | teamTimesheets, | ||||
| @@ -27,12 +23,12 @@ const UserWorkspaceWrapper: React.FC<Props> = async ({ username }) => { | |||||
| leaveTypes, | leaveTypes, | ||||
| holidays, | holidays, | ||||
| ] = await Promise.all([ | ] = await Promise.all([ | ||||
| fetchTeamMemberLeaves(username), | |||||
| fetchTeamMemberTimesheets(username), | |||||
| fetchAssignedProjects(username), | |||||
| fetchTeamMemberLeaves(), | |||||
| fetchTeamMemberTimesheets(), | |||||
| fetchAssignedProjects(), | |||||
| fetchProjectWithTasks(), | fetchProjectWithTasks(), | ||||
| fetchTimesheets(username), | |||||
| fetchLeaves(username), | |||||
| fetchTimesheets(), | |||||
| fetchLeaves(), | |||||
| fetchLeaveTypes(), | fetchLeaveTypes(), | ||||
| fetchHolidays(), | fetchHolidays(), | ||||
| ]); | ]); | ||||
| @@ -43,7 +39,6 @@ const UserWorkspaceWrapper: React.FC<Props> = async ({ username }) => { | |||||
| teamTimesheets={teamTimesheets} | teamTimesheets={teamTimesheets} | ||||
| allProjects={allProjects} | allProjects={allProjects} | ||||
| assignedProjects={assignedProjects} | assignedProjects={assignedProjects} | ||||
| username={username} | |||||
| defaultTimesheets={timesheets} | defaultTimesheets={timesheets} | ||||
| defaultLeaveRecords={leaves} | defaultLeaveRecords={leaves} | ||||
| leaveTypes={leaveTypes} | leaveTypes={leaveTypes} | ||||