119 lines
3.0 KiB
TypeScript
119 lines
3.0 KiB
TypeScript
/**
|
||
* Shared design tokens + KPI data for the AI Logistics Optimization section.
|
||
* Centralizing here keeps the 3D scene, overlay and metrics panel in sync.
|
||
*/
|
||
|
||
export const COLORS = {
|
||
bg: "#020617",
|
||
cyan: "#00E5FF",
|
||
green: "#22C55E",
|
||
red: "#EF4444",
|
||
amber: "#F59E0B",
|
||
ink: "#0B1220",
|
||
slate: "#64748B",
|
||
textDim: "rgba(226,232,240,0.66)",
|
||
} as const;
|
||
|
||
/** rgba helper used by inline styles + scoped CSS. */
|
||
export function rgba(hex: string, alpha: number): string {
|
||
const h = hex.replace("#", "");
|
||
const r = parseInt(h.substring(0, 2), 16);
|
||
const g = parseInt(h.substring(2, 4), 16);
|
||
const b = parseInt(h.substring(4, 6), 16);
|
||
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
|
||
}
|
||
|
||
export type Kpi = {
|
||
key: string;
|
||
/** numeric value the counter animates between */
|
||
before: number;
|
||
after: number;
|
||
prefixBefore?: string;
|
||
prefixAfter?: string;
|
||
suffix?: string;
|
||
labelBefore: string;
|
||
labelAfter: string;
|
||
/** lower number is the better outcome (drives the up/down arrow) */
|
||
goodWhenLower: boolean;
|
||
};
|
||
|
||
export const KPIS: Kpi[] = [
|
||
{
|
||
key: "distance",
|
||
before: 312,
|
||
after: 182,
|
||
suffix: " km",
|
||
labelBefore: "Route Distance",
|
||
labelAfter: "Route Distance",
|
||
goodWhenLower: true,
|
||
},
|
||
{
|
||
key: "vehicles",
|
||
before: 8,
|
||
after: 5,
|
||
labelBefore: "Vehicles",
|
||
labelAfter: "Vehicles",
|
||
goodWhenLower: true,
|
||
},
|
||
{
|
||
key: "orders",
|
||
before: 59,
|
||
after: 59,
|
||
labelBefore: "Orders",
|
||
labelAfter: "Orders Fulfilled",
|
||
goodWhenLower: false,
|
||
},
|
||
{
|
||
key: "delayed",
|
||
before: 23,
|
||
after: 0,
|
||
labelBefore: "Delayed",
|
||
labelAfter: "Delayed",
|
||
goodWhenLower: true,
|
||
},
|
||
{
|
||
key: "cost",
|
||
before: 18,
|
||
after: 18,
|
||
prefixBefore: "+",
|
||
prefixAfter: "−",
|
||
suffix: "%",
|
||
labelBefore: "Cost Overrun",
|
||
labelAfter: "Cost Saved",
|
||
goodWhenLower: false,
|
||
},
|
||
];
|
||
|
||
/**
|
||
* Scroll-phase thresholds (normalized 0 → 1). The whole narrative is driven by
|
||
* a single scroll progress value shared between GSAP, R3F and Framer Motion.
|
||
*/
|
||
export const PHASES = {
|
||
chaos: 0.0, // Stage 1 & 2: Network appears & vehicles active
|
||
scan: 0.28, // Stage 3: AI scans routes
|
||
dissolve: 0.42, // Stage 4 & 5: Optimize begins & bad routes dissolve
|
||
optimize: 0.56, // Stage 6: Optimized routes appear
|
||
reorganize: 0.70, // Reassigning vehicles
|
||
metrics: 0.84, // Stage 7: KPIs update & complete
|
||
} as const;
|
||
|
||
export type PhaseKey = keyof typeof PHASES;
|
||
|
||
export function phaseFromProgress(p: number): PhaseKey {
|
||
if (p >= PHASES.metrics) return "metrics";
|
||
if (p >= PHASES.reorganize) return "reorganize";
|
||
if (p >= PHASES.optimize) return "optimize";
|
||
if (p >= PHASES.dissolve) return "dissolve";
|
||
if (p >= PHASES.scan) return "scan";
|
||
return "chaos";
|
||
}
|
||
|
||
export const PHASE_LABELS: Record<PhaseKey, string> = {
|
||
chaos: "Monitoring network",
|
||
scan: "AI SCANNING NETWORK",
|
||
dissolve: "AI OPTIMIZING ROUTES",
|
||
optimize: "AI OPTIMIZING ROUTES",
|
||
reorganize: "AI REASSIGNING VEHICLES",
|
||
metrics: "AI COMPLETE",
|
||
};
|