feat: add PlanningDurationService for estimating planning duration

- Implemented PlanningDurationService to provide an indicative wait time before calculation based on user input and calendar settings.
- Introduced duration estimation logic that considers horizon dates, balances, and rules without triggering a calculation.
- Enhanced user input component to display estimated duration using the new service.
- Updated translation files to include new duration estimate strings in multiple languages.
- Added tests for PlanningDurationService to ensure accurate duration estimation and calibration.
- Refactored leave planner service to remove hardcoded deadlines and improve worker responsiveness.
This commit is contained in:
nessar committed 2026-10-05 17:06:17 +02:00
1 parent 2edf2004f5
commit bc8570d8ca
29 files changed
+1064 -123

No files matched your search

+7
View File
@@ -63,6 +63,7 @@ type WorkerRequest =
};
type WorkerResponse =
| { type: 'heartbeat' }
| { type: 'progress'; stage: string }
| { type: 'trace-overhead'; totalMs: number }
| { type: 'checkpoint'; plan: PlanOutcome; state?: PlanningTraceState }
@@ -301,7 +302,12 @@ worker.onmessage = async (event: MessageEvent<WorkerRequest>) => {
calculationComplete: false,
};
activeTraceDelivery = traceDelivery;
// The cooperative driver yields during preparation and search, even within one phase.
const heartbeat = () =>
worker.postMessage({ type: 'heartbeat' } satisfies WorkerResponse);
const heartbeatTimer = setInterval(heartbeat, 1000);
try {
heartbeat();
outcome = await calculatePlanningAsyncInternal(
{
...event.data.request,
@@ -351,6 +357,7 @@ worker.onmessage = async (event: MessageEvent<WorkerRequest>) => {
} satisfies WorkerResponse);
return;
} finally {
clearInterval(heartbeatTimer);
if (activeCalculation === calculation) activeCalculation = undefined;
}
if (!outcomePosted)