cd78f72f33
Complete rename of all technical identifiers across the codebase: Package names (11 packages): - @planarchy/* → @capakraken/* in all package.json, tsconfig, imports Import statements: 277 files, 548 occurrences replaced Database & Docker: - PostgreSQL user/db: planarchy → capakraken - Docker volumes: planarchy_pgdata → capakraken_pgdata - Connection strings updated in docker-compose, .env, CI CI/CD: - GitHub Actions workflow: all filter commands updated - Test database credentials updated Infrastructure: - Redis channel: planarchy:sse → capakraken:sse - Logger service name: planarchy-api → capakraken-api - Anonymization seed updated - Start/stop/restart scripts updated Test data: - Seed emails: @planarchy.dev → @capakraken.dev - E2E test credentials: all 11 spec files updated - Email defaults: @planarchy.app → @capakraken.app - localStorage keys: planarchy_* → capakraken_* Documentation: 30+ .md files updated Verification: - pnpm install: workspace resolution works - TypeScript: only pre-existing TS2589 (no new errors) - Engine: 310/310 tests pass - Staffing: 37/37 tests pass Co-Authored-By: claude-flow <ruv@ruv.net>
110 lines
3.6 KiB
TypeScript
110 lines
3.6 KiB
TypeScript
"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;
|
|
/** Show open demand / placeholder entries by default when loading the timeline. Default: true. */
|
|
showDemandProjects: boolean;
|
|
/** Blink overbooked days (>8h) as a warning on the timeline. Default: false. */
|
|
blinkOverbookedDays: boolean;
|
|
}
|
|
|
|
const STORAGE_KEY = "capakraken_prefs";
|
|
const CHANGE_EVENT = "capakraken-prefs-changed";
|
|
|
|
const DEFAULT: AppPreferences = {
|
|
hideCompletedProjects: true,
|
|
timelineDisplayMode: "strip",
|
|
heatmapColorScheme: "green-red",
|
|
showDemandProjects: true,
|
|
blinkOverbookedDays: false,
|
|
};
|
|
|
|
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;
|
|
});
|
|
}, []);
|
|
|
|
const setShowDemandProjects = useCallback((value: boolean) => {
|
|
setPrefs((prev) => {
|
|
const next = { ...prev, showDemandProjects: value };
|
|
saveAppPreferences(next);
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
const setBlinkOverbookedDays = useCallback((value: boolean) => {
|
|
setPrefs((prev) => {
|
|
const next = { ...prev, blinkOverbookedDays: value };
|
|
saveAppPreferences(next);
|
|
return next;
|
|
});
|
|
}, []);
|
|
|
|
return { prefs, setHideCompletedProjects, setTimelineDisplayMode, setHeatmapColorScheme, setShowDemandProjects, setBlinkOverbookedDays };
|
|
}
|