chore(repo): initialize planarchy workspace

This commit is contained in:
2026-03-14 14:31:09 +01:00
commit dd55d0e78b
769 changed files with 166461 additions and 0 deletions
+87
View File
@@ -0,0 +1,87 @@
"use client";
import { useCallback, useEffect, useState } from "react";
export type HeatmapColorScheme = "green-red" | "blue-orange" | "purple-yellow" | "mono";
export interface AppPreferences {
/** Hide allocations that belong to COMPLETED or CANCELLED projects. Default: true. */
hideCompletedProjects: boolean;
/**
* Timeline row rendering style.
* "strip" — horizontal colored blocks per allocation (classic Gantt) + load graph
* "bar" — stacked vertical bars per day showing hours by project
* "heatmap" — strips overlaid with a green→red utilization colour per day column
*/
timelineDisplayMode: "strip" | "bar" | "heatmap";
/** Color palette used for heatmap overlays and bar-mode project view bars. */
heatmapColorScheme: HeatmapColorScheme;
}
const STORAGE_KEY = "planarchy_prefs";
const CHANGE_EVENT = "planarchy-prefs-changed";
const DEFAULT: AppPreferences = {
hideCompletedProjects: true,
timelineDisplayMode: "strip",
heatmapColorScheme: "green-red",
};
export function readAppPreferences(): AppPreferences {
if (typeof window === "undefined") return DEFAULT;
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return DEFAULT;
return { ...DEFAULT, ...(JSON.parse(raw) as Partial<AppPreferences>) };
} catch {
return DEFAULT;
}
}
function saveAppPreferences(prefs: AppPreferences) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(prefs));
// Broadcast to all hook instances in the same tab
window.dispatchEvent(new CustomEvent<AppPreferences>(CHANGE_EVENT, { detail: prefs }));
}
export function useAppPreferences() {
const [prefs, setPrefs] = useState<AppPreferences>(DEFAULT);
useEffect(() => {
// Sync from storage on mount
setPrefs(readAppPreferences());
// Keep in sync when any hook instance saves a change
function handleChange(e: Event) {
setPrefs((e as CustomEvent<AppPreferences>).detail);
}
window.addEventListener(CHANGE_EVENT, handleChange);
return () => window.removeEventListener(CHANGE_EVENT, handleChange);
}, []);
const setHideCompletedProjects = useCallback((value: boolean) => {
setPrefs((prev) => {
const next = { ...prev, hideCompletedProjects: value };
saveAppPreferences(next);
return next;
});
}, []);
const setTimelineDisplayMode = useCallback((value: AppPreferences["timelineDisplayMode"]) => {
setPrefs((prev) => {
const next = { ...prev, timelineDisplayMode: value };
saveAppPreferences(next);
return next;
});
}, []);
const setHeatmapColorScheme = useCallback((value: HeatmapColorScheme) => {
setPrefs((prev) => {
const next = { ...prev, heatmapColorScheme: value };
saveAppPreferences(next);
return next;
});
}, []);
return { prefs, setHideCompletedProjects, setTimelineDisplayMode, setHeatmapColorScheme };
}