-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
2813 refactor timer all start stop buttons should use the same logic (#…
…2814) * feat: encapsulate start /stop timer in a custom hook * feat: encapsulate start /stop timer logic in a custom hook
- Loading branch information
Showing
13 changed files
with
746 additions
and
578 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
149 changes: 149 additions & 0 deletions
149
apps/web/app/hooks/features/useStartStopTimerHandler.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
import { useCallback, useMemo } from 'react'; | ||
import { useModal } from '../useModal'; | ||
import { useTeamTasks } from './useTeamTasks'; | ||
import { useTimer } from './useTimer'; | ||
import { | ||
DAILY_PLAN_SUGGESTION_MODAL_DATE, | ||
TASKS_ESTIMATE_HOURS_MODAL_DATE, | ||
DAILY_PLAN_ESTIMATE_HOURS_MODAL_DATE | ||
} from '@app/constants'; | ||
|
||
export function useStartStopTimerHandler() { | ||
const { | ||
isOpen: isEnforceTaskModalOpen, | ||
closeModal: enforceTaskCloseModal, | ||
openModal: openEnforcePlannedTaskModal | ||
} = useModal(); | ||
|
||
const { | ||
isOpen: isDailyPlanWorkHoursModalOpen, | ||
closeModal: dailyPlanWorkHoursCloseModal, | ||
openModal: openAddDailyPlanWorkHoursModal | ||
} = useModal(); | ||
|
||
const { | ||
isOpen: isTasksEstimationHoursModalOpen, | ||
closeModal: tasksEstimationHoursCloseModal, | ||
openModal: openAddTasksEstimationHoursModal | ||
} = useModal(); | ||
|
||
const { | ||
isOpen: isSuggestDailyPlanModalOpen, | ||
closeModal: suggestDailyPlanCloseModal, | ||
openModal: openSuggestDailyPlanModal | ||
} = useModal(); | ||
|
||
const { timerStatus, timerStatusFetching, startTimer, stopTimer, hasPlan, canRunTimer, activeTeamTask } = | ||
useTimer(); | ||
|
||
const { activeTeam } = useTeamTasks(); | ||
|
||
const requirePlan = useMemo(() => activeTeam?.requirePlanToTrack, [activeTeam?.requirePlanToTrack]); | ||
|
||
const hasWorkedHours = useMemo( | ||
() => hasPlan?.workTimePlanned && hasPlan?.workTimePlanned > 0, | ||
[hasPlan?.workTimePlanned] | ||
); | ||
const areAllTasksEstimated = useMemo( | ||
() => hasPlan?.tasks?.every((el) => typeof el?.estimate === 'number' && el?.estimate > 0), | ||
[hasPlan?.tasks] | ||
); | ||
|
||
const isActiveTaskPlaned = useMemo( | ||
() => hasPlan?.tasks?.some((task) => task.id === activeTeamTask?.id), | ||
[activeTeamTask?.id, hasPlan?.tasks] | ||
); | ||
|
||
const startStopTimerHandler = useCallback(() => { | ||
const currentDate = new Date().toISOString().split('T')[0]; | ||
const dailyPlanSuggestionModalDate = window && window?.localStorage.getItem(DAILY_PLAN_SUGGESTION_MODAL_DATE); | ||
const tasksEstimateHoursModalDate = window && window?.localStorage.getItem(TASKS_ESTIMATE_HOURS_MODAL_DATE); | ||
const dailyPlanEstimateHoursModalDate = | ||
window && window?.localStorage.getItem(DAILY_PLAN_ESTIMATE_HOURS_MODAL_DATE); | ||
|
||
/** | ||
* Handle missing working hour for a daily plN | ||
*/ | ||
const handleMissingDailyPlanWorkHour = () => { | ||
if (!hasWorkedHours) { | ||
openAddDailyPlanWorkHoursModal(); | ||
} else { | ||
startTimer(); | ||
} | ||
}; | ||
|
||
/** | ||
* Handler function to start or stop the timer based on various conditions. | ||
* Shows appropriate modals and starts or stops the timer as needed. | ||
*/ | ||
if (timerStatusFetching || !canRunTimer) return; | ||
if (timerStatus?.running) { | ||
stopTimer(); | ||
} else if (requirePlan && !isActiveTaskPlaned) { | ||
openEnforcePlannedTaskModal(); | ||
} else { | ||
if ( | ||
dailyPlanSuggestionModalDate == currentDate && | ||
tasksEstimateHoursModalDate == currentDate && | ||
dailyPlanEstimateHoursModalDate == currentDate | ||
) { | ||
startTimer(); | ||
} else { | ||
if (dailyPlanSuggestionModalDate != currentDate) { | ||
openSuggestDailyPlanModal(); | ||
} else if (tasksEstimateHoursModalDate != currentDate) { | ||
if (areAllTasksEstimated) { | ||
if (dailyPlanEstimateHoursModalDate != currentDate) { | ||
handleMissingDailyPlanWorkHour(); | ||
} else { | ||
startTimer(); | ||
} | ||
} else { | ||
openAddTasksEstimationHoursModal(); | ||
} | ||
} else if (dailyPlanEstimateHoursModalDate != currentDate) { | ||
if (areAllTasksEstimated) { | ||
handleMissingDailyPlanWorkHour(); | ||
} else { | ||
startTimer(); | ||
} | ||
} else { | ||
// Default action to start the timer | ||
startTimer(); | ||
} | ||
} | ||
} | ||
}, [ | ||
areAllTasksEstimated, | ||
canRunTimer, | ||
hasWorkedHours, | ||
isActiveTaskPlaned, | ||
openAddDailyPlanWorkHoursModal, | ||
openAddTasksEstimationHoursModal, | ||
openEnforcePlannedTaskModal, | ||
openSuggestDailyPlanModal, | ||
requirePlan, | ||
startTimer, | ||
stopTimer, | ||
timerStatus?.running, | ||
timerStatusFetching | ||
]); | ||
|
||
return { | ||
modals: { | ||
isEnforceTaskModalOpen, | ||
enforceTaskCloseModal, | ||
openEnforcePlannedTaskModal, | ||
isDailyPlanWorkHoursModalOpen, | ||
dailyPlanWorkHoursCloseModal, | ||
openAddDailyPlanWorkHoursModal, | ||
isTasksEstimationHoursModalOpen, | ||
tasksEstimationHoursCloseModal, | ||
openAddTasksEstimationHoursModal, | ||
isSuggestDailyPlanModalOpen, | ||
suggestDailyPlanCloseModal, | ||
openSuggestDailyPlanModal | ||
}, | ||
startStopTimerHandler | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
apps/web/lib/features/daily-plan/add-daily-plan-work-hours-modal.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import { Card, InputField, Modal, Text } from 'lib/components'; | ||
import { Button } from '@components/ui/button'; | ||
import { useCallback, useMemo, useState } from 'react'; | ||
import { DAILY_PLAN_ESTIMATE_HOURS_MODAL_DATE } from '@app/constants'; | ||
import { IDailyPlan } from '@app/interfaces'; | ||
import { useDailyPlan, useTeamTasks, useTimerView } from '@app/hooks'; | ||
import { useTranslations } from 'next-intl'; | ||
|
||
interface IAddDailyPlanWorkHoursModalProps { | ||
closeModal: () => void; | ||
isOpen: boolean; | ||
plan: IDailyPlan; | ||
} | ||
|
||
export function AddDailyPlanWorkHourModal(props: IAddDailyPlanWorkHoursModalProps) { | ||
const { closeModal, isOpen, plan } = props; | ||
|
||
const t = useTranslations(); | ||
const { updateDailyPlan } = useDailyPlan(); | ||
const { startTimer } = useTimerView(); | ||
const { activeTeam } = useTeamTasks(); | ||
|
||
const [workTimePlanned, setworkTimePlanned] = useState<number | undefined>(plan.workTimePlanned); | ||
const currentDate = useMemo(() => new Date().toISOString().split('T')[0], []); | ||
const requirePlan = useMemo(() => activeTeam?.requirePlanToTrack, [activeTeam?.requirePlanToTrack]); | ||
const hasWorkHours = useMemo(() => plan.workTimePlanned && plan.workTimePlanned > 0, [plan.workTimePlanned]); | ||
|
||
const handleCloseModal = useCallback(() => { | ||
localStorage.setItem(DAILY_PLAN_ESTIMATE_HOURS_MODAL_DATE, currentDate); | ||
closeModal(); | ||
}, [closeModal, currentDate]); | ||
|
||
const handleSubmit = useCallback(() => { | ||
updateDailyPlan({ workTimePlanned }, plan.id ?? ''); | ||
startTimer(); | ||
handleCloseModal(); | ||
}, [handleCloseModal, plan.id, startTimer, updateDailyPlan, workTimePlanned]); | ||
|
||
return ( | ||
<Modal isOpen={isOpen} closeModal={handleCloseModal} showCloseIcon={requirePlan ? false : true}> | ||
<Card className="w-full" shadow="custom"> | ||
<div className="flex flex-col justify-between"> | ||
<div className="mb-7"> | ||
<Text.Heading as="h3" className="mb-3 text-center"> | ||
{t('timer.todayPlanSettings.TITLE')} | ||
</Text.Heading> | ||
<div className="mb-7 w-full flex flex-col gap-4"> | ||
<span className="text-sm"> | ||
{t('timer.todayPlanSettings.WORK_TIME_PLANNED')} <span className="text-red-600">*</span> | ||
</span> | ||
|
||
<InputField | ||
type="number" | ||
placeholder={t('timer.todayPlanSettings.WORK_TIME_PLANNED_PLACEHOLDER')} | ||
className="mb-0 min-w-[350px]" | ||
wrapperClassName="mb-0 rounded-lg" | ||
onChange={(e) => setworkTimePlanned(parseFloat(e.target.value))} | ||
required | ||
min={0} | ||
value={workTimePlanned} | ||
defaultValue={plan.workTimePlanned ?? 0} | ||
/> | ||
</div> | ||
</div> | ||
<div className="mt-6 flex justify-between items-center"> | ||
<Button | ||
variant="outline" | ||
type="submit" | ||
className="py-3 px-5 rounded-md font-light text-md dark:text-white dark:bg-slate-700 dark:border-slate-600" | ||
onClick={handleCloseModal} | ||
> | ||
{t('common.SKIP_ADD_LATER')} | ||
</Button> | ||
<Button | ||
variant="default" | ||
type="submit" | ||
disabled={requirePlan ? (hasWorkHours ? false : true) : false} | ||
className="py-3 px-5 rounded-md font-light text-md dark:text-white" | ||
onClick={handleSubmit} | ||
> | ||
{t('timer.todayPlanSettings.START_WORKING_BUTTON')} | ||
</Button> | ||
</div> | ||
</div> | ||
</Card> | ||
</Modal> | ||
); | ||
} |
Oops, something went wrong.