functional

This commit is contained in:
2026-09-17 01:19:19 -04:00
commit 3d4d75fdfb
19 changed files with 3257 additions and 0 deletions
+52
View File
@@ -0,0 +1,52 @@
import type { Config, Selections } from "./types";
type Listener = () => void;
/**
* Minimal reactive store: holds the immutable config plus mutable user
* selections, and notifies subscribers on any change.
*/
export class Store {
private listeners = new Set<Listener>();
constructor(
public readonly config: Config,
private selections: Selections
) {}
getSelections(): Selections {
return this.selections;
}
onChange(listener: Listener): void {
this.listeners.add(listener);
}
private update(patch: Partial<Selections>): void {
this.selections = { ...this.selections, ...patch };
this.emit();
}
setSelectedPlan(planId: string): void {
this.update({ selectedPlanId: planId });
}
setTargetDate(date: Date): void {
this.update({ targetDate: date });
}
setMissingPeriodActive(periodId: string, isActive: boolean): void {
const next = new Set(this.selections.activeMissingPeriodIds);
if (isActive) next.add(periodId);
else next.delete(periodId);
this.update({ activeMissingPeriodIds: next });
}
setExtraExcludedDays(count: number): void {
this.update({ extraExcludedDays: Math.max(0, Math.floor(count) || 0) });
}
private emit(): void {
for (const l of this.listeners) l();
}
}