@optifye/dashboard-core 6.12.49 → 6.12.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +22 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +375 -120
- package/dist/index.mjs +375 -120
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13791,12 +13791,22 @@ var stripSeconds = (timeStr) => {
|
|
|
13791
13791
|
if (!timeStr) return timeStr;
|
|
13792
13792
|
return timeStr.substring(0, 5);
|
|
13793
13793
|
};
|
|
13794
|
+
var normalizeOffDays = (value) => {
|
|
13795
|
+
if (!value) return [];
|
|
13796
|
+
if (Array.isArray(value)) {
|
|
13797
|
+
return value.map((day) => String(day || "").trim().toLowerCase()).filter(Boolean);
|
|
13798
|
+
}
|
|
13799
|
+
if (Array.isArray(value.off_days)) return normalizeOffDays(value.off_days);
|
|
13800
|
+
if (Array.isArray(value.offDays)) return normalizeOffDays(value.offDays);
|
|
13801
|
+
return [];
|
|
13802
|
+
};
|
|
13794
13803
|
var buildShiftConfigFromOperatingHoursRows = (rows, fallback) => {
|
|
13795
13804
|
const mapped = (rows || []).map((row) => ({
|
|
13796
13805
|
shiftId: row.shift_id,
|
|
13797
13806
|
shiftName: row.shift_name || `Shift ${row.shift_id}`,
|
|
13798
13807
|
startTime: stripSeconds(row.start_time),
|
|
13799
13808
|
endTime: stripSeconds(row.end_time),
|
|
13809
|
+
offDays: normalizeOffDays(row.off_days),
|
|
13800
13810
|
breaks: (() => {
|
|
13801
13811
|
const raw = Array.isArray(row.breaks) ? row.breaks : Array.isArray(row.breaks?.breaks) ? row.breaks.breaks : [];
|
|
13802
13812
|
return raw.map((b) => ({
|
|
@@ -13856,7 +13866,7 @@ var fetchAndStoreShiftConfig = async (supabase, lineId, fallback) => {
|
|
|
13856
13866
|
if (existing) return existing;
|
|
13857
13867
|
const promise = (async () => {
|
|
13858
13868
|
try {
|
|
13859
|
-
const { data, error } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks, timezone").eq("line_id", lineId);
|
|
13869
|
+
const { data, error } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks, timezone, off_days").eq("line_id", lineId);
|
|
13860
13870
|
if (error) {
|
|
13861
13871
|
throw new Error(`Failed to fetch shift config: ${error.message}`);
|
|
13862
13872
|
}
|
|
@@ -14549,7 +14559,7 @@ var useMultiLineShiftConfigs = (lineIds, fallbackConfig) => {
|
|
|
14549
14559
|
setError(null);
|
|
14550
14560
|
}
|
|
14551
14561
|
console.log(`[useMultiLineShiftConfigs] Fetching shift configs for ${missingLineIds.length} lines`);
|
|
14552
|
-
const { data, error: fetchError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks, timezone").in("line_id", missingLineIds);
|
|
14562
|
+
const { data, error: fetchError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks, timezone, off_days").in("line_id", missingLineIds);
|
|
14553
14563
|
if (fetchError) {
|
|
14554
14564
|
console.error("[useMultiLineShiftConfigs] Error fetching shift configs:", fetchError);
|
|
14555
14565
|
throw new Error(`Failed to fetch shift configs: ${fetchError.message}`);
|
|
@@ -37779,7 +37789,12 @@ var HourlyOutputChartComponent = ({
|
|
|
37779
37789
|
}, [idleBarState.visible, idleBarState.key, idleBarState.shouldAnimate]);
|
|
37780
37790
|
const maxDataValue = Math.max(...data, 0);
|
|
37781
37791
|
const numericChartTargets = chartData.map((d) => d.target).filter((target) => target !== null && Number.isFinite(target));
|
|
37782
|
-
const
|
|
37792
|
+
const hasAuthoritativeNumericTargets = hasHourlyTargetOutputProp && numericChartTargets.length > 0;
|
|
37793
|
+
const maxTargetValue = Math.max(
|
|
37794
|
+
...numericChartTargets,
|
|
37795
|
+
hasAuthoritativeNumericTargets ? 0 : pphThreshold,
|
|
37796
|
+
0
|
|
37797
|
+
);
|
|
37783
37798
|
const maxYValue = Math.max(
|
|
37784
37799
|
Math.ceil(maxTargetValue * 1.5),
|
|
37785
37800
|
Math.ceil(maxDataValue * 1.15)
|
|
@@ -37934,14 +37949,9 @@ var HourlyOutputChartComponent = ({
|
|
|
37934
37949
|
return /* @__PURE__ */ jsx("g", { children: lines });
|
|
37935
37950
|
}, [hourlyTargetSegments, targetTimelineSegments, SHIFT_DURATION, pphThreshold, targetLineEndOffset, hasHourlyTargetOutputProp]);
|
|
37936
37951
|
const renderLegend = () => {
|
|
37937
|
-
const uniqueTargets = [...new Set(
|
|
37938
|
-
chartData.map((d) => d.target).filter((target) => target !== null && Number.isFinite(target)).map((target) => Math.round(target))
|
|
37939
|
-
)].sort((a, b) => a - b);
|
|
37940
|
-
const unitLabel = hasHourlyTargetOutputProp ? "units" : "units/hr";
|
|
37941
|
-
const targetText = uniqueTargets.length === 0 ? `Target` : uniqueTargets.length === 1 ? `Target: ${uniqueTargets[0]} ${unitLabel}` : `Target: ${uniqueTargets[0]} - ${uniqueTargets[uniqueTargets.length - 1]} ${unitLabel}`;
|
|
37942
37952
|
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center text-sm text-gray-600 bg-white py-1", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border border-gray-100 rounded-full px-3 py-1", children: [
|
|
37943
37953
|
/* @__PURE__ */ jsx("div", { className: "w-8 flex items-center", children: /* @__PURE__ */ jsx("div", { className: "w-full border-t-2 border-[#E34329] border-dashed" }) }),
|
|
37944
|
-
/* @__PURE__ */ jsx("span", { children:
|
|
37954
|
+
/* @__PURE__ */ jsx("span", { children: "Target" })
|
|
37945
37955
|
] }) });
|
|
37946
37956
|
};
|
|
37947
37957
|
return /* @__PURE__ */ jsxs(
|
|
@@ -52459,6 +52469,106 @@ var getOrdinal = (n) => {
|
|
|
52459
52469
|
const v = n % 100;
|
|
52460
52470
|
return n + (suffix[(v - 20) % 10] || suffix[v] || suffix[0]);
|
|
52461
52471
|
};
|
|
52472
|
+
var resolveDailyTargetOutput = (shiftData) => {
|
|
52473
|
+
if (!shiftData || shiftData.hasData === false) return 0;
|
|
52474
|
+
const target = Number(shiftData?.targetOutput || shiftData?.idealOutput || 0);
|
|
52475
|
+
return Number.isFinite(target) && target > 0 ? target : 0;
|
|
52476
|
+
};
|
|
52477
|
+
var getUniqueRoundedTargets = (data) => Array.from(new Set(
|
|
52478
|
+
data.map((entry) => Number(entry.targetOutput || 0)).filter((target) => Number.isFinite(target) && target > 0).map((target) => Math.round(target))
|
|
52479
|
+
)).sort((a, b) => a - b);
|
|
52480
|
+
var formatDailyTargetLegend = (targets) => {
|
|
52481
|
+
if (targets.length === 0) return "";
|
|
52482
|
+
if (targets.length === 1) return `Target: ${targets[0].toLocaleString()} units/day`;
|
|
52483
|
+
return `Target: ${targets[0].toLocaleString()} - ${targets[targets.length - 1].toLocaleString()} units/day`;
|
|
52484
|
+
};
|
|
52485
|
+
var WEEKDAY_NAMES = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
|
52486
|
+
var getShiftOffDays = (shiftConfig, selectedShiftId) => {
|
|
52487
|
+
const shift = shiftConfig?.shifts?.find((candidate) => candidate.shiftId === selectedShiftId);
|
|
52488
|
+
const raw = shift?.offDays || shift?.off_days || [];
|
|
52489
|
+
return Array.isArray(raw) ? raw.map((day) => String(day || "").trim().toLowerCase()).filter(Boolean) : [];
|
|
52490
|
+
};
|
|
52491
|
+
var isScheduledOffDay = (dateKey, shiftConfig, selectedShiftId) => {
|
|
52492
|
+
const offDays = getShiftOffDays(shiftConfig, selectedShiftId);
|
|
52493
|
+
if (offDays.length === 0) return false;
|
|
52494
|
+
const date = parseDateKeyToDate(dateKey);
|
|
52495
|
+
return offDays.includes(WEEKDAY_NAMES[date.getDay()]);
|
|
52496
|
+
};
|
|
52497
|
+
var renderDailyOutputCapsules = (props, data) => {
|
|
52498
|
+
const { offset, yAxisMap } = props;
|
|
52499
|
+
if (!offset || !yAxisMap || data.length === 0) return null;
|
|
52500
|
+
const { left, width } = offset;
|
|
52501
|
+
const yAxis = yAxisMap.default || yAxisMap[0];
|
|
52502
|
+
if (!Number.isFinite(left) || !Number.isFinite(width) || width <= 0 || !yAxis?.scale) {
|
|
52503
|
+
return null;
|
|
52504
|
+
}
|
|
52505
|
+
const slotWidth = width / data.length;
|
|
52506
|
+
const capsuleWidth = Math.max(10, Math.min(28, slotWidth * 0.44));
|
|
52507
|
+
const radius = capsuleWidth / 2;
|
|
52508
|
+
const baseY = yAxis.scale(0);
|
|
52509
|
+
const capsules = [];
|
|
52510
|
+
data.forEach((entry, index) => {
|
|
52511
|
+
const target = Number(entry.targetOutput || 0);
|
|
52512
|
+
const output = Number(entry.output || 0);
|
|
52513
|
+
if ((!Number.isFinite(target) || target <= 0) && (!Number.isFinite(output) || output <= 0)) return;
|
|
52514
|
+
const x = left + index * slotWidth + (slotWidth - capsuleWidth) / 2;
|
|
52515
|
+
const targetTop = target > 0 ? yAxis.scale(target) : yAxis.scale(output);
|
|
52516
|
+
const capsuleTop = Math.min(targetTop, baseY - 4);
|
|
52517
|
+
const capsuleHeight = Math.max(baseY - capsuleTop, 4);
|
|
52518
|
+
const fillValue = target > 0 ? Math.min(Math.max(output, 0), target) : Math.max(output, 0);
|
|
52519
|
+
const fillTop = fillValue > 0 ? Math.max(yAxis.scale(fillValue), capsuleTop) : baseY;
|
|
52520
|
+
const fillHeight = Math.max(baseY - fillTop, 0);
|
|
52521
|
+
const fillColor = target > 0 ? output >= target ? "#00AB45" : "#E34329" : entry.color || "#6b7280";
|
|
52522
|
+
const trackFill = output >= target ? "#f0fdf4" : "#fff5f3";
|
|
52523
|
+
const trackStroke = output >= target ? "#00AB45" : "#E34329";
|
|
52524
|
+
const clipId = `line-daily-output-capsule-${index}`;
|
|
52525
|
+
capsules.push(
|
|
52526
|
+
/* @__PURE__ */ jsxs("g", { children: [
|
|
52527
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsx(
|
|
52528
|
+
"rect",
|
|
52529
|
+
{
|
|
52530
|
+
x,
|
|
52531
|
+
y: capsuleTop,
|
|
52532
|
+
width: capsuleWidth,
|
|
52533
|
+
height: capsuleHeight,
|
|
52534
|
+
rx: radius,
|
|
52535
|
+
ry: radius
|
|
52536
|
+
}
|
|
52537
|
+
) }) }),
|
|
52538
|
+
target > 0 && /* @__PURE__ */ jsx(
|
|
52539
|
+
"rect",
|
|
52540
|
+
{
|
|
52541
|
+
"data-testid": "daily-target-capsule-track",
|
|
52542
|
+
x,
|
|
52543
|
+
y: capsuleTop,
|
|
52544
|
+
width: capsuleWidth,
|
|
52545
|
+
height: capsuleHeight,
|
|
52546
|
+
rx: radius,
|
|
52547
|
+
ry: radius,
|
|
52548
|
+
fill: trackFill,
|
|
52549
|
+
stroke: trackStroke,
|
|
52550
|
+
strokeWidth: 1.5
|
|
52551
|
+
}
|
|
52552
|
+
),
|
|
52553
|
+
/* @__PURE__ */ jsx(
|
|
52554
|
+
"rect",
|
|
52555
|
+
{
|
|
52556
|
+
"data-testid": "daily-output-capsule-fill",
|
|
52557
|
+
x,
|
|
52558
|
+
y: fillTop,
|
|
52559
|
+
width: capsuleWidth,
|
|
52560
|
+
height: fillHeight,
|
|
52561
|
+
rx: fillHeight >= capsuleHeight ? radius : 0,
|
|
52562
|
+
ry: fillHeight >= capsuleHeight ? radius : 0,
|
|
52563
|
+
fill: fillColor,
|
|
52564
|
+
clipPath: target > 0 ? `url(#${clipId})` : void 0
|
|
52565
|
+
}
|
|
52566
|
+
)
|
|
52567
|
+
] }, `daily-output-capsule-${index}`)
|
|
52568
|
+
);
|
|
52569
|
+
});
|
|
52570
|
+
return capsules.length > 0 ? /* @__PURE__ */ jsx("g", { children: capsules }) : null;
|
|
52571
|
+
};
|
|
52462
52572
|
var CustomTooltip2 = ({ active, payload, label, isUptimeMode }) => {
|
|
52463
52573
|
if (!active || !payload || payload.length === 0) return null;
|
|
52464
52574
|
if (isUptimeMode) {
|
|
@@ -52542,6 +52652,7 @@ var LineMonthlyHistory = ({
|
|
|
52542
52652
|
legend,
|
|
52543
52653
|
monitoringMode,
|
|
52544
52654
|
lineAssembly = false,
|
|
52655
|
+
shiftConfig,
|
|
52545
52656
|
underperformingWorkspaces = {},
|
|
52546
52657
|
lineId,
|
|
52547
52658
|
selectedShiftId = 0,
|
|
@@ -52559,6 +52670,13 @@ var LineMonthlyHistory = ({
|
|
|
52559
52670
|
const { isIdleTimeVlmEnabled } = useIdleTimeVlmConfig();
|
|
52560
52671
|
const idleTimeVlmEnabled = isIdleTimeVlmEnabled(lineId);
|
|
52561
52672
|
const isUptimeMode = monitoringMode === "uptime";
|
|
52673
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
52674
|
+
useEffect(() => {
|
|
52675
|
+
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
52676
|
+
checkMobile();
|
|
52677
|
+
window.addEventListener("resize", checkMobile);
|
|
52678
|
+
return () => window.removeEventListener("resize", checkMobile);
|
|
52679
|
+
}, []);
|
|
52562
52680
|
const chartKey = useMemo(() => `${lineId}-${month}-${year}-${selectedShiftId}-${rangeStart}-${rangeEnd}`, [lineId, month, year, selectedShiftId, rangeStart, rangeEnd]);
|
|
52563
52681
|
const monthBounds = useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
52564
52682
|
const normalizedRange = useMemo(() => {
|
|
@@ -52720,29 +52838,21 @@ var LineMonthlyHistory = ({
|
|
|
52720
52838
|
});
|
|
52721
52839
|
}
|
|
52722
52840
|
const yAxisMax2 = maxHours > 0 ? 100 : 1;
|
|
52723
|
-
return { data: dailyData2, maxOutput: 0,
|
|
52841
|
+
return { data: dailyData2, maxOutput: 0, targetValues: [], yAxisMax: yAxisMax2, targetLegend: "" };
|
|
52724
52842
|
}
|
|
52725
52843
|
const dailyData = [];
|
|
52726
52844
|
let maxOutput = 0;
|
|
52727
|
-
let
|
|
52728
|
-
for (let i = rangeDateKeys.length - 1; i >= 0; i--) {
|
|
52729
|
-
const dayKey = rangeDateKeys[i];
|
|
52730
|
-
const dayData = analysisMonthlyDataByKey.get(dayKey);
|
|
52731
|
-
const shiftData = dayData ? getShiftData2(dayData, selectedShiftId) : null;
|
|
52732
|
-
const idealOutput = shiftData ? shiftData.idealOutput || 0 : 0;
|
|
52733
|
-
if (idealOutput > 0) {
|
|
52734
|
-
lastSetTarget = idealOutput;
|
|
52735
|
-
break;
|
|
52736
|
-
}
|
|
52737
|
-
}
|
|
52845
|
+
let maxTarget = 0;
|
|
52738
52846
|
for (const dayKey of rangeDateKeys) {
|
|
52739
52847
|
const day = Number(dayKey.slice(-2));
|
|
52740
52848
|
const dayData = analysisMonthlyDataByKey.get(dayKey);
|
|
52849
|
+
const isOffDay = isScheduledOffDay(dayKey, shiftConfig, selectedShiftId);
|
|
52741
52850
|
const shiftData = dayData ? getShiftData2(dayData, selectedShiftId) : null;
|
|
52742
|
-
const output = shiftData && hasRealData(shiftData) ? shiftData.output || 0 : 0;
|
|
52743
|
-
const
|
|
52851
|
+
const output = !isOffDay && shiftData && hasRealData(shiftData) ? shiftData.output || 0 : 0;
|
|
52852
|
+
const targetOutput = isOffDay ? 0 : resolveDailyTargetOutput(shiftData);
|
|
52744
52853
|
if (output > maxOutput) maxOutput = output;
|
|
52745
|
-
|
|
52854
|
+
if (targetOutput > maxTarget) maxTarget = targetOutput;
|
|
52855
|
+
const color2 = targetOutput > 0 && output >= targetOutput ? "#00AB45" : "#E34329";
|
|
52746
52856
|
dailyData.push({
|
|
52747
52857
|
hour: getOrdinal(day),
|
|
52748
52858
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -52750,17 +52860,25 @@ var LineMonthlyHistory = ({
|
|
|
52750
52860
|
output,
|
|
52751
52861
|
originalOutput: output,
|
|
52752
52862
|
// For label display
|
|
52753
|
-
idealOutput,
|
|
52863
|
+
idealOutput: targetOutput,
|
|
52864
|
+
targetOutput,
|
|
52754
52865
|
color: color2
|
|
52755
52866
|
});
|
|
52756
52867
|
}
|
|
52757
|
-
const calculatedMax = Math.max(maxOutput,
|
|
52868
|
+
const calculatedMax = Math.max(maxOutput, maxTarget);
|
|
52758
52869
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
52759
|
-
|
|
52760
|
-
|
|
52870
|
+
const targetValues = getUniqueRoundedTargets(dailyData);
|
|
52871
|
+
return {
|
|
52872
|
+
data: dailyData,
|
|
52873
|
+
maxOutput,
|
|
52874
|
+
targetValues,
|
|
52875
|
+
yAxisMax,
|
|
52876
|
+
targetLegend: formatDailyTargetLegend(targetValues)
|
|
52877
|
+
};
|
|
52878
|
+
}, [analysisMonthlyDataByKey, normalizedRange.endKey, normalizedRange.startKey, selectedShiftId, isUptimeMode, timezone, shiftConfig]);
|
|
52761
52879
|
const yAxisTicks = useMemo(() => {
|
|
52762
52880
|
const max = chartData.yAxisMax;
|
|
52763
|
-
const
|
|
52881
|
+
const targets = chartData.targetValues || [];
|
|
52764
52882
|
if (!max || max <= 0) return void 0;
|
|
52765
52883
|
const desiredIntervals = 4;
|
|
52766
52884
|
const roughStep = max / desiredIntervals;
|
|
@@ -52774,11 +52892,18 @@ var LineMonthlyHistory = ({
|
|
|
52774
52892
|
for (let v = 0; v <= max; v += step) {
|
|
52775
52893
|
ticks.push(Math.round(v));
|
|
52776
52894
|
}
|
|
52777
|
-
|
|
52778
|
-
ticks.push(Math.round(target));
|
|
52779
|
-
}
|
|
52895
|
+
targets.forEach((target) => ticks.push(Math.round(target)));
|
|
52780
52896
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
52781
|
-
}, [chartData.yAxisMax, chartData.
|
|
52897
|
+
}, [chartData.yAxisMax, chartData.targetValues]);
|
|
52898
|
+
const visibleYAxisTicks = useMemo(() => {
|
|
52899
|
+
if (!isMobile || isUptimeMode || !yAxisTicks || yAxisTicks.length <= 3) return yAxisTicks;
|
|
52900
|
+
const importantTicks = /* @__PURE__ */ new Set([
|
|
52901
|
+
0,
|
|
52902
|
+
Math.round(chartData.yAxisMax),
|
|
52903
|
+
...chartData.targetValues || []
|
|
52904
|
+
]);
|
|
52905
|
+
return yAxisTicks.filter((tick) => importantTicks.has(Math.round(tick))).sort((a, b) => a - b).slice(-3);
|
|
52906
|
+
}, [chartData.targetValues, chartData.yAxisMax, isMobile, isUptimeMode, yAxisTicks]);
|
|
52782
52907
|
const pieChartData = useMemo(() => {
|
|
52783
52908
|
if (!isUptimeMode) return [];
|
|
52784
52909
|
const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
|
|
@@ -53097,36 +53222,35 @@ var LineMonthlyHistory = ({
|
|
|
53097
53222
|
] }),
|
|
53098
53223
|
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg sm:rounded-xl shadow-sm border border-gray-100 p-2 sm:p-3 lg:p-4", children: [
|
|
53099
53224
|
/* @__PURE__ */ jsx("h3", { className: "text-xs sm:text-sm font-bold text-gray-700 mb-1 sm:mb-2 text-left", children: isUptimeMode ? "Daily Utilization" : "Daily Output" }),
|
|
53100
|
-
/* @__PURE__ */ jsx("div", { className: "h-[
|
|
53225
|
+
/* @__PURE__ */ jsx("div", { className: "h-[140px] sm:h-[180px] lg:h-[220px]", children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
|
|
53101
53226
|
BarChart$1,
|
|
53102
53227
|
{
|
|
53103
53228
|
data: chartData.data,
|
|
53104
|
-
margin: { top: 20, right: 10, bottom: 40, left: 10 },
|
|
53229
|
+
margin: isMobile ? { top: 8, right: 4, bottom: 28, left: 0 } : { top: 20, right: 10, bottom: 40, left: 10 },
|
|
53105
53230
|
children: [
|
|
53106
53231
|
/* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#f3f4f6" }),
|
|
53107
53232
|
/* @__PURE__ */ jsx(
|
|
53108
53233
|
XAxis,
|
|
53109
53234
|
{
|
|
53110
53235
|
dataKey: "hour",
|
|
53111
|
-
tick: { fontSize: 10, fill: "#6b7280" },
|
|
53112
|
-
interval: 0,
|
|
53236
|
+
tick: { fontSize: isMobile ? 9 : 10, fill: "#6b7280" },
|
|
53237
|
+
interval: isMobile ? 3 : 0,
|
|
53113
53238
|
angle: -45,
|
|
53114
53239
|
textAnchor: "end",
|
|
53115
|
-
height: 60
|
|
53240
|
+
height: isMobile ? 42 : 60
|
|
53116
53241
|
}
|
|
53117
53242
|
),
|
|
53118
53243
|
/* @__PURE__ */ jsx(
|
|
53119
53244
|
YAxis,
|
|
53120
53245
|
{
|
|
53121
53246
|
domain: [0, chartData.yAxisMax],
|
|
53122
|
-
width: 40,
|
|
53123
|
-
ticks: isUptimeMode ? [0, 25, 50, 75, 100] :
|
|
53247
|
+
width: isMobile ? 34 : 40,
|
|
53248
|
+
ticks: isUptimeMode ? [0, 25, 50, 75, 100] : visibleYAxisTicks,
|
|
53124
53249
|
tickFormatter: isUptimeMode ? (value) => `${value}%` : void 0,
|
|
53125
53250
|
tick: isUptimeMode ? void 0 : (props) => {
|
|
53126
53251
|
const { x, y, payload } = props;
|
|
53127
53252
|
const value = Math.round(payload.value);
|
|
53128
|
-
const
|
|
53129
|
-
const isTarget = value === targetValue && targetValue > 0;
|
|
53253
|
+
const isTarget = (chartData.targetValues || []).includes(value);
|
|
53130
53254
|
return /* @__PURE__ */ jsx(
|
|
53131
53255
|
"text",
|
|
53132
53256
|
{
|
|
@@ -53149,15 +53273,7 @@ var LineMonthlyHistory = ({
|
|
|
53149
53273
|
content: (props) => /* @__PURE__ */ jsx(CustomTooltip2, { ...props, isUptimeMode })
|
|
53150
53274
|
}
|
|
53151
53275
|
),
|
|
53152
|
-
!isUptimeMode &&
|
|
53153
|
-
ReferenceLine,
|
|
53154
|
-
{
|
|
53155
|
-
y: chartData.lastSetTarget,
|
|
53156
|
-
stroke: "#E34329",
|
|
53157
|
-
strokeDasharray: "5 5",
|
|
53158
|
-
strokeWidth: 2
|
|
53159
|
-
}
|
|
53160
|
-
),
|
|
53276
|
+
!isUptimeMode && /* @__PURE__ */ jsx(Customized, { component: (props) => renderDailyOutputCapsules(props, chartData.data) }),
|
|
53161
53277
|
isUptimeMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
53162
53278
|
/* @__PURE__ */ jsx(
|
|
53163
53279
|
Bar,
|
|
@@ -53190,6 +53306,8 @@ var LineMonthlyHistory = ({
|
|
|
53190
53306
|
{
|
|
53191
53307
|
dataKey: "output",
|
|
53192
53308
|
radius: [4, 4, 0, 0],
|
|
53309
|
+
fill: "transparent",
|
|
53310
|
+
opacity: 0,
|
|
53193
53311
|
isAnimationActive: true,
|
|
53194
53312
|
animationBegin: 0,
|
|
53195
53313
|
animationDuration: 1e3,
|
|
@@ -53208,13 +53326,9 @@ var LineMonthlyHistory = ({
|
|
|
53208
53326
|
},
|
|
53209
53327
|
chartKey
|
|
53210
53328
|
) }) }),
|
|
53211
|
-
!isUptimeMode && chartData.
|
|
53212
|
-
/* @__PURE__ */ jsx("div", { className: "w-
|
|
53213
|
-
/* @__PURE__ */
|
|
53214
|
-
"Target: ",
|
|
53215
|
-
Math.round(chartData.lastSetTarget),
|
|
53216
|
-
" units/day"
|
|
53217
|
-
] })
|
|
53329
|
+
!isUptimeMode && chartData.targetValues.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center text-sm text-gray-600 bg-white py-1 pt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 border border-gray-100 rounded-full px-3 py-1", children: [
|
|
53330
|
+
/* @__PURE__ */ jsx("div", { className: "relative h-5 w-3 rounded-full border border-[#E34329] bg-[#fff5f3] overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 bottom-0 h-1/2 bg-[#E34329]" }) }),
|
|
53331
|
+
/* @__PURE__ */ jsx("span", { children: chartData.targetLegend })
|
|
53218
53332
|
] }) })
|
|
53219
53333
|
] })
|
|
53220
53334
|
] })
|
|
@@ -55137,6 +55251,106 @@ var formatCycleSeconds = (value) => {
|
|
|
55137
55251
|
if (!Number.isFinite(value)) return "0.0s";
|
|
55138
55252
|
return `${value.toFixed(1)}s`;
|
|
55139
55253
|
};
|
|
55254
|
+
var resolveDailyTargetOutput2 = (shiftData) => {
|
|
55255
|
+
if (!shiftData || shiftData.hasData === false) return 0;
|
|
55256
|
+
const target = Number(shiftData?.targetOutput || shiftData?.idealOutput || 0);
|
|
55257
|
+
return Number.isFinite(target) && target > 0 ? target : 0;
|
|
55258
|
+
};
|
|
55259
|
+
var getUniqueRoundedTargets2 = (data) => Array.from(new Set(
|
|
55260
|
+
data.map((entry) => Number(entry.targetOutput || 0)).filter((target) => Number.isFinite(target) && target > 0).map((target) => Math.round(target))
|
|
55261
|
+
)).sort((a, b) => a - b);
|
|
55262
|
+
var formatDailyTargetLegend2 = (targets) => {
|
|
55263
|
+
if (targets.length === 0) return "";
|
|
55264
|
+
if (targets.length === 1) return `Target: ${targets[0].toLocaleString()} units/day`;
|
|
55265
|
+
return `Target: ${targets[0].toLocaleString()} - ${targets[targets.length - 1].toLocaleString()} units/day`;
|
|
55266
|
+
};
|
|
55267
|
+
var WEEKDAY_NAMES2 = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
|
55268
|
+
var getShiftOffDays2 = (shiftConfig, selectedShiftId) => {
|
|
55269
|
+
const shift = shiftConfig?.shifts?.find((candidate) => candidate.shiftId === selectedShiftId);
|
|
55270
|
+
const raw = shift?.offDays || shift?.off_days || [];
|
|
55271
|
+
return Array.isArray(raw) ? raw.map((day) => String(day || "").trim().toLowerCase()).filter(Boolean) : [];
|
|
55272
|
+
};
|
|
55273
|
+
var isScheduledOffDay2 = (dateKey, shiftConfig, selectedShiftId) => {
|
|
55274
|
+
const offDays = getShiftOffDays2(shiftConfig, selectedShiftId);
|
|
55275
|
+
if (offDays.length === 0) return false;
|
|
55276
|
+
const date = parseDateKeyToDate(dateKey);
|
|
55277
|
+
return offDays.includes(WEEKDAY_NAMES2[date.getDay()]);
|
|
55278
|
+
};
|
|
55279
|
+
var renderDailyOutputCapsules2 = (props, data) => {
|
|
55280
|
+
const { offset, yAxisMap } = props;
|
|
55281
|
+
if (!offset || !yAxisMap || data.length === 0) return null;
|
|
55282
|
+
const { left, width } = offset;
|
|
55283
|
+
const yAxis = yAxisMap.default || yAxisMap[0];
|
|
55284
|
+
if (!Number.isFinite(left) || !Number.isFinite(width) || width <= 0 || !yAxis?.scale) {
|
|
55285
|
+
return null;
|
|
55286
|
+
}
|
|
55287
|
+
const slotWidth = width / data.length;
|
|
55288
|
+
const capsuleWidth = Math.max(10, Math.min(28, slotWidth * 0.44));
|
|
55289
|
+
const radius = capsuleWidth / 2;
|
|
55290
|
+
const baseY = yAxis.scale(0);
|
|
55291
|
+
const capsules = [];
|
|
55292
|
+
data.forEach((entry, index) => {
|
|
55293
|
+
const target = Number(entry.targetOutput || 0);
|
|
55294
|
+
const output = Number(entry.output || 0);
|
|
55295
|
+
if ((!Number.isFinite(target) || target <= 0) && (!Number.isFinite(output) || output <= 0)) return;
|
|
55296
|
+
const x = left + index * slotWidth + (slotWidth - capsuleWidth) / 2;
|
|
55297
|
+
const targetTop = target > 0 ? yAxis.scale(target) : yAxis.scale(output);
|
|
55298
|
+
const capsuleTop = Math.min(targetTop, baseY - 4);
|
|
55299
|
+
const capsuleHeight = Math.max(baseY - capsuleTop, 4);
|
|
55300
|
+
const fillValue = target > 0 ? Math.min(Math.max(output, 0), target) : Math.max(output, 0);
|
|
55301
|
+
const fillTop = fillValue > 0 ? Math.max(yAxis.scale(fillValue), capsuleTop) : baseY;
|
|
55302
|
+
const fillHeight = Math.max(baseY - fillTop, 0);
|
|
55303
|
+
const fillColor = target > 0 ? output >= target ? "#00AB45" : "#E34329" : entry.color || "#6b7280";
|
|
55304
|
+
const trackFill = output >= target ? "#f0fdf4" : "#fff5f3";
|
|
55305
|
+
const trackStroke = output >= target ? "#00AB45" : "#E34329";
|
|
55306
|
+
const clipId = `workspace-daily-output-capsule-${index}`;
|
|
55307
|
+
capsules.push(
|
|
55308
|
+
/* @__PURE__ */ jsxs("g", { children: [
|
|
55309
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsx(
|
|
55310
|
+
"rect",
|
|
55311
|
+
{
|
|
55312
|
+
x,
|
|
55313
|
+
y: capsuleTop,
|
|
55314
|
+
width: capsuleWidth,
|
|
55315
|
+
height: capsuleHeight,
|
|
55316
|
+
rx: radius,
|
|
55317
|
+
ry: radius
|
|
55318
|
+
}
|
|
55319
|
+
) }) }),
|
|
55320
|
+
target > 0 && /* @__PURE__ */ jsx(
|
|
55321
|
+
"rect",
|
|
55322
|
+
{
|
|
55323
|
+
"data-testid": "daily-target-capsule-track",
|
|
55324
|
+
x,
|
|
55325
|
+
y: capsuleTop,
|
|
55326
|
+
width: capsuleWidth,
|
|
55327
|
+
height: capsuleHeight,
|
|
55328
|
+
rx: radius,
|
|
55329
|
+
ry: radius,
|
|
55330
|
+
fill: trackFill,
|
|
55331
|
+
stroke: trackStroke,
|
|
55332
|
+
strokeWidth: 1.5
|
|
55333
|
+
}
|
|
55334
|
+
),
|
|
55335
|
+
/* @__PURE__ */ jsx(
|
|
55336
|
+
"rect",
|
|
55337
|
+
{
|
|
55338
|
+
"data-testid": "daily-output-capsule-fill",
|
|
55339
|
+
x,
|
|
55340
|
+
y: fillTop,
|
|
55341
|
+
width: capsuleWidth,
|
|
55342
|
+
height: fillHeight,
|
|
55343
|
+
rx: fillHeight >= capsuleHeight ? radius : 0,
|
|
55344
|
+
ry: fillHeight >= capsuleHeight ? radius : 0,
|
|
55345
|
+
fill: fillColor,
|
|
55346
|
+
clipPath: target > 0 ? `url(#${clipId})` : void 0
|
|
55347
|
+
}
|
|
55348
|
+
)
|
|
55349
|
+
] }, `daily-output-capsule-${index}`)
|
|
55350
|
+
);
|
|
55351
|
+
});
|
|
55352
|
+
return capsules.length > 0 ? /* @__PURE__ */ jsx("g", { children: capsules }) : null;
|
|
55353
|
+
};
|
|
55140
55354
|
var CustomTooltip3 = ({ active, payload, label, isUptimeMode }) => {
|
|
55141
55355
|
if (!active || !payload || payload.length === 0) return null;
|
|
55142
55356
|
if (isUptimeMode) {
|
|
@@ -55316,28 +55530,20 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55316
55530
|
});
|
|
55317
55531
|
}
|
|
55318
55532
|
const yAxisMax2 = maxHours > 0 ? maxHours * 1.1 : 1;
|
|
55319
|
-
return { data: dailyData, yAxisMax: yAxisMax2,
|
|
55533
|
+
return { data: dailyData, yAxisMax: yAxisMax2, targetValues: [], targetLegend: "" };
|
|
55320
55534
|
}
|
|
55321
55535
|
let maxOutput = 0;
|
|
55322
|
-
let
|
|
55323
|
-
for (let i = rangeDateKeys.length - 1; i >= 0; i--) {
|
|
55324
|
-
const dateKey = rangeDateKeys[i];
|
|
55325
|
-
const dayData = analysisMonthlyDataByKey.get(dateKey);
|
|
55326
|
-
const shiftData = dayData ? getShiftData(dayData, selectedShiftId) : null;
|
|
55327
|
-
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
55328
|
-
if (idealOutput > 0) {
|
|
55329
|
-
lastSetTarget = idealOutput;
|
|
55330
|
-
break;
|
|
55331
|
-
}
|
|
55332
|
-
}
|
|
55536
|
+
let maxTarget = 0;
|
|
55333
55537
|
for (const dateKey of rangeDateKeys) {
|
|
55334
55538
|
const dayData = analysisMonthlyDataByKey.get(dateKey);
|
|
55335
55539
|
const dayNumber = Number(dateKey.slice(-2));
|
|
55540
|
+
const isOffDay = isScheduledOffDay2(dateKey, shiftConfig, selectedShiftId);
|
|
55336
55541
|
const shiftData = dayData ? getShiftData(dayData, selectedShiftId) : null;
|
|
55337
|
-
const output = shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
55338
|
-
const
|
|
55542
|
+
const output = !isOffDay && shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
55543
|
+
const targetOutput = isOffDay ? 0 : resolveDailyTargetOutput2(shiftData);
|
|
55339
55544
|
if (output > maxOutput) maxOutput = output;
|
|
55340
|
-
|
|
55545
|
+
if (targetOutput > maxTarget) maxTarget = targetOutput;
|
|
55546
|
+
const color2 = targetOutput > 0 && output >= targetOutput ? "#00AB45" : "#E34329";
|
|
55341
55547
|
dailyData.push({
|
|
55342
55548
|
hour: getOrdinal2(dayNumber),
|
|
55343
55549
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -55345,21 +55551,29 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55345
55551
|
output,
|
|
55346
55552
|
originalOutput: output,
|
|
55347
55553
|
// For label display
|
|
55348
|
-
idealOutput,
|
|
55554
|
+
idealOutput: targetOutput,
|
|
55555
|
+
targetOutput,
|
|
55349
55556
|
efficiency: shiftData && hasRealData(shiftData) ? shiftData.efficiency : 0,
|
|
55350
55557
|
color: color2,
|
|
55351
55558
|
idleMinutes: 0
|
|
55352
55559
|
// Not used but keeps structure consistent
|
|
55353
55560
|
});
|
|
55354
55561
|
}
|
|
55355
|
-
const calculatedMax = Math.max(maxOutput,
|
|
55562
|
+
const calculatedMax = Math.max(maxOutput, maxTarget);
|
|
55356
55563
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
55357
|
-
|
|
55358
|
-
|
|
55564
|
+
const targetValues = getUniqueRoundedTargets2(dailyData);
|
|
55565
|
+
return {
|
|
55566
|
+
data: dailyData,
|
|
55567
|
+
maxOutput,
|
|
55568
|
+
targetValues,
|
|
55569
|
+
yAxisMax,
|
|
55570
|
+
targetLegend: formatDailyTargetLegend2(targetValues)
|
|
55571
|
+
};
|
|
55572
|
+
}, [analysisMonthlyDataByKey, rangeDateKeys, selectedShiftId, isUptimeMode, shiftConfig, shiftWorkSeconds]);
|
|
55359
55573
|
const yAxisTicks = useMemo(() => {
|
|
55360
55574
|
if (isUptimeMode) return void 0;
|
|
55361
55575
|
const max = chartData.yAxisMax;
|
|
55362
|
-
const
|
|
55576
|
+
const targets = chartData.targetValues || [];
|
|
55363
55577
|
if (!max || max <= 0) return void 0;
|
|
55364
55578
|
const desiredIntervals = 4;
|
|
55365
55579
|
const roughStep = max / desiredIntervals;
|
|
@@ -55373,7 +55587,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55373
55587
|
for (let v = 0; v <= max; v += step) {
|
|
55374
55588
|
ticks.push(Math.round(v));
|
|
55375
55589
|
}
|
|
55376
|
-
|
|
55590
|
+
targets.forEach((target) => {
|
|
55377
55591
|
const roundedTarget = Math.round(target);
|
|
55378
55592
|
if (!ticks.includes(roundedTarget)) {
|
|
55379
55593
|
let nearestIndex = -1;
|
|
@@ -55392,9 +55606,18 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55392
55606
|
ticks.push(roundedTarget);
|
|
55393
55607
|
}
|
|
55394
55608
|
}
|
|
55395
|
-
}
|
|
55609
|
+
});
|
|
55396
55610
|
return ticks.filter((v) => v >= 0 && v <= max * 1.05).sort((a, b) => a - b);
|
|
55397
|
-
}, [chartData.yAxisMax, chartData.
|
|
55611
|
+
}, [chartData.yAxisMax, chartData.targetValues, isUptimeMode]);
|
|
55612
|
+
const visibleYAxisTicks = useMemo(() => {
|
|
55613
|
+
if (!isMobile || isUptimeMode || !yAxisTicks || yAxisTicks.length <= 3) return yAxisTicks;
|
|
55614
|
+
const importantTicks = /* @__PURE__ */ new Set([
|
|
55615
|
+
0,
|
|
55616
|
+
Math.round(chartData.yAxisMax),
|
|
55617
|
+
...chartData.targetValues || []
|
|
55618
|
+
]);
|
|
55619
|
+
return yAxisTicks.filter((tick) => importantTicks.has(Math.round(tick))).sort((a, b) => a - b).slice(-3);
|
|
55620
|
+
}, [chartData.targetValues, chartData.yAxisMax, isMobile, isUptimeMode, yAxisTicks]);
|
|
55398
55621
|
const pieChartData = useMemo(() => {
|
|
55399
55622
|
const aggregateMode = isUptimeMode ? "uptime" : "output";
|
|
55400
55623
|
const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(
|
|
@@ -55784,22 +56007,22 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55784
56007
|
] }),
|
|
55785
56008
|
(!isAssemblyWorkspace || isUptimeMode) && /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex-1", children: [
|
|
55786
56009
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: isUptimeMode ? "Daily Utilization" : "Daily Output" }),
|
|
55787
|
-
/* @__PURE__ */ jsx("div", { style: { height: "220px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
|
|
56010
|
+
/* @__PURE__ */ jsx("div", { style: { height: isMobile ? "150px" : "220px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
|
|
55788
56011
|
BarChart$1,
|
|
55789
56012
|
{
|
|
55790
56013
|
data: chartData.data,
|
|
55791
|
-
margin: { top: 20, right: 10, bottom: 40, left: 10 },
|
|
56014
|
+
margin: isMobile ? { top: 8, right: 4, bottom: 28, left: 0 } : { top: 20, right: 10, bottom: 40, left: 10 },
|
|
55792
56015
|
children: [
|
|
55793
56016
|
/* @__PURE__ */ jsx(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#f3f4f6" }),
|
|
55794
56017
|
/* @__PURE__ */ jsx(
|
|
55795
56018
|
XAxis,
|
|
55796
56019
|
{
|
|
55797
56020
|
dataKey: "hour",
|
|
55798
|
-
tick: { fontSize: 10, fill: "#6b7280" },
|
|
55799
|
-
interval: isMobile ?
|
|
56021
|
+
tick: { fontSize: isMobile ? 9 : 10, fill: "#6b7280" },
|
|
56022
|
+
interval: isMobile ? 3 : 0,
|
|
55800
56023
|
angle: -45,
|
|
55801
56024
|
textAnchor: "end",
|
|
55802
|
-
height: 60
|
|
56025
|
+
height: isMobile ? 42 : 60
|
|
55803
56026
|
}
|
|
55804
56027
|
),
|
|
55805
56028
|
isUptimeMode ? /* @__PURE__ */ jsx(
|
|
@@ -55814,13 +56037,12 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55814
56037
|
YAxis,
|
|
55815
56038
|
{
|
|
55816
56039
|
domain: [0, chartData.yAxisMax],
|
|
55817
|
-
width: 40,
|
|
55818
|
-
ticks:
|
|
56040
|
+
width: isMobile ? 34 : 40,
|
|
56041
|
+
ticks: visibleYAxisTicks,
|
|
55819
56042
|
tick: (props) => {
|
|
55820
56043
|
const { x, y, payload } = props;
|
|
55821
56044
|
const value = Math.round(payload.value);
|
|
55822
|
-
const
|
|
55823
|
-
const isTarget = value === targetValue && targetValue > 0;
|
|
56045
|
+
const isTarget = (chartData.targetValues || []).includes(value);
|
|
55824
56046
|
return /* @__PURE__ */ jsx(
|
|
55825
56047
|
"text",
|
|
55826
56048
|
{
|
|
@@ -55843,15 +56065,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55843
56065
|
content: (props) => /* @__PURE__ */ jsx(CustomTooltip3, { ...props, isUptimeMode })
|
|
55844
56066
|
}
|
|
55845
56067
|
),
|
|
55846
|
-
!isUptimeMode &&
|
|
55847
|
-
ReferenceLine,
|
|
55848
|
-
{
|
|
55849
|
-
y: chartData.lastSetTarget,
|
|
55850
|
-
stroke: "#E34329",
|
|
55851
|
-
strokeDasharray: "5 5",
|
|
55852
|
-
strokeWidth: 2
|
|
55853
|
-
}
|
|
55854
|
-
),
|
|
56068
|
+
!isUptimeMode && /* @__PURE__ */ jsx(Customized, { component: (props) => renderDailyOutputCapsules2(props, chartData.data) }),
|
|
55855
56069
|
isUptimeMode ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
55856
56070
|
/* @__PURE__ */ jsx(
|
|
55857
56071
|
Bar,
|
|
@@ -55884,6 +56098,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55884
56098
|
{
|
|
55885
56099
|
dataKey: "output",
|
|
55886
56100
|
radius: [4, 4, 0, 0],
|
|
56101
|
+
fill: "transparent",
|
|
56102
|
+
opacity: 0,
|
|
55887
56103
|
isAnimationActive: true,
|
|
55888
56104
|
animationBegin: 0,
|
|
55889
56105
|
animationDuration: 1e3,
|
|
@@ -55927,13 +56143,9 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55927
56143
|
/* @__PURE__ */ jsx("span", { className: "w-2.5 h-2.5 rounded-full", style: { backgroundColor: "#e5e7eb" } }),
|
|
55928
56144
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-600", children: "Idle" })
|
|
55929
56145
|
] })
|
|
55930
|
-
] }) : chartData.
|
|
55931
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
55932
|
-
/* @__PURE__ */
|
|
55933
|
-
"Target: ",
|
|
55934
|
-
Math.round(chartData.lastSetTarget),
|
|
55935
|
-
" units/day"
|
|
55936
|
-
] })
|
|
56146
|
+
] }) : chartData.targetValues.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
56147
|
+
/* @__PURE__ */ jsx("div", { className: "relative h-5 w-3 rounded-full border border-[#E34329] bg-[#fff5f3] overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 bottom-0 h-1/2 bg-[#E34329]" }) }),
|
|
56148
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-600", children: chartData.targetLegend })
|
|
55937
56149
|
] }) })
|
|
55938
56150
|
] })
|
|
55939
56151
|
] })
|
|
@@ -67563,6 +67775,17 @@ var setSessionSeenValue = (key) => {
|
|
|
67563
67775
|
};
|
|
67564
67776
|
var buildAllGreenCelebrationSeenKey = (identity) => `${ALL_GREEN_CELEBRATION_SEEN_PREFIX}${identity}`;
|
|
67565
67777
|
var buildAllGreenMilestoneSeenKey = (identity, milestoneSeconds) => `${ALL_GREEN_MILESTONE_SEEN_PREFIX}${identity}:${milestoneSeconds}`;
|
|
67778
|
+
var LINE_SELECTOR_INDICATOR_VERSION = "incident_exclamation_v1";
|
|
67779
|
+
var LineSelectorIncidentIcon = ({ lineId }) => /* @__PURE__ */ jsx(
|
|
67780
|
+
"span",
|
|
67781
|
+
{
|
|
67782
|
+
"data-testid": `line-selector-incident-icon-${lineId}`,
|
|
67783
|
+
"aria-label": "Line needs attention",
|
|
67784
|
+
role: "img",
|
|
67785
|
+
className: "inline-flex h-5 w-5 flex-shrink-0 items-center justify-center rounded-full border border-rose-200 bg-white text-[13px] font-semibold leading-none text-rose-600 shadow-[0_1px_2px_rgba(15,23,42,0.06)]",
|
|
67786
|
+
children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "-mt-px", children: "!" })
|
|
67787
|
+
}
|
|
67788
|
+
);
|
|
67566
67789
|
var LoadingPageCmp = LoadingPage_default;
|
|
67567
67790
|
var LoadingOverlayCmp = LoadingOverlay_default;
|
|
67568
67791
|
function HomeView({
|
|
@@ -67902,25 +68125,49 @@ function HomeView({
|
|
|
67902
68125
|
const currentIsCurrentScopeResolved = isBootstrapMonitorMode ? bootstrapMonitor.isCurrentScopeResolved : legacyIsCurrentScopeResolved;
|
|
67903
68126
|
const currentMetricsError = isBootstrapMonitorMode ? bootstrapMonitor.error : legacyMetricsError;
|
|
67904
68127
|
const currentRefetchMetrics = isBootstrapMonitorMode ? bootstrapMonitor.refetch : refetchLegacyMetrics;
|
|
67905
|
-
const
|
|
67906
|
-
const
|
|
68128
|
+
const lineSelectorIndicatorByLine = useMemo(() => {
|
|
68129
|
+
const indicatorByLine = /* @__PURE__ */ new Map();
|
|
67907
68130
|
const legend = currentEfficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
67908
68131
|
const addRows = (rows) => {
|
|
67909
68132
|
(rows || []).forEach((row) => {
|
|
67910
68133
|
const lineId = typeof row?.line_id === "string" ? row.line_id : "";
|
|
67911
|
-
if (!lineId
|
|
68134
|
+
if (!lineId) {
|
|
68135
|
+
return;
|
|
68136
|
+
}
|
|
68137
|
+
if (row?.red_flow_incident?.active === true) {
|
|
68138
|
+
indicatorByLine.set(lineId, "incident");
|
|
68139
|
+
return;
|
|
68140
|
+
}
|
|
68141
|
+
if (indicatorByLine.get(lineId) === "incident") {
|
|
67912
68142
|
return;
|
|
67913
68143
|
}
|
|
67914
68144
|
const status = getKpiSignalStatus(row?.line_signal, legend);
|
|
67915
|
-
if (status) {
|
|
67916
|
-
|
|
68145
|
+
if (status === "attention") {
|
|
68146
|
+
indicatorByLine.set(lineId, "red");
|
|
67917
68147
|
}
|
|
67918
68148
|
});
|
|
67919
68149
|
};
|
|
67920
68150
|
addRows(currentSelectorLineMetrics);
|
|
67921
68151
|
addRows(currentLineMetrics);
|
|
67922
|
-
return
|
|
68152
|
+
return indicatorByLine;
|
|
67923
68153
|
}, [currentEfficiencyLegend, currentLineMetrics, currentSelectorLineMetrics]);
|
|
68154
|
+
const lineSelectorIndicatorStats = useMemo(() => {
|
|
68155
|
+
let incidentLineCount = 0;
|
|
68156
|
+
let redFlowLineCount = 0;
|
|
68157
|
+
visibleLineIds.forEach((lineId) => {
|
|
68158
|
+
const indicator = lineSelectorIndicatorByLine.get(lineId);
|
|
68159
|
+
if (indicator === "incident") {
|
|
68160
|
+
incidentLineCount += 1;
|
|
68161
|
+
} else if (indicator === "red") {
|
|
68162
|
+
redFlowLineCount += 1;
|
|
68163
|
+
}
|
|
68164
|
+
});
|
|
68165
|
+
return {
|
|
68166
|
+
incidentLineCount,
|
|
68167
|
+
redFlowLineCount,
|
|
68168
|
+
hasAnyIncident: incidentLineCount > 0
|
|
68169
|
+
};
|
|
68170
|
+
}, [lineSelectorIndicatorByLine, visibleLineIds]);
|
|
67924
68171
|
const metricsDisplayNames = useMemo(() => {
|
|
67925
68172
|
const nextDisplayNames = {};
|
|
67926
68173
|
currentWorkspaceMetrics.forEach((workspace) => {
|
|
@@ -68777,9 +69024,12 @@ function HomeView({
|
|
|
68777
69024
|
new_line_ids: normalizedLineIds,
|
|
68778
69025
|
selected_line_count: normalizedLineIds.length,
|
|
68779
69026
|
selection_mode: isAllLinesSelection(normalizedLineIds) ? "all" : normalizedLineIds.length === 1 ? "single" : "custom",
|
|
69027
|
+
incident_line_count: lineSelectorIndicatorStats.incidentLineCount,
|
|
69028
|
+
red_flow_line_count: lineSelectorIndicatorStats.redFlowLineCount,
|
|
69029
|
+
selector_indicator_version: LINE_SELECTOR_INDICATOR_VERSION,
|
|
68780
69030
|
line_name: getLineSelectionLabel(normalizedLineIds)
|
|
68781
69031
|
});
|
|
68782
|
-
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
|
|
69032
|
+
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, lineSelectorIndicatorStats, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
|
|
68783
69033
|
useCallback(() => {
|
|
68784
69034
|
updateSelectedLineIds(visibleLineIds);
|
|
68785
69035
|
}, [updateSelectedLineIds, visibleLineIds]);
|
|
@@ -68837,7 +69087,10 @@ function HomeView({
|
|
|
68837
69087
|
current_display_mode_label: getHomeDisplayModeLabel(displayMode),
|
|
68838
69088
|
selected_line_ids: selectedLineIds,
|
|
68839
69089
|
selected_line_count: selectedLineIds.length,
|
|
68840
|
-
is_all_lines: isAllLinesSelection(selectedLineIds)
|
|
69090
|
+
is_all_lines: isAllLinesSelection(selectedLineIds),
|
|
69091
|
+
incident_line_count: lineSelectorIndicatorStats.incidentLineCount,
|
|
69092
|
+
red_flow_line_count: lineSelectorIndicatorStats.redFlowLineCount,
|
|
69093
|
+
selector_indicator_version: LINE_SELECTOR_INDICATOR_VERSION
|
|
68841
69094
|
});
|
|
68842
69095
|
}
|
|
68843
69096
|
},
|
|
@@ -68878,8 +69131,8 @@ function HomeView({
|
|
|
68878
69131
|
] }),
|
|
68879
69132
|
/* @__PURE__ */ jsx("div", { className: "max-h-56 space-y-0.5 overflow-y-auto pr-1", children: visibleLineIds.map((lineId) => {
|
|
68880
69133
|
const isChecked = pendingSelectedLineIds.includes(lineId);
|
|
68881
|
-
const
|
|
68882
|
-
const
|
|
69134
|
+
const selectorIndicator = lineSelectorIndicatorByLine.get(lineId);
|
|
69135
|
+
const lineLabel = mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}`;
|
|
68883
69136
|
return /* @__PURE__ */ jsxs(
|
|
68884
69137
|
"label",
|
|
68885
69138
|
{
|
|
@@ -68889,6 +69142,7 @@ function HomeView({
|
|
|
68889
69142
|
"input",
|
|
68890
69143
|
{
|
|
68891
69144
|
type: "checkbox",
|
|
69145
|
+
"aria-label": lineLabel,
|
|
68892
69146
|
className: "h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500",
|
|
68893
69147
|
checked: isChecked,
|
|
68894
69148
|
onChange: () => {
|
|
@@ -68904,12 +69158,12 @@ function HomeView({
|
|
|
68904
69158
|
}
|
|
68905
69159
|
}
|
|
68906
69160
|
),
|
|
68907
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children:
|
|
68908
|
-
/* @__PURE__ */ jsx("span", { className: "flex h-
|
|
69161
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: lineLabel }),
|
|
69162
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-5 w-5 flex-shrink-0 items-center justify-center", children: selectorIndicator === "incident" ? /* @__PURE__ */ jsx(LineSelectorIncidentIcon, { lineId }) : selectorIndicator === "red" && !lineSelectorIndicatorStats.hasAnyIncident ? /* @__PURE__ */ jsx(
|
|
68909
69163
|
"span",
|
|
68910
69164
|
{
|
|
68911
69165
|
"data-testid": `line-selector-signal-dot-${lineId}`,
|
|
68912
|
-
className:
|
|
69166
|
+
className: "h-2 w-2 rounded-full bg-red-500",
|
|
68913
69167
|
"aria-hidden": "true"
|
|
68914
69168
|
}
|
|
68915
69169
|
) : null })
|
|
@@ -68941,7 +69195,8 @@ function HomeView({
|
|
|
68941
69195
|
mergedLineNames,
|
|
68942
69196
|
selectedLineIds,
|
|
68943
69197
|
pendingSelectedLineIds,
|
|
68944
|
-
|
|
69198
|
+
lineSelectorIndicatorByLine,
|
|
69199
|
+
lineSelectorIndicatorStats,
|
|
68945
69200
|
displayMode,
|
|
68946
69201
|
slideshowActiveLineId,
|
|
68947
69202
|
visibleLineIds,
|