@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.js
CHANGED
|
@@ -13820,12 +13820,22 @@ var stripSeconds = (timeStr) => {
|
|
|
13820
13820
|
if (!timeStr) return timeStr;
|
|
13821
13821
|
return timeStr.substring(0, 5);
|
|
13822
13822
|
};
|
|
13823
|
+
var normalizeOffDays = (value) => {
|
|
13824
|
+
if (!value) return [];
|
|
13825
|
+
if (Array.isArray(value)) {
|
|
13826
|
+
return value.map((day) => String(day || "").trim().toLowerCase()).filter(Boolean);
|
|
13827
|
+
}
|
|
13828
|
+
if (Array.isArray(value.off_days)) return normalizeOffDays(value.off_days);
|
|
13829
|
+
if (Array.isArray(value.offDays)) return normalizeOffDays(value.offDays);
|
|
13830
|
+
return [];
|
|
13831
|
+
};
|
|
13823
13832
|
var buildShiftConfigFromOperatingHoursRows = (rows, fallback) => {
|
|
13824
13833
|
const mapped = (rows || []).map((row) => ({
|
|
13825
13834
|
shiftId: row.shift_id,
|
|
13826
13835
|
shiftName: row.shift_name || `Shift ${row.shift_id}`,
|
|
13827
13836
|
startTime: stripSeconds(row.start_time),
|
|
13828
13837
|
endTime: stripSeconds(row.end_time),
|
|
13838
|
+
offDays: normalizeOffDays(row.off_days),
|
|
13829
13839
|
breaks: (() => {
|
|
13830
13840
|
const raw = Array.isArray(row.breaks) ? row.breaks : Array.isArray(row.breaks?.breaks) ? row.breaks.breaks : [];
|
|
13831
13841
|
return raw.map((b) => ({
|
|
@@ -13885,7 +13895,7 @@ var fetchAndStoreShiftConfig = async (supabase, lineId, fallback) => {
|
|
|
13885
13895
|
if (existing) return existing;
|
|
13886
13896
|
const promise = (async () => {
|
|
13887
13897
|
try {
|
|
13888
|
-
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);
|
|
13898
|
+
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);
|
|
13889
13899
|
if (error) {
|
|
13890
13900
|
throw new Error(`Failed to fetch shift config: ${error.message}`);
|
|
13891
13901
|
}
|
|
@@ -14578,7 +14588,7 @@ var useMultiLineShiftConfigs = (lineIds, fallbackConfig) => {
|
|
|
14578
14588
|
setError(null);
|
|
14579
14589
|
}
|
|
14580
14590
|
console.log(`[useMultiLineShiftConfigs] Fetching shift configs for ${missingLineIds.length} lines`);
|
|
14581
|
-
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);
|
|
14591
|
+
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);
|
|
14582
14592
|
if (fetchError) {
|
|
14583
14593
|
console.error("[useMultiLineShiftConfigs] Error fetching shift configs:", fetchError);
|
|
14584
14594
|
throw new Error(`Failed to fetch shift configs: ${fetchError.message}`);
|
|
@@ -37808,7 +37818,12 @@ var HourlyOutputChartComponent = ({
|
|
|
37808
37818
|
}, [idleBarState.visible, idleBarState.key, idleBarState.shouldAnimate]);
|
|
37809
37819
|
const maxDataValue = Math.max(...data, 0);
|
|
37810
37820
|
const numericChartTargets = chartData.map((d) => d.target).filter((target) => target !== null && Number.isFinite(target));
|
|
37811
|
-
const
|
|
37821
|
+
const hasAuthoritativeNumericTargets = hasHourlyTargetOutputProp && numericChartTargets.length > 0;
|
|
37822
|
+
const maxTargetValue = Math.max(
|
|
37823
|
+
...numericChartTargets,
|
|
37824
|
+
hasAuthoritativeNumericTargets ? 0 : pphThreshold,
|
|
37825
|
+
0
|
|
37826
|
+
);
|
|
37812
37827
|
const maxYValue = Math.max(
|
|
37813
37828
|
Math.ceil(maxTargetValue * 1.5),
|
|
37814
37829
|
Math.ceil(maxDataValue * 1.15)
|
|
@@ -37963,14 +37978,9 @@ var HourlyOutputChartComponent = ({
|
|
|
37963
37978
|
return /* @__PURE__ */ jsxRuntime.jsx("g", { children: lines });
|
|
37964
37979
|
}, [hourlyTargetSegments, targetTimelineSegments, SHIFT_DURATION, pphThreshold, targetLineEndOffset, hasHourlyTargetOutputProp]);
|
|
37965
37980
|
const renderLegend = () => {
|
|
37966
|
-
const uniqueTargets = [...new Set(
|
|
37967
|
-
chartData.map((d) => d.target).filter((target) => target !== null && Number.isFinite(target)).map((target) => Math.round(target))
|
|
37968
|
-
)].sort((a, b) => a - b);
|
|
37969
|
-
const unitLabel = hasHourlyTargetOutputProp ? "units" : "units/hr";
|
|
37970
|
-
const targetText = uniqueTargets.length === 0 ? `Target` : uniqueTargets.length === 1 ? `Target: ${uniqueTargets[0]} ${unitLabel}` : `Target: ${uniqueTargets[0]} - ${uniqueTargets[uniqueTargets.length - 1]} ${unitLabel}`;
|
|
37971
37981
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center text-sm text-gray-600 bg-white py-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border border-gray-100 rounded-full px-3 py-1", children: [
|
|
37972
37982
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full border-t-2 border-[#E34329] border-dashed" }) }),
|
|
37973
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
37983
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Target" })
|
|
37974
37984
|
] }) });
|
|
37975
37985
|
};
|
|
37976
37986
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -52488,6 +52498,106 @@ var getOrdinal = (n) => {
|
|
|
52488
52498
|
const v = n % 100;
|
|
52489
52499
|
return n + (suffix[(v - 20) % 10] || suffix[v] || suffix[0]);
|
|
52490
52500
|
};
|
|
52501
|
+
var resolveDailyTargetOutput = (shiftData) => {
|
|
52502
|
+
if (!shiftData || shiftData.hasData === false) return 0;
|
|
52503
|
+
const target = Number(shiftData?.targetOutput || shiftData?.idealOutput || 0);
|
|
52504
|
+
return Number.isFinite(target) && target > 0 ? target : 0;
|
|
52505
|
+
};
|
|
52506
|
+
var getUniqueRoundedTargets = (data) => Array.from(new Set(
|
|
52507
|
+
data.map((entry) => Number(entry.targetOutput || 0)).filter((target) => Number.isFinite(target) && target > 0).map((target) => Math.round(target))
|
|
52508
|
+
)).sort((a, b) => a - b);
|
|
52509
|
+
var formatDailyTargetLegend = (targets) => {
|
|
52510
|
+
if (targets.length === 0) return "";
|
|
52511
|
+
if (targets.length === 1) return `Target: ${targets[0].toLocaleString()} units/day`;
|
|
52512
|
+
return `Target: ${targets[0].toLocaleString()} - ${targets[targets.length - 1].toLocaleString()} units/day`;
|
|
52513
|
+
};
|
|
52514
|
+
var WEEKDAY_NAMES = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
|
52515
|
+
var getShiftOffDays = (shiftConfig, selectedShiftId) => {
|
|
52516
|
+
const shift = shiftConfig?.shifts?.find((candidate) => candidate.shiftId === selectedShiftId);
|
|
52517
|
+
const raw = shift?.offDays || shift?.off_days || [];
|
|
52518
|
+
return Array.isArray(raw) ? raw.map((day) => String(day || "").trim().toLowerCase()).filter(Boolean) : [];
|
|
52519
|
+
};
|
|
52520
|
+
var isScheduledOffDay = (dateKey, shiftConfig, selectedShiftId) => {
|
|
52521
|
+
const offDays = getShiftOffDays(shiftConfig, selectedShiftId);
|
|
52522
|
+
if (offDays.length === 0) return false;
|
|
52523
|
+
const date = parseDateKeyToDate(dateKey);
|
|
52524
|
+
return offDays.includes(WEEKDAY_NAMES[date.getDay()]);
|
|
52525
|
+
};
|
|
52526
|
+
var renderDailyOutputCapsules = (props, data) => {
|
|
52527
|
+
const { offset, yAxisMap } = props;
|
|
52528
|
+
if (!offset || !yAxisMap || data.length === 0) return null;
|
|
52529
|
+
const { left, width } = offset;
|
|
52530
|
+
const yAxis = yAxisMap.default || yAxisMap[0];
|
|
52531
|
+
if (!Number.isFinite(left) || !Number.isFinite(width) || width <= 0 || !yAxis?.scale) {
|
|
52532
|
+
return null;
|
|
52533
|
+
}
|
|
52534
|
+
const slotWidth = width / data.length;
|
|
52535
|
+
const capsuleWidth = Math.max(10, Math.min(28, slotWidth * 0.44));
|
|
52536
|
+
const radius = capsuleWidth / 2;
|
|
52537
|
+
const baseY = yAxis.scale(0);
|
|
52538
|
+
const capsules = [];
|
|
52539
|
+
data.forEach((entry, index) => {
|
|
52540
|
+
const target = Number(entry.targetOutput || 0);
|
|
52541
|
+
const output = Number(entry.output || 0);
|
|
52542
|
+
if ((!Number.isFinite(target) || target <= 0) && (!Number.isFinite(output) || output <= 0)) return;
|
|
52543
|
+
const x = left + index * slotWidth + (slotWidth - capsuleWidth) / 2;
|
|
52544
|
+
const targetTop = target > 0 ? yAxis.scale(target) : yAxis.scale(output);
|
|
52545
|
+
const capsuleTop = Math.min(targetTop, baseY - 4);
|
|
52546
|
+
const capsuleHeight = Math.max(baseY - capsuleTop, 4);
|
|
52547
|
+
const fillValue = target > 0 ? Math.min(Math.max(output, 0), target) : Math.max(output, 0);
|
|
52548
|
+
const fillTop = fillValue > 0 ? Math.max(yAxis.scale(fillValue), capsuleTop) : baseY;
|
|
52549
|
+
const fillHeight = Math.max(baseY - fillTop, 0);
|
|
52550
|
+
const fillColor = target > 0 ? output >= target ? "#00AB45" : "#E34329" : entry.color || "#6b7280";
|
|
52551
|
+
const trackFill = output >= target ? "#f0fdf4" : "#fff5f3";
|
|
52552
|
+
const trackStroke = output >= target ? "#00AB45" : "#E34329";
|
|
52553
|
+
const clipId = `line-daily-output-capsule-${index}`;
|
|
52554
|
+
capsules.push(
|
|
52555
|
+
/* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
52556
|
+
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
52557
|
+
"rect",
|
|
52558
|
+
{
|
|
52559
|
+
x,
|
|
52560
|
+
y: capsuleTop,
|
|
52561
|
+
width: capsuleWidth,
|
|
52562
|
+
height: capsuleHeight,
|
|
52563
|
+
rx: radius,
|
|
52564
|
+
ry: radius
|
|
52565
|
+
}
|
|
52566
|
+
) }) }),
|
|
52567
|
+
target > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
52568
|
+
"rect",
|
|
52569
|
+
{
|
|
52570
|
+
"data-testid": "daily-target-capsule-track",
|
|
52571
|
+
x,
|
|
52572
|
+
y: capsuleTop,
|
|
52573
|
+
width: capsuleWidth,
|
|
52574
|
+
height: capsuleHeight,
|
|
52575
|
+
rx: radius,
|
|
52576
|
+
ry: radius,
|
|
52577
|
+
fill: trackFill,
|
|
52578
|
+
stroke: trackStroke,
|
|
52579
|
+
strokeWidth: 1.5
|
|
52580
|
+
}
|
|
52581
|
+
),
|
|
52582
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
52583
|
+
"rect",
|
|
52584
|
+
{
|
|
52585
|
+
"data-testid": "daily-output-capsule-fill",
|
|
52586
|
+
x,
|
|
52587
|
+
y: fillTop,
|
|
52588
|
+
width: capsuleWidth,
|
|
52589
|
+
height: fillHeight,
|
|
52590
|
+
rx: fillHeight >= capsuleHeight ? radius : 0,
|
|
52591
|
+
ry: fillHeight >= capsuleHeight ? radius : 0,
|
|
52592
|
+
fill: fillColor,
|
|
52593
|
+
clipPath: target > 0 ? `url(#${clipId})` : void 0
|
|
52594
|
+
}
|
|
52595
|
+
)
|
|
52596
|
+
] }, `daily-output-capsule-${index}`)
|
|
52597
|
+
);
|
|
52598
|
+
});
|
|
52599
|
+
return capsules.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("g", { children: capsules }) : null;
|
|
52600
|
+
};
|
|
52491
52601
|
var CustomTooltip2 = ({ active, payload, label, isUptimeMode }) => {
|
|
52492
52602
|
if (!active || !payload || payload.length === 0) return null;
|
|
52493
52603
|
if (isUptimeMode) {
|
|
@@ -52571,6 +52681,7 @@ var LineMonthlyHistory = ({
|
|
|
52571
52681
|
legend,
|
|
52572
52682
|
monitoringMode,
|
|
52573
52683
|
lineAssembly = false,
|
|
52684
|
+
shiftConfig,
|
|
52574
52685
|
underperformingWorkspaces = {},
|
|
52575
52686
|
lineId,
|
|
52576
52687
|
selectedShiftId = 0,
|
|
@@ -52588,6 +52699,13 @@ var LineMonthlyHistory = ({
|
|
|
52588
52699
|
const { isIdleTimeVlmEnabled } = useIdleTimeVlmConfig();
|
|
52589
52700
|
const idleTimeVlmEnabled = isIdleTimeVlmEnabled(lineId);
|
|
52590
52701
|
const isUptimeMode = monitoringMode === "uptime";
|
|
52702
|
+
const [isMobile, setIsMobile] = React125.useState(false);
|
|
52703
|
+
React125.useEffect(() => {
|
|
52704
|
+
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
52705
|
+
checkMobile();
|
|
52706
|
+
window.addEventListener("resize", checkMobile);
|
|
52707
|
+
return () => window.removeEventListener("resize", checkMobile);
|
|
52708
|
+
}, []);
|
|
52591
52709
|
const chartKey = React125.useMemo(() => `${lineId}-${month}-${year}-${selectedShiftId}-${rangeStart}-${rangeEnd}`, [lineId, month, year, selectedShiftId, rangeStart, rangeEnd]);
|
|
52592
52710
|
const monthBounds = React125.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
52593
52711
|
const normalizedRange = React125.useMemo(() => {
|
|
@@ -52749,29 +52867,21 @@ var LineMonthlyHistory = ({
|
|
|
52749
52867
|
});
|
|
52750
52868
|
}
|
|
52751
52869
|
const yAxisMax2 = maxHours > 0 ? 100 : 1;
|
|
52752
|
-
return { data: dailyData2, maxOutput: 0,
|
|
52870
|
+
return { data: dailyData2, maxOutput: 0, targetValues: [], yAxisMax: yAxisMax2, targetLegend: "" };
|
|
52753
52871
|
}
|
|
52754
52872
|
const dailyData = [];
|
|
52755
52873
|
let maxOutput = 0;
|
|
52756
|
-
let
|
|
52757
|
-
for (let i = rangeDateKeys.length - 1; i >= 0; i--) {
|
|
52758
|
-
const dayKey = rangeDateKeys[i];
|
|
52759
|
-
const dayData = analysisMonthlyDataByKey.get(dayKey);
|
|
52760
|
-
const shiftData = dayData ? getShiftData2(dayData, selectedShiftId) : null;
|
|
52761
|
-
const idealOutput = shiftData ? shiftData.idealOutput || 0 : 0;
|
|
52762
|
-
if (idealOutput > 0) {
|
|
52763
|
-
lastSetTarget = idealOutput;
|
|
52764
|
-
break;
|
|
52765
|
-
}
|
|
52766
|
-
}
|
|
52874
|
+
let maxTarget = 0;
|
|
52767
52875
|
for (const dayKey of rangeDateKeys) {
|
|
52768
52876
|
const day = Number(dayKey.slice(-2));
|
|
52769
52877
|
const dayData = analysisMonthlyDataByKey.get(dayKey);
|
|
52878
|
+
const isOffDay = isScheduledOffDay(dayKey, shiftConfig, selectedShiftId);
|
|
52770
52879
|
const shiftData = dayData ? getShiftData2(dayData, selectedShiftId) : null;
|
|
52771
|
-
const output = shiftData && hasRealData(shiftData) ? shiftData.output || 0 : 0;
|
|
52772
|
-
const
|
|
52880
|
+
const output = !isOffDay && shiftData && hasRealData(shiftData) ? shiftData.output || 0 : 0;
|
|
52881
|
+
const targetOutput = isOffDay ? 0 : resolveDailyTargetOutput(shiftData);
|
|
52773
52882
|
if (output > maxOutput) maxOutput = output;
|
|
52774
|
-
|
|
52883
|
+
if (targetOutput > maxTarget) maxTarget = targetOutput;
|
|
52884
|
+
const color2 = targetOutput > 0 && output >= targetOutput ? "#00AB45" : "#E34329";
|
|
52775
52885
|
dailyData.push({
|
|
52776
52886
|
hour: getOrdinal(day),
|
|
52777
52887
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -52779,17 +52889,25 @@ var LineMonthlyHistory = ({
|
|
|
52779
52889
|
output,
|
|
52780
52890
|
originalOutput: output,
|
|
52781
52891
|
// For label display
|
|
52782
|
-
idealOutput,
|
|
52892
|
+
idealOutput: targetOutput,
|
|
52893
|
+
targetOutput,
|
|
52783
52894
|
color: color2
|
|
52784
52895
|
});
|
|
52785
52896
|
}
|
|
52786
|
-
const calculatedMax = Math.max(maxOutput,
|
|
52897
|
+
const calculatedMax = Math.max(maxOutput, maxTarget);
|
|
52787
52898
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
52788
|
-
|
|
52789
|
-
|
|
52899
|
+
const targetValues = getUniqueRoundedTargets(dailyData);
|
|
52900
|
+
return {
|
|
52901
|
+
data: dailyData,
|
|
52902
|
+
maxOutput,
|
|
52903
|
+
targetValues,
|
|
52904
|
+
yAxisMax,
|
|
52905
|
+
targetLegend: formatDailyTargetLegend(targetValues)
|
|
52906
|
+
};
|
|
52907
|
+
}, [analysisMonthlyDataByKey, normalizedRange.endKey, normalizedRange.startKey, selectedShiftId, isUptimeMode, timezone, shiftConfig]);
|
|
52790
52908
|
const yAxisTicks = React125.useMemo(() => {
|
|
52791
52909
|
const max = chartData.yAxisMax;
|
|
52792
|
-
const
|
|
52910
|
+
const targets = chartData.targetValues || [];
|
|
52793
52911
|
if (!max || max <= 0) return void 0;
|
|
52794
52912
|
const desiredIntervals = 4;
|
|
52795
52913
|
const roughStep = max / desiredIntervals;
|
|
@@ -52803,11 +52921,18 @@ var LineMonthlyHistory = ({
|
|
|
52803
52921
|
for (let v = 0; v <= max; v += step) {
|
|
52804
52922
|
ticks.push(Math.round(v));
|
|
52805
52923
|
}
|
|
52806
|
-
|
|
52807
|
-
ticks.push(Math.round(target));
|
|
52808
|
-
}
|
|
52924
|
+
targets.forEach((target) => ticks.push(Math.round(target)));
|
|
52809
52925
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
52810
|
-
}, [chartData.yAxisMax, chartData.
|
|
52926
|
+
}, [chartData.yAxisMax, chartData.targetValues]);
|
|
52927
|
+
const visibleYAxisTicks = React125.useMemo(() => {
|
|
52928
|
+
if (!isMobile || isUptimeMode || !yAxisTicks || yAxisTicks.length <= 3) return yAxisTicks;
|
|
52929
|
+
const importantTicks = /* @__PURE__ */ new Set([
|
|
52930
|
+
0,
|
|
52931
|
+
Math.round(chartData.yAxisMax),
|
|
52932
|
+
...chartData.targetValues || []
|
|
52933
|
+
]);
|
|
52934
|
+
return yAxisTicks.filter((tick) => importantTicks.has(Math.round(tick))).sort((a, b) => a - b).slice(-3);
|
|
52935
|
+
}, [chartData.targetValues, chartData.yAxisMax, isMobile, isUptimeMode, yAxisTicks]);
|
|
52811
52936
|
const pieChartData = React125.useMemo(() => {
|
|
52812
52937
|
if (!isUptimeMode) return [];
|
|
52813
52938
|
const validShifts = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter(
|
|
@@ -53126,36 +53251,35 @@ var LineMonthlyHistory = ({
|
|
|
53126
53251
|
] }),
|
|
53127
53252
|
/* @__PURE__ */ jsxRuntime.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: [
|
|
53128
53253
|
/* @__PURE__ */ jsxRuntime.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" }),
|
|
53129
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[
|
|
53254
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[140px] sm:h-[180px] lg:h-[220px]", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
53130
53255
|
recharts.BarChart,
|
|
53131
53256
|
{
|
|
53132
53257
|
data: chartData.data,
|
|
53133
|
-
margin: { top: 20, right: 10, bottom: 40, left: 10 },
|
|
53258
|
+
margin: isMobile ? { top: 8, right: 4, bottom: 28, left: 0 } : { top: 20, right: 10, bottom: 40, left: 10 },
|
|
53134
53259
|
children: [
|
|
53135
53260
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#f3f4f6" }),
|
|
53136
53261
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
53137
53262
|
recharts.XAxis,
|
|
53138
53263
|
{
|
|
53139
53264
|
dataKey: "hour",
|
|
53140
|
-
tick: { fontSize: 10, fill: "#6b7280" },
|
|
53141
|
-
interval: 0,
|
|
53265
|
+
tick: { fontSize: isMobile ? 9 : 10, fill: "#6b7280" },
|
|
53266
|
+
interval: isMobile ? 3 : 0,
|
|
53142
53267
|
angle: -45,
|
|
53143
53268
|
textAnchor: "end",
|
|
53144
|
-
height: 60
|
|
53269
|
+
height: isMobile ? 42 : 60
|
|
53145
53270
|
}
|
|
53146
53271
|
),
|
|
53147
53272
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
53148
53273
|
recharts.YAxis,
|
|
53149
53274
|
{
|
|
53150
53275
|
domain: [0, chartData.yAxisMax],
|
|
53151
|
-
width: 40,
|
|
53152
|
-
ticks: isUptimeMode ? [0, 25, 50, 75, 100] :
|
|
53276
|
+
width: isMobile ? 34 : 40,
|
|
53277
|
+
ticks: isUptimeMode ? [0, 25, 50, 75, 100] : visibleYAxisTicks,
|
|
53153
53278
|
tickFormatter: isUptimeMode ? (value) => `${value}%` : void 0,
|
|
53154
53279
|
tick: isUptimeMode ? void 0 : (props) => {
|
|
53155
53280
|
const { x, y, payload } = props;
|
|
53156
53281
|
const value = Math.round(payload.value);
|
|
53157
|
-
const
|
|
53158
|
-
const isTarget = value === targetValue && targetValue > 0;
|
|
53282
|
+
const isTarget = (chartData.targetValues || []).includes(value);
|
|
53159
53283
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
53160
53284
|
"text",
|
|
53161
53285
|
{
|
|
@@ -53178,15 +53302,7 @@ var LineMonthlyHistory = ({
|
|
|
53178
53302
|
content: (props) => /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip2, { ...props, isUptimeMode })
|
|
53179
53303
|
}
|
|
53180
53304
|
),
|
|
53181
|
-
!isUptimeMode &&
|
|
53182
|
-
recharts.ReferenceLine,
|
|
53183
|
-
{
|
|
53184
|
-
y: chartData.lastSetTarget,
|
|
53185
|
-
stroke: "#E34329",
|
|
53186
|
-
strokeDasharray: "5 5",
|
|
53187
|
-
strokeWidth: 2
|
|
53188
|
-
}
|
|
53189
|
-
),
|
|
53305
|
+
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(recharts.Customized, { component: (props) => renderDailyOutputCapsules(props, chartData.data) }),
|
|
53190
53306
|
isUptimeMode ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
53191
53307
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
53192
53308
|
recharts.Bar,
|
|
@@ -53219,6 +53335,8 @@ var LineMonthlyHistory = ({
|
|
|
53219
53335
|
{
|
|
53220
53336
|
dataKey: "output",
|
|
53221
53337
|
radius: [4, 4, 0, 0],
|
|
53338
|
+
fill: "transparent",
|
|
53339
|
+
opacity: 0,
|
|
53222
53340
|
isAnimationActive: true,
|
|
53223
53341
|
animationBegin: 0,
|
|
53224
53342
|
animationDuration: 1e3,
|
|
@@ -53237,13 +53355,9 @@ var LineMonthlyHistory = ({
|
|
|
53237
53355
|
},
|
|
53238
53356
|
chartKey
|
|
53239
53357
|
) }) }),
|
|
53240
|
-
!isUptimeMode && chartData.
|
|
53241
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-
|
|
53242
|
-
/* @__PURE__ */ jsxRuntime.
|
|
53243
|
-
"Target: ",
|
|
53244
|
-
Math.round(chartData.lastSetTarget),
|
|
53245
|
-
" units/day"
|
|
53246
|
-
] })
|
|
53358
|
+
!isUptimeMode && chartData.targetValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center text-sm text-gray-600 bg-white py-1 pt-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 border border-gray-100 rounded-full px-3 py-1", children: [
|
|
53359
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-5 w-3 rounded-full border border-[#E34329] bg-[#fff5f3] overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-x-0 bottom-0 h-1/2 bg-[#E34329]" }) }),
|
|
53360
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: chartData.targetLegend })
|
|
53247
53361
|
] }) })
|
|
53248
53362
|
] })
|
|
53249
53363
|
] })
|
|
@@ -55166,6 +55280,106 @@ var formatCycleSeconds = (value) => {
|
|
|
55166
55280
|
if (!Number.isFinite(value)) return "0.0s";
|
|
55167
55281
|
return `${value.toFixed(1)}s`;
|
|
55168
55282
|
};
|
|
55283
|
+
var resolveDailyTargetOutput2 = (shiftData) => {
|
|
55284
|
+
if (!shiftData || shiftData.hasData === false) return 0;
|
|
55285
|
+
const target = Number(shiftData?.targetOutput || shiftData?.idealOutput || 0);
|
|
55286
|
+
return Number.isFinite(target) && target > 0 ? target : 0;
|
|
55287
|
+
};
|
|
55288
|
+
var getUniqueRoundedTargets2 = (data) => Array.from(new Set(
|
|
55289
|
+
data.map((entry) => Number(entry.targetOutput || 0)).filter((target) => Number.isFinite(target) && target > 0).map((target) => Math.round(target))
|
|
55290
|
+
)).sort((a, b) => a - b);
|
|
55291
|
+
var formatDailyTargetLegend2 = (targets) => {
|
|
55292
|
+
if (targets.length === 0) return "";
|
|
55293
|
+
if (targets.length === 1) return `Target: ${targets[0].toLocaleString()} units/day`;
|
|
55294
|
+
return `Target: ${targets[0].toLocaleString()} - ${targets[targets.length - 1].toLocaleString()} units/day`;
|
|
55295
|
+
};
|
|
55296
|
+
var WEEKDAY_NAMES2 = ["sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"];
|
|
55297
|
+
var getShiftOffDays2 = (shiftConfig, selectedShiftId) => {
|
|
55298
|
+
const shift = shiftConfig?.shifts?.find((candidate) => candidate.shiftId === selectedShiftId);
|
|
55299
|
+
const raw = shift?.offDays || shift?.off_days || [];
|
|
55300
|
+
return Array.isArray(raw) ? raw.map((day) => String(day || "").trim().toLowerCase()).filter(Boolean) : [];
|
|
55301
|
+
};
|
|
55302
|
+
var isScheduledOffDay2 = (dateKey, shiftConfig, selectedShiftId) => {
|
|
55303
|
+
const offDays = getShiftOffDays2(shiftConfig, selectedShiftId);
|
|
55304
|
+
if (offDays.length === 0) return false;
|
|
55305
|
+
const date = parseDateKeyToDate(dateKey);
|
|
55306
|
+
return offDays.includes(WEEKDAY_NAMES2[date.getDay()]);
|
|
55307
|
+
};
|
|
55308
|
+
var renderDailyOutputCapsules2 = (props, data) => {
|
|
55309
|
+
const { offset, yAxisMap } = props;
|
|
55310
|
+
if (!offset || !yAxisMap || data.length === 0) return null;
|
|
55311
|
+
const { left, width } = offset;
|
|
55312
|
+
const yAxis = yAxisMap.default || yAxisMap[0];
|
|
55313
|
+
if (!Number.isFinite(left) || !Number.isFinite(width) || width <= 0 || !yAxis?.scale) {
|
|
55314
|
+
return null;
|
|
55315
|
+
}
|
|
55316
|
+
const slotWidth = width / data.length;
|
|
55317
|
+
const capsuleWidth = Math.max(10, Math.min(28, slotWidth * 0.44));
|
|
55318
|
+
const radius = capsuleWidth / 2;
|
|
55319
|
+
const baseY = yAxis.scale(0);
|
|
55320
|
+
const capsules = [];
|
|
55321
|
+
data.forEach((entry, index) => {
|
|
55322
|
+
const target = Number(entry.targetOutput || 0);
|
|
55323
|
+
const output = Number(entry.output || 0);
|
|
55324
|
+
if ((!Number.isFinite(target) || target <= 0) && (!Number.isFinite(output) || output <= 0)) return;
|
|
55325
|
+
const x = left + index * slotWidth + (slotWidth - capsuleWidth) / 2;
|
|
55326
|
+
const targetTop = target > 0 ? yAxis.scale(target) : yAxis.scale(output);
|
|
55327
|
+
const capsuleTop = Math.min(targetTop, baseY - 4);
|
|
55328
|
+
const capsuleHeight = Math.max(baseY - capsuleTop, 4);
|
|
55329
|
+
const fillValue = target > 0 ? Math.min(Math.max(output, 0), target) : Math.max(output, 0);
|
|
55330
|
+
const fillTop = fillValue > 0 ? Math.max(yAxis.scale(fillValue), capsuleTop) : baseY;
|
|
55331
|
+
const fillHeight = Math.max(baseY - fillTop, 0);
|
|
55332
|
+
const fillColor = target > 0 ? output >= target ? "#00AB45" : "#E34329" : entry.color || "#6b7280";
|
|
55333
|
+
const trackFill = output >= target ? "#f0fdf4" : "#fff5f3";
|
|
55334
|
+
const trackStroke = output >= target ? "#00AB45" : "#E34329";
|
|
55335
|
+
const clipId = `workspace-daily-output-capsule-${index}`;
|
|
55336
|
+
capsules.push(
|
|
55337
|
+
/* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
55338
|
+
/* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("clipPath", { id: clipId, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
55339
|
+
"rect",
|
|
55340
|
+
{
|
|
55341
|
+
x,
|
|
55342
|
+
y: capsuleTop,
|
|
55343
|
+
width: capsuleWidth,
|
|
55344
|
+
height: capsuleHeight,
|
|
55345
|
+
rx: radius,
|
|
55346
|
+
ry: radius
|
|
55347
|
+
}
|
|
55348
|
+
) }) }),
|
|
55349
|
+
target > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
55350
|
+
"rect",
|
|
55351
|
+
{
|
|
55352
|
+
"data-testid": "daily-target-capsule-track",
|
|
55353
|
+
x,
|
|
55354
|
+
y: capsuleTop,
|
|
55355
|
+
width: capsuleWidth,
|
|
55356
|
+
height: capsuleHeight,
|
|
55357
|
+
rx: radius,
|
|
55358
|
+
ry: radius,
|
|
55359
|
+
fill: trackFill,
|
|
55360
|
+
stroke: trackStroke,
|
|
55361
|
+
strokeWidth: 1.5
|
|
55362
|
+
}
|
|
55363
|
+
),
|
|
55364
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
55365
|
+
"rect",
|
|
55366
|
+
{
|
|
55367
|
+
"data-testid": "daily-output-capsule-fill",
|
|
55368
|
+
x,
|
|
55369
|
+
y: fillTop,
|
|
55370
|
+
width: capsuleWidth,
|
|
55371
|
+
height: fillHeight,
|
|
55372
|
+
rx: fillHeight >= capsuleHeight ? radius : 0,
|
|
55373
|
+
ry: fillHeight >= capsuleHeight ? radius : 0,
|
|
55374
|
+
fill: fillColor,
|
|
55375
|
+
clipPath: target > 0 ? `url(#${clipId})` : void 0
|
|
55376
|
+
}
|
|
55377
|
+
)
|
|
55378
|
+
] }, `daily-output-capsule-${index}`)
|
|
55379
|
+
);
|
|
55380
|
+
});
|
|
55381
|
+
return capsules.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("g", { children: capsules }) : null;
|
|
55382
|
+
};
|
|
55169
55383
|
var CustomTooltip3 = ({ active, payload, label, isUptimeMode }) => {
|
|
55170
55384
|
if (!active || !payload || payload.length === 0) return null;
|
|
55171
55385
|
if (isUptimeMode) {
|
|
@@ -55345,28 +55559,20 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55345
55559
|
});
|
|
55346
55560
|
}
|
|
55347
55561
|
const yAxisMax2 = maxHours > 0 ? maxHours * 1.1 : 1;
|
|
55348
|
-
return { data: dailyData, yAxisMax: yAxisMax2,
|
|
55562
|
+
return { data: dailyData, yAxisMax: yAxisMax2, targetValues: [], targetLegend: "" };
|
|
55349
55563
|
}
|
|
55350
55564
|
let maxOutput = 0;
|
|
55351
|
-
let
|
|
55352
|
-
for (let i = rangeDateKeys.length - 1; i >= 0; i--) {
|
|
55353
|
-
const dateKey = rangeDateKeys[i];
|
|
55354
|
-
const dayData = analysisMonthlyDataByKey.get(dateKey);
|
|
55355
|
-
const shiftData = dayData ? getShiftData(dayData, selectedShiftId) : null;
|
|
55356
|
-
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
55357
|
-
if (idealOutput > 0) {
|
|
55358
|
-
lastSetTarget = idealOutput;
|
|
55359
|
-
break;
|
|
55360
|
-
}
|
|
55361
|
-
}
|
|
55565
|
+
let maxTarget = 0;
|
|
55362
55566
|
for (const dateKey of rangeDateKeys) {
|
|
55363
55567
|
const dayData = analysisMonthlyDataByKey.get(dateKey);
|
|
55364
55568
|
const dayNumber = Number(dateKey.slice(-2));
|
|
55569
|
+
const isOffDay = isScheduledOffDay2(dateKey, shiftConfig, selectedShiftId);
|
|
55365
55570
|
const shiftData = dayData ? getShiftData(dayData, selectedShiftId) : null;
|
|
55366
|
-
const output = shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
55367
|
-
const
|
|
55571
|
+
const output = !isOffDay && shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
55572
|
+
const targetOutput = isOffDay ? 0 : resolveDailyTargetOutput2(shiftData);
|
|
55368
55573
|
if (output > maxOutput) maxOutput = output;
|
|
55369
|
-
|
|
55574
|
+
if (targetOutput > maxTarget) maxTarget = targetOutput;
|
|
55575
|
+
const color2 = targetOutput > 0 && output >= targetOutput ? "#00AB45" : "#E34329";
|
|
55370
55576
|
dailyData.push({
|
|
55371
55577
|
hour: getOrdinal2(dayNumber),
|
|
55372
55578
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -55374,21 +55580,29 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55374
55580
|
output,
|
|
55375
55581
|
originalOutput: output,
|
|
55376
55582
|
// For label display
|
|
55377
|
-
idealOutput,
|
|
55583
|
+
idealOutput: targetOutput,
|
|
55584
|
+
targetOutput,
|
|
55378
55585
|
efficiency: shiftData && hasRealData(shiftData) ? shiftData.efficiency : 0,
|
|
55379
55586
|
color: color2,
|
|
55380
55587
|
idleMinutes: 0
|
|
55381
55588
|
// Not used but keeps structure consistent
|
|
55382
55589
|
});
|
|
55383
55590
|
}
|
|
55384
|
-
const calculatedMax = Math.max(maxOutput,
|
|
55591
|
+
const calculatedMax = Math.max(maxOutput, maxTarget);
|
|
55385
55592
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
55386
|
-
|
|
55387
|
-
|
|
55593
|
+
const targetValues = getUniqueRoundedTargets2(dailyData);
|
|
55594
|
+
return {
|
|
55595
|
+
data: dailyData,
|
|
55596
|
+
maxOutput,
|
|
55597
|
+
targetValues,
|
|
55598
|
+
yAxisMax,
|
|
55599
|
+
targetLegend: formatDailyTargetLegend2(targetValues)
|
|
55600
|
+
};
|
|
55601
|
+
}, [analysisMonthlyDataByKey, rangeDateKeys, selectedShiftId, isUptimeMode, shiftConfig, shiftWorkSeconds]);
|
|
55388
55602
|
const yAxisTicks = React125.useMemo(() => {
|
|
55389
55603
|
if (isUptimeMode) return void 0;
|
|
55390
55604
|
const max = chartData.yAxisMax;
|
|
55391
|
-
const
|
|
55605
|
+
const targets = chartData.targetValues || [];
|
|
55392
55606
|
if (!max || max <= 0) return void 0;
|
|
55393
55607
|
const desiredIntervals = 4;
|
|
55394
55608
|
const roughStep = max / desiredIntervals;
|
|
@@ -55402,7 +55616,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55402
55616
|
for (let v = 0; v <= max; v += step) {
|
|
55403
55617
|
ticks.push(Math.round(v));
|
|
55404
55618
|
}
|
|
55405
|
-
|
|
55619
|
+
targets.forEach((target) => {
|
|
55406
55620
|
const roundedTarget = Math.round(target);
|
|
55407
55621
|
if (!ticks.includes(roundedTarget)) {
|
|
55408
55622
|
let nearestIndex = -1;
|
|
@@ -55421,9 +55635,18 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55421
55635
|
ticks.push(roundedTarget);
|
|
55422
55636
|
}
|
|
55423
55637
|
}
|
|
55424
|
-
}
|
|
55638
|
+
});
|
|
55425
55639
|
return ticks.filter((v) => v >= 0 && v <= max * 1.05).sort((a, b) => a - b);
|
|
55426
|
-
}, [chartData.yAxisMax, chartData.
|
|
55640
|
+
}, [chartData.yAxisMax, chartData.targetValues, isUptimeMode]);
|
|
55641
|
+
const visibleYAxisTicks = React125.useMemo(() => {
|
|
55642
|
+
if (!isMobile || isUptimeMode || !yAxisTicks || yAxisTicks.length <= 3) return yAxisTicks;
|
|
55643
|
+
const importantTicks = /* @__PURE__ */ new Set([
|
|
55644
|
+
0,
|
|
55645
|
+
Math.round(chartData.yAxisMax),
|
|
55646
|
+
...chartData.targetValues || []
|
|
55647
|
+
]);
|
|
55648
|
+
return yAxisTicks.filter((tick) => importantTicks.has(Math.round(tick))).sort((a, b) => a - b).slice(-3);
|
|
55649
|
+
}, [chartData.targetValues, chartData.yAxisMax, isMobile, isUptimeMode, yAxisTicks]);
|
|
55427
55650
|
const pieChartData = React125.useMemo(() => {
|
|
55428
55651
|
const aggregateMode = isUptimeMode ? "uptime" : "output";
|
|
55429
55652
|
const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(
|
|
@@ -55813,22 +56036,22 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55813
56036
|
] }),
|
|
55814
56037
|
(!isAssemblyWorkspace || isUptimeMode) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex-1", children: [
|
|
55815
56038
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: isUptimeMode ? "Daily Utilization" : "Daily Output" }),
|
|
55816
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "220px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
56039
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: isMobile ? "150px" : "220px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
55817
56040
|
recharts.BarChart,
|
|
55818
56041
|
{
|
|
55819
56042
|
data: chartData.data,
|
|
55820
|
-
margin: { top: 20, right: 10, bottom: 40, left: 10 },
|
|
56043
|
+
margin: isMobile ? { top: 8, right: 4, bottom: 28, left: 0 } : { top: 20, right: 10, bottom: 40, left: 10 },
|
|
55821
56044
|
children: [
|
|
55822
56045
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#f3f4f6" }),
|
|
55823
56046
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
55824
56047
|
recharts.XAxis,
|
|
55825
56048
|
{
|
|
55826
56049
|
dataKey: "hour",
|
|
55827
|
-
tick: { fontSize: 10, fill: "#6b7280" },
|
|
55828
|
-
interval: isMobile ?
|
|
56050
|
+
tick: { fontSize: isMobile ? 9 : 10, fill: "#6b7280" },
|
|
56051
|
+
interval: isMobile ? 3 : 0,
|
|
55829
56052
|
angle: -45,
|
|
55830
56053
|
textAnchor: "end",
|
|
55831
|
-
height: 60
|
|
56054
|
+
height: isMobile ? 42 : 60
|
|
55832
56055
|
}
|
|
55833
56056
|
),
|
|
55834
56057
|
isUptimeMode ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -55843,13 +56066,12 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55843
56066
|
recharts.YAxis,
|
|
55844
56067
|
{
|
|
55845
56068
|
domain: [0, chartData.yAxisMax],
|
|
55846
|
-
width: 40,
|
|
55847
|
-
ticks:
|
|
56069
|
+
width: isMobile ? 34 : 40,
|
|
56070
|
+
ticks: visibleYAxisTicks,
|
|
55848
56071
|
tick: (props) => {
|
|
55849
56072
|
const { x, y, payload } = props;
|
|
55850
56073
|
const value = Math.round(payload.value);
|
|
55851
|
-
const
|
|
55852
|
-
const isTarget = value === targetValue && targetValue > 0;
|
|
56074
|
+
const isTarget = (chartData.targetValues || []).includes(value);
|
|
55853
56075
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
55854
56076
|
"text",
|
|
55855
56077
|
{
|
|
@@ -55872,15 +56094,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55872
56094
|
content: (props) => /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip3, { ...props, isUptimeMode })
|
|
55873
56095
|
}
|
|
55874
56096
|
),
|
|
55875
|
-
!isUptimeMode &&
|
|
55876
|
-
recharts.ReferenceLine,
|
|
55877
|
-
{
|
|
55878
|
-
y: chartData.lastSetTarget,
|
|
55879
|
-
stroke: "#E34329",
|
|
55880
|
-
strokeDasharray: "5 5",
|
|
55881
|
-
strokeWidth: 2
|
|
55882
|
-
}
|
|
55883
|
-
),
|
|
56097
|
+
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(recharts.Customized, { component: (props) => renderDailyOutputCapsules2(props, chartData.data) }),
|
|
55884
56098
|
isUptimeMode ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
55885
56099
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
55886
56100
|
recharts.Bar,
|
|
@@ -55913,6 +56127,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55913
56127
|
{
|
|
55914
56128
|
dataKey: "output",
|
|
55915
56129
|
radius: [4, 4, 0, 0],
|
|
56130
|
+
fill: "transparent",
|
|
56131
|
+
opacity: 0,
|
|
55916
56132
|
isAnimationActive: true,
|
|
55917
56133
|
animationBegin: 0,
|
|
55918
56134
|
animationDuration: 1e3,
|
|
@@ -55956,13 +56172,9 @@ var WorkspaceMonthlyHistory = ({
|
|
|
55956
56172
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-2.5 h-2.5 rounded-full", style: { backgroundColor: "#e5e7eb" } }),
|
|
55957
56173
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600", children: "Idle" })
|
|
55958
56174
|
] })
|
|
55959
|
-
] }) : chartData.
|
|
55960
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
55961
|
-
/* @__PURE__ */ jsxRuntime.
|
|
55962
|
-
"Target: ",
|
|
55963
|
-
Math.round(chartData.lastSetTarget),
|
|
55964
|
-
" units/day"
|
|
55965
|
-
] })
|
|
56175
|
+
] }) : chartData.targetValues.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
56176
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-5 w-3 rounded-full border border-[#E34329] bg-[#fff5f3] overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-x-0 bottom-0 h-1/2 bg-[#E34329]" }) }),
|
|
56177
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-600", children: chartData.targetLegend })
|
|
55966
56178
|
] }) })
|
|
55967
56179
|
] })
|
|
55968
56180
|
] })
|
|
@@ -67592,6 +67804,17 @@ var setSessionSeenValue = (key) => {
|
|
|
67592
67804
|
};
|
|
67593
67805
|
var buildAllGreenCelebrationSeenKey = (identity) => `${ALL_GREEN_CELEBRATION_SEEN_PREFIX}${identity}`;
|
|
67594
67806
|
var buildAllGreenMilestoneSeenKey = (identity, milestoneSeconds) => `${ALL_GREEN_MILESTONE_SEEN_PREFIX}${identity}:${milestoneSeconds}`;
|
|
67807
|
+
var LINE_SELECTOR_INDICATOR_VERSION = "incident_exclamation_v1";
|
|
67808
|
+
var LineSelectorIncidentIcon = ({ lineId }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
67809
|
+
"span",
|
|
67810
|
+
{
|
|
67811
|
+
"data-testid": `line-selector-incident-icon-${lineId}`,
|
|
67812
|
+
"aria-label": "Line needs attention",
|
|
67813
|
+
role: "img",
|
|
67814
|
+
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)]",
|
|
67815
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": "true", className: "-mt-px", children: "!" })
|
|
67816
|
+
}
|
|
67817
|
+
);
|
|
67595
67818
|
var LoadingPageCmp = LoadingPage_default;
|
|
67596
67819
|
var LoadingOverlayCmp = LoadingOverlay_default;
|
|
67597
67820
|
function HomeView({
|
|
@@ -67931,25 +68154,49 @@ function HomeView({
|
|
|
67931
68154
|
const currentIsCurrentScopeResolved = isBootstrapMonitorMode ? bootstrapMonitor.isCurrentScopeResolved : legacyIsCurrentScopeResolved;
|
|
67932
68155
|
const currentMetricsError = isBootstrapMonitorMode ? bootstrapMonitor.error : legacyMetricsError;
|
|
67933
68156
|
const currentRefetchMetrics = isBootstrapMonitorMode ? bootstrapMonitor.refetch : refetchLegacyMetrics;
|
|
67934
|
-
const
|
|
67935
|
-
const
|
|
68157
|
+
const lineSelectorIndicatorByLine = React125.useMemo(() => {
|
|
68158
|
+
const indicatorByLine = /* @__PURE__ */ new Map();
|
|
67936
68159
|
const legend = currentEfficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
67937
68160
|
const addRows = (rows) => {
|
|
67938
68161
|
(rows || []).forEach((row) => {
|
|
67939
68162
|
const lineId = typeof row?.line_id === "string" ? row.line_id : "";
|
|
67940
|
-
if (!lineId
|
|
68163
|
+
if (!lineId) {
|
|
68164
|
+
return;
|
|
68165
|
+
}
|
|
68166
|
+
if (row?.red_flow_incident?.active === true) {
|
|
68167
|
+
indicatorByLine.set(lineId, "incident");
|
|
68168
|
+
return;
|
|
68169
|
+
}
|
|
68170
|
+
if (indicatorByLine.get(lineId) === "incident") {
|
|
67941
68171
|
return;
|
|
67942
68172
|
}
|
|
67943
68173
|
const status = getKpiSignalStatus(row?.line_signal, legend);
|
|
67944
|
-
if (status) {
|
|
67945
|
-
|
|
68174
|
+
if (status === "attention") {
|
|
68175
|
+
indicatorByLine.set(lineId, "red");
|
|
67946
68176
|
}
|
|
67947
68177
|
});
|
|
67948
68178
|
};
|
|
67949
68179
|
addRows(currentSelectorLineMetrics);
|
|
67950
68180
|
addRows(currentLineMetrics);
|
|
67951
|
-
return
|
|
68181
|
+
return indicatorByLine;
|
|
67952
68182
|
}, [currentEfficiencyLegend, currentLineMetrics, currentSelectorLineMetrics]);
|
|
68183
|
+
const lineSelectorIndicatorStats = React125.useMemo(() => {
|
|
68184
|
+
let incidentLineCount = 0;
|
|
68185
|
+
let redFlowLineCount = 0;
|
|
68186
|
+
visibleLineIds.forEach((lineId) => {
|
|
68187
|
+
const indicator = lineSelectorIndicatorByLine.get(lineId);
|
|
68188
|
+
if (indicator === "incident") {
|
|
68189
|
+
incidentLineCount += 1;
|
|
68190
|
+
} else if (indicator === "red") {
|
|
68191
|
+
redFlowLineCount += 1;
|
|
68192
|
+
}
|
|
68193
|
+
});
|
|
68194
|
+
return {
|
|
68195
|
+
incidentLineCount,
|
|
68196
|
+
redFlowLineCount,
|
|
68197
|
+
hasAnyIncident: incidentLineCount > 0
|
|
68198
|
+
};
|
|
68199
|
+
}, [lineSelectorIndicatorByLine, visibleLineIds]);
|
|
67953
68200
|
const metricsDisplayNames = React125.useMemo(() => {
|
|
67954
68201
|
const nextDisplayNames = {};
|
|
67955
68202
|
currentWorkspaceMetrics.forEach((workspace) => {
|
|
@@ -68806,9 +69053,12 @@ function HomeView({
|
|
|
68806
69053
|
new_line_ids: normalizedLineIds,
|
|
68807
69054
|
selected_line_count: normalizedLineIds.length,
|
|
68808
69055
|
selection_mode: isAllLinesSelection(normalizedLineIds) ? "all" : normalizedLineIds.length === 1 ? "single" : "custom",
|
|
69056
|
+
incident_line_count: lineSelectorIndicatorStats.incidentLineCount,
|
|
69057
|
+
red_flow_line_count: lineSelectorIndicatorStats.redFlowLineCount,
|
|
69058
|
+
selector_indicator_version: LINE_SELECTOR_INDICATOR_VERSION,
|
|
68809
69059
|
line_name: getLineSelectionLabel(normalizedLineIds)
|
|
68810
69060
|
});
|
|
68811
|
-
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
|
|
69061
|
+
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, lineSelectorIndicatorStats, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
|
|
68812
69062
|
React125.useCallback(() => {
|
|
68813
69063
|
updateSelectedLineIds(visibleLineIds);
|
|
68814
69064
|
}, [updateSelectedLineIds, visibleLineIds]);
|
|
@@ -68866,7 +69116,10 @@ function HomeView({
|
|
|
68866
69116
|
current_display_mode_label: getHomeDisplayModeLabel(displayMode),
|
|
68867
69117
|
selected_line_ids: selectedLineIds,
|
|
68868
69118
|
selected_line_count: selectedLineIds.length,
|
|
68869
|
-
is_all_lines: isAllLinesSelection(selectedLineIds)
|
|
69119
|
+
is_all_lines: isAllLinesSelection(selectedLineIds),
|
|
69120
|
+
incident_line_count: lineSelectorIndicatorStats.incidentLineCount,
|
|
69121
|
+
red_flow_line_count: lineSelectorIndicatorStats.redFlowLineCount,
|
|
69122
|
+
selector_indicator_version: LINE_SELECTOR_INDICATOR_VERSION
|
|
68870
69123
|
});
|
|
68871
69124
|
}
|
|
68872
69125
|
},
|
|
@@ -68907,8 +69160,8 @@ function HomeView({
|
|
|
68907
69160
|
] }),
|
|
68908
69161
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-56 space-y-0.5 overflow-y-auto pr-1", children: visibleLineIds.map((lineId) => {
|
|
68909
69162
|
const isChecked = pendingSelectedLineIds.includes(lineId);
|
|
68910
|
-
const
|
|
68911
|
-
const
|
|
69163
|
+
const selectorIndicator = lineSelectorIndicatorByLine.get(lineId);
|
|
69164
|
+
const lineLabel = mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}`;
|
|
68912
69165
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
68913
69166
|
"label",
|
|
68914
69167
|
{
|
|
@@ -68918,6 +69171,7 @@ function HomeView({
|
|
|
68918
69171
|
"input",
|
|
68919
69172
|
{
|
|
68920
69173
|
type: "checkbox",
|
|
69174
|
+
"aria-label": lineLabel,
|
|
68921
69175
|
className: "h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500",
|
|
68922
69176
|
checked: isChecked,
|
|
68923
69177
|
onChange: () => {
|
|
@@ -68933,12 +69187,12 @@ function HomeView({
|
|
|
68933
69187
|
}
|
|
68934
69188
|
}
|
|
68935
69189
|
),
|
|
68936
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children:
|
|
68937
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-
|
|
69190
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: lineLabel }),
|
|
69191
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex h-5 w-5 flex-shrink-0 items-center justify-center", children: selectorIndicator === "incident" ? /* @__PURE__ */ jsxRuntime.jsx(LineSelectorIncidentIcon, { lineId }) : selectorIndicator === "red" && !lineSelectorIndicatorStats.hasAnyIncident ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
68938
69192
|
"span",
|
|
68939
69193
|
{
|
|
68940
69194
|
"data-testid": `line-selector-signal-dot-${lineId}`,
|
|
68941
|
-
className:
|
|
69195
|
+
className: "h-2 w-2 rounded-full bg-red-500",
|
|
68942
69196
|
"aria-hidden": "true"
|
|
68943
69197
|
}
|
|
68944
69198
|
) : null })
|
|
@@ -68970,7 +69224,8 @@ function HomeView({
|
|
|
68970
69224
|
mergedLineNames,
|
|
68971
69225
|
selectedLineIds,
|
|
68972
69226
|
pendingSelectedLineIds,
|
|
68973
|
-
|
|
69227
|
+
lineSelectorIndicatorByLine,
|
|
69228
|
+
lineSelectorIndicatorStats,
|
|
68974
69229
|
displayMode,
|
|
68975
69230
|
slideshowActiveLineId,
|
|
68976
69231
|
visibleLineIds,
|