functional
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user