fix: align scale info with floating timeline
This commit is contained in:
@@ -1,6 +1,10 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { ScheduledConditionItem } from "../types";
|
||||
import { clusterOperationalEvents, createOperationalEvents } from "./operational-timeline-model";
|
||||
import {
|
||||
canDockMapScaleBesideTimeline,
|
||||
clusterOperationalEvents,
|
||||
createOperationalEvents
|
||||
} from "./operational-timeline-model";
|
||||
|
||||
const workOrder: ScheduledConditionItem = {
|
||||
id: "work-1", kind: "work_order", code: "WO-1", scheduledAt: "2026-08-19T10:00:00.000Z",
|
||||
@@ -39,4 +43,10 @@ describe("operational timeline model", () => {
|
||||
expect(clusters).toHaveLength(2);
|
||||
expect(clusters.find((cluster) => cluster.lane === "plan")?.events).toHaveLength(2);
|
||||
});
|
||||
|
||||
it("docks scale info beside a floating timeline only when the business area is wide enough", () => {
|
||||
expect(canDockMapScaleBesideTimeline(2048, "expanded", true)).toBe(true);
|
||||
expect(canDockMapScaleBesideTimeline(1380, "expanded", true)).toBe(false);
|
||||
expect(canDockMapScaleBesideTimeline(1380, "expanded", false)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,6 +30,28 @@ export type OperationalEventCluster = {
|
||||
events: OperationalEvent[];
|
||||
};
|
||||
|
||||
export const OPERATIONAL_TIMELINE_LAYOUT = {
|
||||
compact: { height: 72, maxWidth: 980 },
|
||||
expanded: { height: 240, maxWidth: 1180 },
|
||||
summary: { height: 52, maxWidth: 760 },
|
||||
mobileSummaryHeight: 48,
|
||||
mapScaleSafeWidth: 520,
|
||||
floatingGap: 48
|
||||
} as const;
|
||||
|
||||
export function canDockMapScaleBesideTimeline(
|
||||
businessWorkspaceWidth: number,
|
||||
mode: OperationalTimelineMode,
|
||||
visible: boolean
|
||||
) {
|
||||
if (!visible) return true;
|
||||
const layout = OPERATIONAL_TIMELINE_LAYOUT[mode];
|
||||
return businessWorkspaceWidth >=
|
||||
layout.maxWidth +
|
||||
OPERATIONAL_TIMELINE_LAYOUT.mapScaleSafeWidth +
|
||||
OPERATIONAL_TIMELINE_LAYOUT.floatingGap;
|
||||
}
|
||||
|
||||
export function createOperationalEvents(items: ScheduledConditionItem[]): OperationalEvent[] {
|
||||
return items.flatMap((item) =>
|
||||
item.kind === "work_order" ? createWorkOrderEvents(item) : createConditionEvents(item)
|
||||
|
||||
@@ -13,6 +13,7 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/shar
|
||||
import {
|
||||
clusterOperationalEvents,
|
||||
getOperationalEventSummary,
|
||||
OPERATIONAL_TIMELINE_LAYOUT,
|
||||
type OperationalEvent,
|
||||
type OperationalEventCluster,
|
||||
type OperationalEventLane,
|
||||
@@ -54,7 +55,7 @@ export function OperationalTimeline({
|
||||
const clusters = clusterOperationalEvents(events, mobile ? 60 : 10);
|
||||
const selectedEvent = events.find((event) => event.id === selectedEventId) ?? null;
|
||||
const cursorPosition = getDayPosition(cursorTime);
|
||||
const height = mobile ? "100%" : mode === "expanded" ? 240 : mode === "summary" ? 52 : 72;
|
||||
const height = mobile ? "100%" : OPERATIONAL_TIMELINE_LAYOUT[mode].height;
|
||||
|
||||
if (mode === "summary" && !mobile) {
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user