@optifye/dashboard-core 6.11.3 → 6.11.4
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 +15 -3
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +172 -96
- package/dist/index.mjs +172 -96
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -1173,12 +1173,12 @@ body {
|
|
|
1173
1173
|
.max-h-\[300px\] {
|
|
1174
1174
|
max-height: 300px;
|
|
1175
1175
|
}
|
|
1176
|
-
.max-h-\[380px\] {
|
|
1177
|
-
max-height: 380px;
|
|
1178
|
-
}
|
|
1179
1176
|
.max-h-\[400px\] {
|
|
1180
1177
|
max-height: 400px;
|
|
1181
1178
|
}
|
|
1179
|
+
.max-h-\[500px\] {
|
|
1180
|
+
max-height: 500px;
|
|
1181
|
+
}
|
|
1182
1182
|
.max-h-\[60vh\] {
|
|
1183
1183
|
max-height: 60vh;
|
|
1184
1184
|
}
|
|
@@ -1188,6 +1188,9 @@ body {
|
|
|
1188
1188
|
.max-h-\[90vh\] {
|
|
1189
1189
|
max-height: 90vh;
|
|
1190
1190
|
}
|
|
1191
|
+
.max-h-\[calc\(100vh-80px\)\] {
|
|
1192
|
+
max-height: calc(100vh - 80px);
|
|
1193
|
+
}
|
|
1191
1194
|
.max-h-full {
|
|
1192
1195
|
max-height: 100%;
|
|
1193
1196
|
}
|
|
@@ -1443,6 +1446,9 @@ body {
|
|
|
1443
1446
|
.min-w-\[250px\] {
|
|
1444
1447
|
min-width: 250px;
|
|
1445
1448
|
}
|
|
1449
|
+
.min-w-\[280px\] {
|
|
1450
|
+
min-width: 280px;
|
|
1451
|
+
}
|
|
1446
1452
|
.min-w-\[32px\] {
|
|
1447
1453
|
min-width: 32px;
|
|
1448
1454
|
}
|
|
@@ -1494,6 +1500,9 @@ body {
|
|
|
1494
1500
|
.max-w-\[150px\] {
|
|
1495
1501
|
max-width: 150px;
|
|
1496
1502
|
}
|
|
1503
|
+
.max-w-\[170px\] {
|
|
1504
|
+
max-width: 170px;
|
|
1505
|
+
}
|
|
1497
1506
|
.max-w-\[1800px\] {
|
|
1498
1507
|
max-width: 1800px;
|
|
1499
1508
|
}
|
|
@@ -2957,6 +2966,9 @@ body {
|
|
|
2957
2966
|
.bg-slate-50\/50 {
|
|
2958
2967
|
background-color: rgb(248 250 252 / 0.5);
|
|
2959
2968
|
}
|
|
2969
|
+
.bg-slate-50\/80 {
|
|
2970
|
+
background-color: rgb(248 250 252 / 0.8);
|
|
2971
|
+
}
|
|
2960
2972
|
.bg-slate-900 {
|
|
2961
2973
|
--tw-bg-opacity: 1;
|
|
2962
2974
|
background-color: rgb(15 23 42 / var(--tw-bg-opacity, 1));
|
package/dist/index.d.mts
CHANGED
|
@@ -7057,6 +7057,7 @@ interface LineChartProps {
|
|
|
7057
7057
|
yAxisUnit?: string;
|
|
7058
7058
|
yAxisDomain?: [number | string, number | string];
|
|
7059
7059
|
tooltipFormatter?: (value: any, name: any, props: any) => any;
|
|
7060
|
+
tooltipLabelFormatter?: (label: any, payload: any[]) => any;
|
|
7060
7061
|
legendPayload?: any[];
|
|
7061
7062
|
className?: string;
|
|
7062
7063
|
showGrid?: boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -7057,6 +7057,7 @@ interface LineChartProps {
|
|
|
7057
7057
|
yAxisUnit?: string;
|
|
7058
7058
|
yAxisDomain?: [number | string, number | string];
|
|
7059
7059
|
tooltipFormatter?: (value: any, name: any, props: any) => any;
|
|
7060
|
+
tooltipLabelFormatter?: (label: any, payload: any[]) => any;
|
|
7060
7061
|
legendPayload?: any[];
|
|
7061
7062
|
className?: string;
|
|
7062
7063
|
showGrid?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -29797,6 +29797,7 @@ var LineChartComponent = ({
|
|
|
29797
29797
|
yAxisUnit,
|
|
29798
29798
|
yAxisDomain,
|
|
29799
29799
|
tooltipFormatter,
|
|
29800
|
+
tooltipLabelFormatter,
|
|
29800
29801
|
legendPayload,
|
|
29801
29802
|
className,
|
|
29802
29803
|
showGrid = true,
|
|
@@ -29876,7 +29877,15 @@ var LineChartComponent = ({
|
|
|
29876
29877
|
stroke: axisStrokeColor
|
|
29877
29878
|
}
|
|
29878
29879
|
),
|
|
29879
|
-
showTooltip && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29880
|
+
showTooltip && /* @__PURE__ */ jsxRuntime.jsx(
|
|
29881
|
+
recharts.Tooltip,
|
|
29882
|
+
{
|
|
29883
|
+
formatter: tooltipFormatter || defaultTooltipFormatter,
|
|
29884
|
+
labelFormatter: tooltipLabelFormatter,
|
|
29885
|
+
itemStyle: { color: "#111827" },
|
|
29886
|
+
cursor: { strokeDasharray: "3 3" }
|
|
29887
|
+
}
|
|
29888
|
+
),
|
|
29880
29889
|
showLegend && /* @__PURE__ */ jsxRuntime.jsx(recharts.Legend, { payload: legendPayload }),
|
|
29881
29890
|
lines.map((lineConfig, index) => {
|
|
29882
29891
|
const lineProps = {
|
|
@@ -29932,7 +29941,7 @@ var LineChart = React141__namespace.default.memo(LineChartComponent, (prevProps,
|
|
|
29932
29941
|
})) {
|
|
29933
29942
|
return false;
|
|
29934
29943
|
}
|
|
29935
|
-
if (prevProps.tooltipFormatter !== nextProps.tooltipFormatter || prevProps.xAxisTickFormatter !== nextProps.xAxisTickFormatter || JSON.stringify(prevProps.legendPayload) !== JSON.stringify(nextProps.legendPayload)) {
|
|
29944
|
+
if (prevProps.tooltipFormatter !== nextProps.tooltipFormatter || prevProps.xAxisTickFormatter !== nextProps.xAxisTickFormatter || prevProps.tooltipLabelFormatter !== nextProps.tooltipLabelFormatter || JSON.stringify(prevProps.legendPayload) !== JSON.stringify(nextProps.legendPayload)) {
|
|
29936
29945
|
return false;
|
|
29937
29946
|
}
|
|
29938
29947
|
return true;
|
|
@@ -42647,22 +42656,16 @@ var formatDuration = (seconds) => {
|
|
|
42647
42656
|
const hours = Math.floor(wholeSeconds % 86400 / 3600);
|
|
42648
42657
|
const minutes = Math.floor(wholeSeconds % 3600 / 60);
|
|
42649
42658
|
const remainingSeconds = wholeSeconds % 60;
|
|
42650
|
-
|
|
42651
|
-
|
|
42652
|
-
}
|
|
42653
|
-
if (
|
|
42654
|
-
|
|
42655
|
-
|
|
42656
|
-
|
|
42657
|
-
|
|
42658
|
-
}
|
|
42659
|
-
return `${remainingSeconds}s`;
|
|
42660
|
-
};
|
|
42661
|
-
var formatPercentage = (value) => {
|
|
42662
|
-
if (value === null || value === void 0 || !Number.isFinite(value)) {
|
|
42663
|
-
return "--";
|
|
42659
|
+
const parts = [];
|
|
42660
|
+
if (days > 0) parts.push(`${days}d`);
|
|
42661
|
+
if (hours > 0) parts.push(`${hours}h`);
|
|
42662
|
+
if (minutes > 0) parts.push(`${minutes}m`);
|
|
42663
|
+
if (days === 0 && hours === 0) {
|
|
42664
|
+
if (remainingSeconds > 0 || parts.length === 0) {
|
|
42665
|
+
parts.push(`${remainingSeconds}s`);
|
|
42666
|
+
}
|
|
42664
42667
|
}
|
|
42665
|
-
return
|
|
42668
|
+
return parts.join(" ");
|
|
42666
42669
|
};
|
|
42667
42670
|
var getColorForEntry = (name, index) => {
|
|
42668
42671
|
const normalized = name.trim().toLowerCase();
|
|
@@ -42682,30 +42685,35 @@ var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
|
|
|
42682
42685
|
if (active && payload && payload.length) {
|
|
42683
42686
|
const datum = payload[0]?.payload;
|
|
42684
42687
|
const contributors = datum?.contributors || [];
|
|
42685
|
-
|
|
42686
|
-
|
|
42687
|
-
|
|
42688
|
-
|
|
42689
|
-
|
|
42688
|
+
let effContributionStr = "--";
|
|
42689
|
+
if (datum?.efficiencyLossPercentage !== null && datum?.efficiencyLossPercentage !== void 0 && Number.isFinite(datum?.efficiencyLossPercentage)) {
|
|
42690
|
+
const val = datum.efficiencyLossPercentage;
|
|
42691
|
+
effContributionStr = val === 0 ? "0.0%" : `${Math.abs(val).toFixed(1)}%`;
|
|
42692
|
+
}
|
|
42693
|
+
const hasContributors = contributors.length > 0;
|
|
42694
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white p-3 border border-gray-100 shadow-lg rounded-lg text-xs z-50 min-w-[280px]", children: [
|
|
42695
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 pb-2 mb-2 border-b border-slate-100", children: [
|
|
42696
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2.5 h-2.5 rounded-full flex-shrink-0", style: { backgroundColor: payload[0].payload.fill || getColorForEntry(payload[0].name, 0) } }),
|
|
42697
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-slate-800 text-[13px]", children: payload[0].name.replace(/_/g, " ") })
|
|
42690
42698
|
] }),
|
|
42691
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
42692
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-
|
|
42699
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 pb-1", children: [
|
|
42700
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
42693
42701
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-500", children: "Share of idle time" }),
|
|
42694
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-
|
|
42702
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-slate-800", children: `${payload[0].value.toFixed(1)}%` })
|
|
42695
42703
|
] }),
|
|
42696
|
-
!hideTotalDuration && datum?.totalDurationSeconds !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-
|
|
42704
|
+
!hideTotalDuration && !hasContributors && datum?.totalDurationSeconds !== void 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
42697
42705
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-500", children: "Total Duration" }),
|
|
42698
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-
|
|
42706
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-slate-800", children: formatDuration(datum.totalDurationSeconds) })
|
|
42699
42707
|
] }) : null,
|
|
42700
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-
|
|
42708
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
42701
42709
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-500", children: "Efficiency Loss" }),
|
|
42702
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-
|
|
42710
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-slate-800", children: effContributionStr })
|
|
42703
42711
|
] })
|
|
42704
42712
|
] }),
|
|
42705
|
-
|
|
42706
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[
|
|
42707
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1", children: contributors.slice(0, 3).map((contributor) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-
|
|
42708
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-
|
|
42713
|
+
hasContributors ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 pt-2 border-t border-slate-100", children: [
|
|
42714
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[10px] font-bold uppercase tracking-wider text-slate-400 mb-2", children: "TOP CONTRIBUTORS" }),
|
|
42715
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1.5", children: contributors.slice(0, 3).map((contributor) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
42716
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-600 truncate max-w-[170px]", title: contributor.workspaceName, children: contributor.workspaceName }),
|
|
42709
42717
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-slate-500 text-right whitespace-nowrap", children: `${formatDuration(contributor.totalDurationSeconds)} \u2022 ${Number(contributor.percentageWithinReason || 0).toFixed(1)}%` })
|
|
42710
42718
|
] }, `${payload[0].name}-${contributor.workspaceId}`)) })
|
|
42711
42719
|
] }) : null
|
|
@@ -49386,10 +49394,11 @@ var AlertsPopup = ({
|
|
|
49386
49394
|
const updatePosition = React141.useCallback(() => {
|
|
49387
49395
|
const viewportHeight = window.innerHeight;
|
|
49388
49396
|
const viewportWidth = window.innerWidth;
|
|
49397
|
+
const currentPopupHeight = popupRef.current?.offsetHeight || 280;
|
|
49389
49398
|
if (viewportWidth < 768) {
|
|
49390
|
-
const mobileWidth = Math.max(240, Math.min(
|
|
49399
|
+
const mobileWidth = Math.max(240, Math.min(380, viewportWidth - 32));
|
|
49391
49400
|
setPosition({
|
|
49392
|
-
top: Math.max(16, (viewportHeight -
|
|
49401
|
+
top: Math.max(16, (viewportHeight - currentPopupHeight) / 2),
|
|
49393
49402
|
left: Math.max(16, (viewportWidth - mobileWidth) / 2),
|
|
49394
49403
|
width: mobileWidth
|
|
49395
49404
|
});
|
|
@@ -49397,22 +49406,25 @@ var AlertsPopup = ({
|
|
|
49397
49406
|
}
|
|
49398
49407
|
if (!triggerRef.current) return;
|
|
49399
49408
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
49400
|
-
const
|
|
49401
|
-
let top = rect.bottom - popupHeight + 40;
|
|
49402
|
-
if (top < 16) top = 16;
|
|
49403
|
-
if (top + popupHeight > viewportHeight - 16) {
|
|
49404
|
-
top = viewportHeight - popupHeight - 16;
|
|
49405
|
-
}
|
|
49409
|
+
const bottomOffset = viewportHeight - rect.bottom + 12;
|
|
49406
49410
|
setPosition({
|
|
49407
|
-
|
|
49411
|
+
bottom: bottomOffset,
|
|
49408
49412
|
left: 88,
|
|
49409
49413
|
// Sidebar width (80px) + gap (8px)
|
|
49410
|
-
width:
|
|
49414
|
+
width: 400
|
|
49415
|
+
// Make it a bit wider for enterprise/cleaner look
|
|
49411
49416
|
});
|
|
49412
49417
|
}, [triggerRef]);
|
|
49413
49418
|
React141.useEffect(() => {
|
|
49414
49419
|
if (isOpen) {
|
|
49415
|
-
|
|
49420
|
+
const timer = setTimeout(() => {
|
|
49421
|
+
updatePosition();
|
|
49422
|
+
}, 0);
|
|
49423
|
+
return () => clearTimeout(timer);
|
|
49424
|
+
}
|
|
49425
|
+
}, [isOpen, alerts, isLoading, error, updatePosition]);
|
|
49426
|
+
React141.useEffect(() => {
|
|
49427
|
+
if (isOpen) {
|
|
49416
49428
|
window.addEventListener("resize", updatePosition);
|
|
49417
49429
|
window.addEventListener("scroll", updatePosition);
|
|
49418
49430
|
}
|
|
@@ -49458,19 +49470,21 @@ var AlertsPopup = ({
|
|
|
49458
49470
|
},
|
|
49459
49471
|
style: {
|
|
49460
49472
|
position: "fixed",
|
|
49461
|
-
top: position.top,
|
|
49473
|
+
...position.top !== void 0 ? { top: position.top } : {},
|
|
49474
|
+
...position.bottom !== void 0 ? { bottom: position.bottom } : {},
|
|
49462
49475
|
left: position.left,
|
|
49463
49476
|
width: position.width,
|
|
49477
|
+
maxHeight: "calc(100vh - 32px)",
|
|
49464
49478
|
zIndex: 2147483647
|
|
49465
49479
|
},
|
|
49466
|
-
className: "bg-white rounded-[16px] shadow-
|
|
49480
|
+
className: "bg-white rounded-[16px] shadow-2xl border border-gray-100 max-w-[calc(100vw-32px)] max-h-[calc(100vh-80px)] overflow-hidden flex flex-col",
|
|
49467
49481
|
children: [
|
|
49468
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-50 bg-[#fafafa]", children: [
|
|
49482
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-50 bg-[#fafafa] shrink-0", children: [
|
|
49469
49483
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
49470
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14px] font-bold text-[#111827] uppercase tracking-wide", children: "
|
|
49484
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-[14px] font-bold text-[#111827] uppercase tracking-wide", children: "Current Alerts" }),
|
|
49471
49485
|
alertsCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "bg-[#eff6ff] text-[#2563eb] text-[11px] font-bold px-2 py-0.5 rounded-full", children: [
|
|
49472
49486
|
alertsCount,
|
|
49473
|
-
"
|
|
49487
|
+
" alerts"
|
|
49474
49488
|
] })
|
|
49475
49489
|
] }),
|
|
49476
49490
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -49482,13 +49496,13 @@ var AlertsPopup = ({
|
|
|
49482
49496
|
}
|
|
49483
49497
|
)
|
|
49484
49498
|
] }),
|
|
49485
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col
|
|
49486
|
-
isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "Loading
|
|
49499
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto max-h-[500px]", children: [
|
|
49500
|
+
isLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "Loading alerts..." }),
|
|
49487
49501
|
!isLoading && error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-10 text-sm text-red-600", children: error }),
|
|
49488
|
-
!isLoading && !error && alerts.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "No
|
|
49502
|
+
!isLoading && !error && alerts.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "No alerts right now." }),
|
|
49489
49503
|
!isLoading && !error && alerts.map((alert2, index) => {
|
|
49490
49504
|
const isCritical = typeof alert2.delta_efficiency === "number" && alert2.delta_efficiency <= -10;
|
|
49491
|
-
const description =
|
|
49505
|
+
const description = `Now: ${formatPercent(alert2.current_efficiency)}. Usual for this shift: ${formatPercent(alert2.baseline_efficiency)}.`;
|
|
49492
49506
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
49493
49507
|
motion.div,
|
|
49494
49508
|
{
|
|
@@ -49505,20 +49519,13 @@ var AlertsPopup = ({
|
|
|
49505
49519
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
|
|
49506
49520
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-start mb-1.5", children: [
|
|
49507
49521
|
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-sm font-semibold text-[#111827]", children: alert2.line_name }),
|
|
49508
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49509
|
-
|
|
49510
|
-
|
|
49511
|
-
|
|
49512
|
-
" regression"
|
|
49522
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[12px] text-[#94a3b8] font-medium whitespace-nowrap ml-3", children: [
|
|
49523
|
+
"Checked ",
|
|
49524
|
+
formatRelativeTime2(alert2.evaluated_at)
|
|
49525
|
+
] })
|
|
49513
49526
|
] }),
|
|
49514
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[
|
|
49515
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49516
|
-
"Delta ",
|
|
49517
|
-
formatPercent(alert2.delta_efficiency),
|
|
49518
|
-
" across ",
|
|
49519
|
-
alert2.baseline_sample_size,
|
|
49520
|
-
" historical shifts"
|
|
49521
|
-
] })
|
|
49527
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[12px] font-medium text-[#475569] uppercase tracking-wide", children: alert2.monitoring_mode === "uptime" ? "Machine Utilization is low" : "Output is low" }),
|
|
49528
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[13.5px] text-[#64748b] leading-[1.45] mt-1", children: description })
|
|
49522
49529
|
] })
|
|
49523
49530
|
] })
|
|
49524
49531
|
},
|
|
@@ -49581,7 +49588,7 @@ var SideNavBar = React141.memo(({
|
|
|
49581
49588
|
const handleHomeClick = React141.useCallback(() => {
|
|
49582
49589
|
navigate("/", {
|
|
49583
49590
|
trackingEvent: {
|
|
49584
|
-
name: "
|
|
49591
|
+
name: "Operations Overview Page Clicked",
|
|
49585
49592
|
properties: {
|
|
49586
49593
|
source: "side_nav",
|
|
49587
49594
|
line_id: lineId,
|
|
@@ -49869,6 +49876,7 @@ var SideNavBar = React141.memo(({
|
|
|
49869
49876
|
}
|
|
49870
49877
|
}, [signOut]);
|
|
49871
49878
|
const handleLogoClick = React141.useCallback(() => {
|
|
49879
|
+
trackCoreEvent("Operations Overview Page Clicked", { source: "logo" });
|
|
49872
49880
|
navigate("/");
|
|
49873
49881
|
onMobileMenuClose?.();
|
|
49874
49882
|
}, [navigate, onMobileMenuClose]);
|
|
@@ -50021,9 +50029,11 @@ var SideNavBar = React141.memo(({
|
|
|
50021
50029
|
{
|
|
50022
50030
|
ref: alertsTriggerRef,
|
|
50023
50031
|
onClick: () => {
|
|
50024
|
-
|
|
50032
|
+
const willOpen = !isAlertsOpen;
|
|
50033
|
+
setIsAlertsOpen(willOpen);
|
|
50025
50034
|
setIsSettingsOpen(false);
|
|
50026
|
-
if (
|
|
50035
|
+
if (willOpen) {
|
|
50036
|
+
trackCoreEvent("Alerts Page Clicked", { source: "side_nav" });
|
|
50027
50037
|
void refreshAlertsSummary();
|
|
50028
50038
|
}
|
|
50029
50039
|
},
|
|
@@ -50181,6 +50191,7 @@ var SideNavBar = React141.memo(({
|
|
|
50181
50191
|
{
|
|
50182
50192
|
onClick: () => {
|
|
50183
50193
|
setIsAlertsOpen(true);
|
|
50194
|
+
trackCoreEvent("Alerts Page Clicked", { source: "side_nav_mobile" });
|
|
50184
50195
|
void refreshAlertsSummary();
|
|
50185
50196
|
onMobileMenuClose?.();
|
|
50186
50197
|
},
|
|
@@ -59990,6 +60001,7 @@ var KPIsOverviewView = ({
|
|
|
59990
60001
|
backLinkUrl,
|
|
59991
60002
|
lineIds
|
|
59992
60003
|
}) => {
|
|
60004
|
+
const router$1 = router.useRouter();
|
|
59993
60005
|
const [lines, setLines] = React141.useState([]);
|
|
59994
60006
|
const [leaderboardLines, setLeaderboardLines] = React141.useState([]);
|
|
59995
60007
|
const [leaderboardLinesLoading, setLeaderboardLinesLoading] = React141.useState(false);
|
|
@@ -60017,6 +60029,13 @@ var KPIsOverviewView = ({
|
|
|
60017
60029
|
const [monthlyError, setMonthlyError] = React141.useState(null);
|
|
60018
60030
|
const dailyRequestKeyRef = React141.useRef(null);
|
|
60019
60031
|
const monthlyRequestKeyRef = React141.useRef(null);
|
|
60032
|
+
React141.useEffect(() => {
|
|
60033
|
+
if (!router$1.isReady) return;
|
|
60034
|
+
const tab = router$1.query.tab;
|
|
60035
|
+
if (tab === "leaderboard") {
|
|
60036
|
+
setActiveTab("leaderboard");
|
|
60037
|
+
}
|
|
60038
|
+
}, [router$1.isReady, router$1.query.tab]);
|
|
60020
60039
|
const supabase = useSupabase();
|
|
60021
60040
|
const { user } = useAuth();
|
|
60022
60041
|
const dashboardConfig = useDashboardConfig();
|
|
@@ -72285,13 +72304,7 @@ var formatIdleDuration = (seconds) => {
|
|
|
72285
72304
|
if (seconds === null || seconds === void 0 || !Number.isFinite(seconds)) {
|
|
72286
72305
|
return "--";
|
|
72287
72306
|
}
|
|
72288
|
-
|
|
72289
|
-
const minutes = Math.floor(wholeSeconds / 60);
|
|
72290
|
-
const remainingSeconds = wholeSeconds % 60;
|
|
72291
|
-
if (minutes > 0) {
|
|
72292
|
-
return `${minutes}m ${remainingSeconds}s`;
|
|
72293
|
-
}
|
|
72294
|
-
return `${remainingSeconds}s`;
|
|
72307
|
+
return formatIdleTime(Math.max(0, Math.round(seconds)));
|
|
72295
72308
|
};
|
|
72296
72309
|
var formatSignedIdleDuration = (seconds) => {
|
|
72297
72310
|
const sign = seconds > 0 ? "+" : "-";
|
|
@@ -72418,6 +72431,7 @@ var PlantHeadView = () => {
|
|
|
72418
72431
|
const [trendFetchNonce, setTrendFetchNonce] = React141__namespace.default.useState(0);
|
|
72419
72432
|
const [trendViewOpenNonce] = React141__namespace.default.useState(() => Date.now());
|
|
72420
72433
|
const [idleReasonBreakdown, setIdleReasonBreakdown] = React141__namespace.default.useState([]);
|
|
72434
|
+
const [idleReasonScope, setIdleReasonScope] = React141__namespace.default.useState(null);
|
|
72421
72435
|
const [isIdleReasonBreakdownLoading, setIsIdleReasonBreakdownLoading] = React141__namespace.default.useState(false);
|
|
72422
72436
|
const [improvements, setImprovements] = React141__namespace.default.useState([]);
|
|
72423
72437
|
const [isImprovementsLoading, setIsImprovementsLoading] = React141__namespace.default.useState(false);
|
|
@@ -72425,6 +72439,35 @@ var PlantHeadView = () => {
|
|
|
72425
72439
|
const filterRef = React141__namespace.default.useRef(null);
|
|
72426
72440
|
const filterButtonRef = React141__namespace.default.useRef(null);
|
|
72427
72441
|
const mobileFilterButtonRef = React141__namespace.default.useRef(null);
|
|
72442
|
+
React141__namespace.default.useEffect(() => {
|
|
72443
|
+
trackCorePageView("Operations Overview");
|
|
72444
|
+
}, []);
|
|
72445
|
+
const handleDateRangeChange = React141__namespace.default.useCallback((range) => {
|
|
72446
|
+
trackCoreEvent("Operations Overview Date Range Changed", {
|
|
72447
|
+
start_date: range.startKey,
|
|
72448
|
+
end_date: range.endKey
|
|
72449
|
+
});
|
|
72450
|
+
setDateRange(range);
|
|
72451
|
+
}, []);
|
|
72452
|
+
const handleFilterToggle = React141__namespace.default.useCallback(() => {
|
|
72453
|
+
trackCoreEvent("Operations Overview Filter Toggled", {
|
|
72454
|
+
action: !isFilterOpen ? "open" : "close"
|
|
72455
|
+
});
|
|
72456
|
+
setIsFilterOpen(!isFilterOpen);
|
|
72457
|
+
}, [isFilterOpen]);
|
|
72458
|
+
const handleTrendModeChange = React141__namespace.default.useCallback((e) => {
|
|
72459
|
+
const newMode = e.target.value;
|
|
72460
|
+
trackCoreEvent("Operations Overview Shift Filter Changed", {
|
|
72461
|
+
shift_mode: newMode
|
|
72462
|
+
});
|
|
72463
|
+
setTrendMode(newMode);
|
|
72464
|
+
}, []);
|
|
72465
|
+
const handlePoorestLineModeChange = React141__namespace.default.useCallback((mode) => {
|
|
72466
|
+
trackCoreEvent("Operations Overview Poorest Line Mode Changed", {
|
|
72467
|
+
mode
|
|
72468
|
+
});
|
|
72469
|
+
setPoorestLineMode(mode);
|
|
72470
|
+
}, []);
|
|
72428
72471
|
React141__namespace.default.useEffect(() => {
|
|
72429
72472
|
function handleClickOutside(event) {
|
|
72430
72473
|
if (filterRef.current && !filterRef.current.contains(event.target) && filterButtonRef.current && !filterButtonRef.current.contains(event.target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(event.target)) {
|
|
@@ -72574,11 +72617,13 @@ var PlantHeadView = () => {
|
|
|
72574
72617
|
React141__namespace.default.useEffect(() => {
|
|
72575
72618
|
if (!supabase || !companyId) return void 0;
|
|
72576
72619
|
if (scopedLineIds.length === 0) {
|
|
72620
|
+
setIdleReasonScope(null);
|
|
72577
72621
|
setIdleReasonBreakdown([]);
|
|
72578
72622
|
setIsIdleReasonBreakdownLoading(false);
|
|
72579
72623
|
return void 0;
|
|
72580
72624
|
}
|
|
72581
72625
|
let cancelled = false;
|
|
72626
|
+
setIdleReasonScope(null);
|
|
72582
72627
|
setIdleReasonBreakdown([]);
|
|
72583
72628
|
setIsIdleReasonBreakdownLoading(true);
|
|
72584
72629
|
const fetchIdleReasonBreakdown = async () => {
|
|
@@ -72594,12 +72639,14 @@ var PlantHeadView = () => {
|
|
|
72594
72639
|
`/api/dashboard/operations-overview/idle-reason-breakdown?${params.toString()}`
|
|
72595
72640
|
);
|
|
72596
72641
|
if (!cancelled) {
|
|
72642
|
+
setIdleReasonScope(response.scope || null);
|
|
72597
72643
|
setIdleReasonBreakdown(response.idle_reason_breakdown || []);
|
|
72598
72644
|
}
|
|
72599
72645
|
};
|
|
72600
72646
|
fetchIdleReasonBreakdown().catch((error) => {
|
|
72601
72647
|
console.error("[PlantHeadView] Failed to fetch idle reason breakdown", error);
|
|
72602
72648
|
if (!cancelled) {
|
|
72649
|
+
setIdleReasonScope(null);
|
|
72603
72650
|
setIdleReasonBreakdown([]);
|
|
72604
72651
|
}
|
|
72605
72652
|
}).finally(() => {
|
|
@@ -72695,13 +72742,17 @@ var PlantHeadView = () => {
|
|
|
72695
72742
|
});
|
|
72696
72743
|
}, [comparisonLabel, overview.summary?.avg_idle_per_workstation?.delta_seconds]);
|
|
72697
72744
|
const trendData = React141__namespace.default.useMemo(() => {
|
|
72698
|
-
return (overview.trend?.points || []).map((point) =>
|
|
72699
|
-
|
|
72700
|
-
|
|
72701
|
-
|
|
72702
|
-
|
|
72703
|
-
|
|
72704
|
-
|
|
72745
|
+
return (overview.trend?.points || []).map((point) => {
|
|
72746
|
+
const pointDate = point.date ? parseDateKeyToDate(point.date) : null;
|
|
72747
|
+
return {
|
|
72748
|
+
name: pointDate ? dateFns.format(pointDate, "MMM d") : "",
|
|
72749
|
+
dayOfWeek: pointDate ? dateFns.format(pointDate, "EEEE") : "",
|
|
72750
|
+
efficiency: (() => {
|
|
72751
|
+
const value = toNumber3(point.avg_efficiency);
|
|
72752
|
+
return value === null ? void 0 : value;
|
|
72753
|
+
})()
|
|
72754
|
+
};
|
|
72755
|
+
});
|
|
72705
72756
|
}, [overview.trend?.points]);
|
|
72706
72757
|
const trendPlayKey = React141__namespace.default.useMemo(() => {
|
|
72707
72758
|
return `${trendViewOpenNonce}:${trendFetchNonce}`;
|
|
@@ -72720,6 +72771,10 @@ var PlantHeadView = () => {
|
|
|
72720
72771
|
}))
|
|
72721
72772
|
})).filter((item) => item.value > 0);
|
|
72722
72773
|
}, [idleReasonBreakdown]);
|
|
72774
|
+
const showIdleModuleNotEnabledState = React141__namespace.default.useMemo(() => {
|
|
72775
|
+
const enabledLineCount = idleReasonScope?.idle_time_vlm_enabled_line_count;
|
|
72776
|
+
return !isIdleReasonBreakdownLoading && scopedLineIds.length > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
|
|
72777
|
+
}, [idleReasonScope?.idle_time_vlm_enabled_line_count, isIdleReasonBreakdownLoading, scopedLineIds.length]);
|
|
72723
72778
|
const mergedPoorestLines = React141__namespace.default.useMemo(() => {
|
|
72724
72779
|
const rows = overview.poorest_lines?.[poorestLineMode] || [];
|
|
72725
72780
|
return rows.slice(0, 3).map((line) => {
|
|
@@ -72740,6 +72795,11 @@ var PlantHeadView = () => {
|
|
|
72740
72795
|
const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
|
|
72741
72796
|
availableLineModes?.has_uptime && !availableLineModes?.has_output ? "Uptime" : "Output";
|
|
72742
72797
|
const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
|
|
72798
|
+
const trendTooltipLabelFormatter = React141__namespace.default.useCallback((label, payload) => {
|
|
72799
|
+
const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
|
|
72800
|
+
if (!dayOfWeek || typeof label !== "string") return label;
|
|
72801
|
+
return `${label} (${dayOfWeek})`;
|
|
72802
|
+
}, []);
|
|
72743
72803
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-h-screen bg-slate-50 w-full font-sans", children: [
|
|
72744
72804
|
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3 relative", children: [
|
|
72745
72805
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
@@ -72766,7 +72826,7 @@ var PlantHeadView = () => {
|
|
|
72766
72826
|
year: parseDateKeyToDate(dateRange.startKey).getFullYear(),
|
|
72767
72827
|
timezone: appTimezone,
|
|
72768
72828
|
value: dateRange,
|
|
72769
|
-
onChange:
|
|
72829
|
+
onChange: handleDateRangeChange,
|
|
72770
72830
|
showLabel: false
|
|
72771
72831
|
}
|
|
72772
72832
|
),
|
|
@@ -72774,7 +72834,7 @@ var PlantHeadView = () => {
|
|
|
72774
72834
|
"button",
|
|
72775
72835
|
{
|
|
72776
72836
|
ref: mobileFilterButtonRef,
|
|
72777
|
-
onClick:
|
|
72837
|
+
onClick: handleFilterToggle,
|
|
72778
72838
|
className: `p-2 rounded-full transition-colors relative ${isFilterOpen || trendMode !== "all" ? "bg-blue-50" : "active:bg-gray-100"}`,
|
|
72779
72839
|
"aria-label": "Open filters",
|
|
72780
72840
|
children: [
|
|
@@ -72802,7 +72862,7 @@ var PlantHeadView = () => {
|
|
|
72802
72862
|
year: parseDateKeyToDate(dateRange.startKey).getFullYear(),
|
|
72803
72863
|
timezone: appTimezone,
|
|
72804
72864
|
value: dateRange,
|
|
72805
|
-
onChange:
|
|
72865
|
+
onChange: handleDateRangeChange,
|
|
72806
72866
|
showLabel: false
|
|
72807
72867
|
}
|
|
72808
72868
|
) }),
|
|
@@ -72810,7 +72870,7 @@ var PlantHeadView = () => {
|
|
|
72810
72870
|
"button",
|
|
72811
72871
|
{
|
|
72812
72872
|
ref: filterButtonRef,
|
|
72813
|
-
onClick:
|
|
72873
|
+
onClick: handleFilterToggle,
|
|
72814
72874
|
className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isFilterOpen || trendMode !== "all" ? "border-blue-500 bg-blue-50 text-blue-700 ring-1 ring-blue-500" : "border-slate-200 bg-white text-slate-700 hover:bg-slate-50"}`,
|
|
72815
72875
|
"aria-label": "Open filters",
|
|
72816
72876
|
children: [
|
|
@@ -72843,7 +72903,7 @@ var PlantHeadView = () => {
|
|
|
72843
72903
|
"select",
|
|
72844
72904
|
{
|
|
72845
72905
|
value: trendMode,
|
|
72846
|
-
onChange:
|
|
72906
|
+
onChange: handleTrendModeChange,
|
|
72847
72907
|
className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
|
|
72848
72908
|
style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
|
|
72849
72909
|
children: [
|
|
@@ -72905,7 +72965,7 @@ var PlantHeadView = () => {
|
|
|
72905
72965
|
"button",
|
|
72906
72966
|
{
|
|
72907
72967
|
type: "button",
|
|
72908
|
-
onClick: () =>
|
|
72968
|
+
onClick: () => handlePoorestLineModeChange("output"),
|
|
72909
72969
|
className: `px-3 py-1 text-[11px] font-bold rounded-md ${poorestLineMode === "output" ? "bg-white text-slate-800 shadow-sm" : "text-slate-500 hover:text-slate-800"}`,
|
|
72910
72970
|
children: "Output"
|
|
72911
72971
|
}
|
|
@@ -72914,7 +72974,7 @@ var PlantHeadView = () => {
|
|
|
72914
72974
|
"button",
|
|
72915
72975
|
{
|
|
72916
72976
|
type: "button",
|
|
72917
|
-
onClick: () =>
|
|
72977
|
+
onClick: () => handlePoorestLineModeChange("uptime"),
|
|
72918
72978
|
className: `px-3 py-1 text-[11px] font-bold rounded-md ${poorestLineMode === "uptime" ? "bg-white text-slate-800 shadow-sm" : "text-slate-500 hover:text-slate-800"}`,
|
|
72919
72979
|
children: "Uptime"
|
|
72920
72980
|
}
|
|
@@ -72925,7 +72985,10 @@ var PlantHeadView = () => {
|
|
|
72925
72985
|
"button",
|
|
72926
72986
|
{
|
|
72927
72987
|
type: "button",
|
|
72928
|
-
onClick: () =>
|
|
72988
|
+
onClick: () => {
|
|
72989
|
+
trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
|
|
72990
|
+
navigate("/kpis?tab=leaderboard");
|
|
72991
|
+
},
|
|
72929
72992
|
className: "text-[11px] font-bold text-slate-500 hover:text-slate-800 transition-colors",
|
|
72930
72993
|
children: "View All"
|
|
72931
72994
|
}
|
|
@@ -72941,7 +73004,10 @@ var PlantHeadView = () => {
|
|
|
72941
73004
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
72942
73005
|
"div",
|
|
72943
73006
|
{
|
|
72944
|
-
onClick: () =>
|
|
73007
|
+
onClick: () => {
|
|
73008
|
+
trackCoreEvent("Operations Overview Line Clicked", { line_id: line.id, line_name: line.name });
|
|
73009
|
+
navigate(`/kpis/${line.id}`);
|
|
73010
|
+
},
|
|
72945
73011
|
className: "block py-3 hover:bg-slate-50/50 transition-colors cursor-pointer group relative",
|
|
72946
73012
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
72947
73013
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
@@ -72981,7 +73047,10 @@ var PlantHeadView = () => {
|
|
|
72981
73047
|
className: "bg-white rounded-xl shadow-sm border border-slate-100 flex flex-col overflow-hidden text-left",
|
|
72982
73048
|
children: [
|
|
72983
73049
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-5 py-4 flex-none flex justify-between items-center border-b border-slate-50/50 relative", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Idle Time Breakdown" }) }),
|
|
72984
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 p-4 pt-2 relative", children: isIdleReasonBreakdownLoading ? /* @__PURE__ */ jsxRuntime.jsx(OverviewIdleBreakdownSkeleton, {}) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
73050
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 p-4 pt-2 relative", children: isIdleReasonBreakdownLoading ? /* @__PURE__ */ jsxRuntime.jsx(OverviewIdleBreakdownSkeleton, {}) : showIdleModuleNotEnabledState ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full flex items-center justify-center rounded-xl border border-dashed border-slate-200 bg-slate-50/80 px-6 text-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
73051
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-slate-700", children: "Module not enabled" }),
|
|
73052
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs text-slate-500", children: "Enable idle-time VLM on at least one line to view this breakdown." })
|
|
73053
|
+
] }) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
72985
73054
|
IdleTimeReasonChart,
|
|
72986
73055
|
{
|
|
72987
73056
|
data: idleBreakdown,
|
|
@@ -73010,7 +73079,8 @@ var PlantHeadView = () => {
|
|
|
73010
73079
|
yAxisDomain: [0, 100],
|
|
73011
73080
|
showLegend: false,
|
|
73012
73081
|
showGrid: true,
|
|
73013
|
-
fillContainer: true
|
|
73082
|
+
fillContainer: true,
|
|
73083
|
+
tooltipLabelFormatter: trendTooltipLabelFormatter
|
|
73014
73084
|
},
|
|
73015
73085
|
trendPlayKey
|
|
73016
73086
|
) }) })
|
|
@@ -73024,7 +73094,10 @@ var PlantHeadView = () => {
|
|
|
73024
73094
|
"button",
|
|
73025
73095
|
{
|
|
73026
73096
|
type: "button",
|
|
73027
|
-
onClick: () =>
|
|
73097
|
+
onClick: () => {
|
|
73098
|
+
trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
|
|
73099
|
+
navigate("/improvement-center");
|
|
73100
|
+
},
|
|
73028
73101
|
className: "text-[11px] font-bold text-slate-500 hover:text-slate-800 transition-colors",
|
|
73029
73102
|
children: "View All"
|
|
73030
73103
|
}
|
|
@@ -73033,7 +73106,10 @@ var PlantHeadView = () => {
|
|
|
73033
73106
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 p-0 flex flex-col px-5 py-2 justify-start overflow-auto", children: isImprovementsLoading ? /* @__PURE__ */ jsxRuntime.jsx(OverviewImprovementsSkeleton, {}) : improvements.length > 0 ? improvements.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
73034
73107
|
"div",
|
|
73035
73108
|
{
|
|
73036
|
-
onClick: () =>
|
|
73109
|
+
onClick: () => {
|
|
73110
|
+
trackCoreEvent("Operations Overview Improvement Clicked", { issue_id: item.id, title: item.title });
|
|
73111
|
+
navigate("/improvement-center");
|
|
73112
|
+
},
|
|
73037
73113
|
className: "flex items-center justify-between py-3 border-b border-slate-50 last:border-0 group cursor-pointer",
|
|
73038
73114
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0 pr-4", children: [
|
|
73039
73115
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: "w-4 h-4 text-slate-400 group-hover:text-indigo-500 transition-colors" }) }),
|
package/dist/index.mjs
CHANGED
|
@@ -29768,6 +29768,7 @@ var LineChartComponent = ({
|
|
|
29768
29768
|
yAxisUnit,
|
|
29769
29769
|
yAxisDomain,
|
|
29770
29770
|
tooltipFormatter,
|
|
29771
|
+
tooltipLabelFormatter,
|
|
29771
29772
|
legendPayload,
|
|
29772
29773
|
className,
|
|
29773
29774
|
showGrid = true,
|
|
@@ -29847,7 +29848,15 @@ var LineChartComponent = ({
|
|
|
29847
29848
|
stroke: axisStrokeColor
|
|
29848
29849
|
}
|
|
29849
29850
|
),
|
|
29850
|
-
showTooltip && /* @__PURE__ */ jsx(
|
|
29851
|
+
showTooltip && /* @__PURE__ */ jsx(
|
|
29852
|
+
Tooltip,
|
|
29853
|
+
{
|
|
29854
|
+
formatter: tooltipFormatter || defaultTooltipFormatter,
|
|
29855
|
+
labelFormatter: tooltipLabelFormatter,
|
|
29856
|
+
itemStyle: { color: "#111827" },
|
|
29857
|
+
cursor: { strokeDasharray: "3 3" }
|
|
29858
|
+
}
|
|
29859
|
+
),
|
|
29851
29860
|
showLegend && /* @__PURE__ */ jsx(Legend, { payload: legendPayload }),
|
|
29852
29861
|
lines.map((lineConfig, index) => {
|
|
29853
29862
|
const lineProps = {
|
|
@@ -29903,7 +29912,7 @@ var LineChart = React141__default.memo(LineChartComponent, (prevProps, nextProps
|
|
|
29903
29912
|
})) {
|
|
29904
29913
|
return false;
|
|
29905
29914
|
}
|
|
29906
|
-
if (prevProps.tooltipFormatter !== nextProps.tooltipFormatter || prevProps.xAxisTickFormatter !== nextProps.xAxisTickFormatter || JSON.stringify(prevProps.legendPayload) !== JSON.stringify(nextProps.legendPayload)) {
|
|
29915
|
+
if (prevProps.tooltipFormatter !== nextProps.tooltipFormatter || prevProps.xAxisTickFormatter !== nextProps.xAxisTickFormatter || prevProps.tooltipLabelFormatter !== nextProps.tooltipLabelFormatter || JSON.stringify(prevProps.legendPayload) !== JSON.stringify(nextProps.legendPayload)) {
|
|
29907
29916
|
return false;
|
|
29908
29917
|
}
|
|
29909
29918
|
return true;
|
|
@@ -42618,22 +42627,16 @@ var formatDuration = (seconds) => {
|
|
|
42618
42627
|
const hours = Math.floor(wholeSeconds % 86400 / 3600);
|
|
42619
42628
|
const minutes = Math.floor(wholeSeconds % 3600 / 60);
|
|
42620
42629
|
const remainingSeconds = wholeSeconds % 60;
|
|
42621
|
-
|
|
42622
|
-
|
|
42623
|
-
}
|
|
42624
|
-
if (
|
|
42625
|
-
|
|
42626
|
-
|
|
42627
|
-
|
|
42628
|
-
|
|
42629
|
-
}
|
|
42630
|
-
return `${remainingSeconds}s`;
|
|
42631
|
-
};
|
|
42632
|
-
var formatPercentage = (value) => {
|
|
42633
|
-
if (value === null || value === void 0 || !Number.isFinite(value)) {
|
|
42634
|
-
return "--";
|
|
42630
|
+
const parts = [];
|
|
42631
|
+
if (days > 0) parts.push(`${days}d`);
|
|
42632
|
+
if (hours > 0) parts.push(`${hours}h`);
|
|
42633
|
+
if (minutes > 0) parts.push(`${minutes}m`);
|
|
42634
|
+
if (days === 0 && hours === 0) {
|
|
42635
|
+
if (remainingSeconds > 0 || parts.length === 0) {
|
|
42636
|
+
parts.push(`${remainingSeconds}s`);
|
|
42637
|
+
}
|
|
42635
42638
|
}
|
|
42636
|
-
return
|
|
42639
|
+
return parts.join(" ");
|
|
42637
42640
|
};
|
|
42638
42641
|
var getColorForEntry = (name, index) => {
|
|
42639
42642
|
const normalized = name.trim().toLowerCase();
|
|
@@ -42653,30 +42656,35 @@ var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
|
|
|
42653
42656
|
if (active && payload && payload.length) {
|
|
42654
42657
|
const datum = payload[0]?.payload;
|
|
42655
42658
|
const contributors = datum?.contributors || [];
|
|
42656
|
-
|
|
42657
|
-
|
|
42658
|
-
|
|
42659
|
-
|
|
42660
|
-
|
|
42659
|
+
let effContributionStr = "--";
|
|
42660
|
+
if (datum?.efficiencyLossPercentage !== null && datum?.efficiencyLossPercentage !== void 0 && Number.isFinite(datum?.efficiencyLossPercentage)) {
|
|
42661
|
+
const val = datum.efficiencyLossPercentage;
|
|
42662
|
+
effContributionStr = val === 0 ? "0.0%" : `${Math.abs(val).toFixed(1)}%`;
|
|
42663
|
+
}
|
|
42664
|
+
const hasContributors = contributors.length > 0;
|
|
42665
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-white p-3 border border-gray-100 shadow-lg rounded-lg text-xs z-50 min-w-[280px]", children: [
|
|
42666
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pb-2 mb-2 border-b border-slate-100", children: [
|
|
42667
|
+
/* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 rounded-full flex-shrink-0", style: { backgroundColor: payload[0].payload.fill || getColorForEntry(payload[0].name, 0) } }),
|
|
42668
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-slate-800 text-[13px]", children: payload[0].name.replace(/_/g, " ") })
|
|
42661
42669
|
] }),
|
|
42662
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
42663
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-
|
|
42670
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5 pb-1", children: [
|
|
42671
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
42664
42672
|
/* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Share of idle time" }),
|
|
42665
|
-
/* @__PURE__ */ jsx("span", { className: "font-
|
|
42673
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-slate-800", children: `${payload[0].value.toFixed(1)}%` })
|
|
42666
42674
|
] }),
|
|
42667
|
-
!hideTotalDuration && datum?.totalDurationSeconds !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-
|
|
42675
|
+
!hideTotalDuration && !hasContributors && datum?.totalDurationSeconds !== void 0 ? /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
42668
42676
|
/* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Total Duration" }),
|
|
42669
|
-
/* @__PURE__ */ jsx("span", { className: "font-
|
|
42677
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-slate-800", children: formatDuration(datum.totalDurationSeconds) })
|
|
42670
42678
|
] }) : null,
|
|
42671
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-
|
|
42679
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
42672
42680
|
/* @__PURE__ */ jsx("span", { className: "text-slate-500", children: "Efficiency Loss" }),
|
|
42673
|
-
/* @__PURE__ */ jsx("span", { className: "font-
|
|
42681
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold text-slate-800", children: effContributionStr })
|
|
42674
42682
|
] })
|
|
42675
42683
|
] }),
|
|
42676
|
-
|
|
42677
|
-
/* @__PURE__ */ jsx("p", { className: "text-[
|
|
42678
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-1", children: contributors.slice(0, 3).map((contributor) => /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-
|
|
42679
|
-
/* @__PURE__ */ jsx("span", { className: "text-slate-
|
|
42684
|
+
hasContributors ? /* @__PURE__ */ jsxs("div", { className: "mt-2 pt-2 border-t border-slate-100", children: [
|
|
42685
|
+
/* @__PURE__ */ jsx("p", { className: "text-[10px] font-bold uppercase tracking-wider text-slate-400 mb-2", children: "TOP CONTRIBUTORS" }),
|
|
42686
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: contributors.slice(0, 3).map((contributor) => /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
42687
|
+
/* @__PURE__ */ jsx("span", { className: "text-slate-600 truncate max-w-[170px]", title: contributor.workspaceName, children: contributor.workspaceName }),
|
|
42680
42688
|
/* @__PURE__ */ jsx("span", { className: "text-slate-500 text-right whitespace-nowrap", children: `${formatDuration(contributor.totalDurationSeconds)} \u2022 ${Number(contributor.percentageWithinReason || 0).toFixed(1)}%` })
|
|
42681
42689
|
] }, `${payload[0].name}-${contributor.workspaceId}`)) })
|
|
42682
42690
|
] }) : null
|
|
@@ -49357,10 +49365,11 @@ var AlertsPopup = ({
|
|
|
49357
49365
|
const updatePosition = useCallback(() => {
|
|
49358
49366
|
const viewportHeight = window.innerHeight;
|
|
49359
49367
|
const viewportWidth = window.innerWidth;
|
|
49368
|
+
const currentPopupHeight = popupRef.current?.offsetHeight || 280;
|
|
49360
49369
|
if (viewportWidth < 768) {
|
|
49361
|
-
const mobileWidth = Math.max(240, Math.min(
|
|
49370
|
+
const mobileWidth = Math.max(240, Math.min(380, viewportWidth - 32));
|
|
49362
49371
|
setPosition({
|
|
49363
|
-
top: Math.max(16, (viewportHeight -
|
|
49372
|
+
top: Math.max(16, (viewportHeight - currentPopupHeight) / 2),
|
|
49364
49373
|
left: Math.max(16, (viewportWidth - mobileWidth) / 2),
|
|
49365
49374
|
width: mobileWidth
|
|
49366
49375
|
});
|
|
@@ -49368,22 +49377,25 @@ var AlertsPopup = ({
|
|
|
49368
49377
|
}
|
|
49369
49378
|
if (!triggerRef.current) return;
|
|
49370
49379
|
const rect = triggerRef.current.getBoundingClientRect();
|
|
49371
|
-
const
|
|
49372
|
-
let top = rect.bottom - popupHeight + 40;
|
|
49373
|
-
if (top < 16) top = 16;
|
|
49374
|
-
if (top + popupHeight > viewportHeight - 16) {
|
|
49375
|
-
top = viewportHeight - popupHeight - 16;
|
|
49376
|
-
}
|
|
49380
|
+
const bottomOffset = viewportHeight - rect.bottom + 12;
|
|
49377
49381
|
setPosition({
|
|
49378
|
-
|
|
49382
|
+
bottom: bottomOffset,
|
|
49379
49383
|
left: 88,
|
|
49380
49384
|
// Sidebar width (80px) + gap (8px)
|
|
49381
|
-
width:
|
|
49385
|
+
width: 400
|
|
49386
|
+
// Make it a bit wider for enterprise/cleaner look
|
|
49382
49387
|
});
|
|
49383
49388
|
}, [triggerRef]);
|
|
49384
49389
|
useEffect(() => {
|
|
49385
49390
|
if (isOpen) {
|
|
49386
|
-
|
|
49391
|
+
const timer = setTimeout(() => {
|
|
49392
|
+
updatePosition();
|
|
49393
|
+
}, 0);
|
|
49394
|
+
return () => clearTimeout(timer);
|
|
49395
|
+
}
|
|
49396
|
+
}, [isOpen, alerts, isLoading, error, updatePosition]);
|
|
49397
|
+
useEffect(() => {
|
|
49398
|
+
if (isOpen) {
|
|
49387
49399
|
window.addEventListener("resize", updatePosition);
|
|
49388
49400
|
window.addEventListener("scroll", updatePosition);
|
|
49389
49401
|
}
|
|
@@ -49429,19 +49441,21 @@ var AlertsPopup = ({
|
|
|
49429
49441
|
},
|
|
49430
49442
|
style: {
|
|
49431
49443
|
position: "fixed",
|
|
49432
|
-
top: position.top,
|
|
49444
|
+
...position.top !== void 0 ? { top: position.top } : {},
|
|
49445
|
+
...position.bottom !== void 0 ? { bottom: position.bottom } : {},
|
|
49433
49446
|
left: position.left,
|
|
49434
49447
|
width: position.width,
|
|
49448
|
+
maxHeight: "calc(100vh - 32px)",
|
|
49435
49449
|
zIndex: 2147483647
|
|
49436
49450
|
},
|
|
49437
|
-
className: "bg-white rounded-[16px] shadow-
|
|
49451
|
+
className: "bg-white rounded-[16px] shadow-2xl border border-gray-100 max-w-[calc(100vw-32px)] max-h-[calc(100vh-80px)] overflow-hidden flex flex-col",
|
|
49438
49452
|
children: [
|
|
49439
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-50 bg-[#fafafa]", children: [
|
|
49453
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-5 py-4 border-b border-gray-50 bg-[#fafafa] shrink-0", children: [
|
|
49440
49454
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
49441
|
-
/* @__PURE__ */ jsx("h3", { className: "text-[14px] font-bold text-[#111827] uppercase tracking-wide", children: "
|
|
49455
|
+
/* @__PURE__ */ jsx("h3", { className: "text-[14px] font-bold text-[#111827] uppercase tracking-wide", children: "Current Alerts" }),
|
|
49442
49456
|
alertsCount > 0 && /* @__PURE__ */ jsxs("span", { className: "bg-[#eff6ff] text-[#2563eb] text-[11px] font-bold px-2 py-0.5 rounded-full", children: [
|
|
49443
49457
|
alertsCount,
|
|
49444
|
-
"
|
|
49458
|
+
" alerts"
|
|
49445
49459
|
] })
|
|
49446
49460
|
] }),
|
|
49447
49461
|
/* @__PURE__ */ jsx(
|
|
@@ -49453,13 +49467,13 @@ var AlertsPopup = ({
|
|
|
49453
49467
|
}
|
|
49454
49468
|
)
|
|
49455
49469
|
] }),
|
|
49456
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col
|
|
49457
|
-
isLoading && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "Loading
|
|
49470
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col flex-1 min-h-0 overflow-y-auto max-h-[500px]", children: [
|
|
49471
|
+
isLoading && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "Loading alerts..." }),
|
|
49458
49472
|
!isLoading && error && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-red-600", children: error }),
|
|
49459
|
-
!isLoading && !error && alerts.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "No
|
|
49473
|
+
!isLoading && !error && alerts.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-5 py-10 text-sm text-gray-500", children: "No alerts right now." }),
|
|
49460
49474
|
!isLoading && !error && alerts.map((alert2, index) => {
|
|
49461
49475
|
const isCritical = typeof alert2.delta_efficiency === "number" && alert2.delta_efficiency <= -10;
|
|
49462
|
-
const description =
|
|
49476
|
+
const description = `Now: ${formatPercent(alert2.current_efficiency)}. Usual for this shift: ${formatPercent(alert2.baseline_efficiency)}.`;
|
|
49463
49477
|
return /* @__PURE__ */ jsx(
|
|
49464
49478
|
motion.div,
|
|
49465
49479
|
{
|
|
@@ -49476,20 +49490,13 @@ var AlertsPopup = ({
|
|
|
49476
49490
|
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
49477
49491
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-start mb-1.5", children: [
|
|
49478
49492
|
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-[#111827]", children: alert2.line_name }),
|
|
49479
|
-
/* @__PURE__ */
|
|
49480
|
-
|
|
49481
|
-
|
|
49482
|
-
|
|
49483
|
-
" regression"
|
|
49493
|
+
/* @__PURE__ */ jsxs("span", { className: "text-[12px] text-[#94a3b8] font-medium whitespace-nowrap ml-3", children: [
|
|
49494
|
+
"Checked ",
|
|
49495
|
+
formatRelativeTime2(alert2.evaluated_at)
|
|
49496
|
+
] })
|
|
49484
49497
|
] }),
|
|
49485
|
-
/* @__PURE__ */ jsx("p", { className: "text-[
|
|
49486
|
-
/* @__PURE__ */
|
|
49487
|
-
"Delta ",
|
|
49488
|
-
formatPercent(alert2.delta_efficiency),
|
|
49489
|
-
" across ",
|
|
49490
|
-
alert2.baseline_sample_size,
|
|
49491
|
-
" historical shifts"
|
|
49492
|
-
] })
|
|
49498
|
+
/* @__PURE__ */ jsx("p", { className: "text-[12px] font-medium text-[#475569] uppercase tracking-wide", children: alert2.monitoring_mode === "uptime" ? "Machine Utilization is low" : "Output is low" }),
|
|
49499
|
+
/* @__PURE__ */ jsx("p", { className: "text-[13.5px] text-[#64748b] leading-[1.45] mt-1", children: description })
|
|
49493
49500
|
] })
|
|
49494
49501
|
] })
|
|
49495
49502
|
},
|
|
@@ -49552,7 +49559,7 @@ var SideNavBar = memo$1(({
|
|
|
49552
49559
|
const handleHomeClick = useCallback(() => {
|
|
49553
49560
|
navigate("/", {
|
|
49554
49561
|
trackingEvent: {
|
|
49555
|
-
name: "
|
|
49562
|
+
name: "Operations Overview Page Clicked",
|
|
49556
49563
|
properties: {
|
|
49557
49564
|
source: "side_nav",
|
|
49558
49565
|
line_id: lineId,
|
|
@@ -49840,6 +49847,7 @@ var SideNavBar = memo$1(({
|
|
|
49840
49847
|
}
|
|
49841
49848
|
}, [signOut]);
|
|
49842
49849
|
const handleLogoClick = useCallback(() => {
|
|
49850
|
+
trackCoreEvent("Operations Overview Page Clicked", { source: "logo" });
|
|
49843
49851
|
navigate("/");
|
|
49844
49852
|
onMobileMenuClose?.();
|
|
49845
49853
|
}, [navigate, onMobileMenuClose]);
|
|
@@ -49992,9 +50000,11 @@ var SideNavBar = memo$1(({
|
|
|
49992
50000
|
{
|
|
49993
50001
|
ref: alertsTriggerRef,
|
|
49994
50002
|
onClick: () => {
|
|
49995
|
-
|
|
50003
|
+
const willOpen = !isAlertsOpen;
|
|
50004
|
+
setIsAlertsOpen(willOpen);
|
|
49996
50005
|
setIsSettingsOpen(false);
|
|
49997
|
-
if (
|
|
50006
|
+
if (willOpen) {
|
|
50007
|
+
trackCoreEvent("Alerts Page Clicked", { source: "side_nav" });
|
|
49998
50008
|
void refreshAlertsSummary();
|
|
49999
50009
|
}
|
|
50000
50010
|
},
|
|
@@ -50152,6 +50162,7 @@ var SideNavBar = memo$1(({
|
|
|
50152
50162
|
{
|
|
50153
50163
|
onClick: () => {
|
|
50154
50164
|
setIsAlertsOpen(true);
|
|
50165
|
+
trackCoreEvent("Alerts Page Clicked", { source: "side_nav_mobile" });
|
|
50155
50166
|
void refreshAlertsSummary();
|
|
50156
50167
|
onMobileMenuClose?.();
|
|
50157
50168
|
},
|
|
@@ -59961,6 +59972,7 @@ var KPIsOverviewView = ({
|
|
|
59961
59972
|
backLinkUrl,
|
|
59962
59973
|
lineIds
|
|
59963
59974
|
}) => {
|
|
59975
|
+
const router = useRouter();
|
|
59964
59976
|
const [lines, setLines] = useState([]);
|
|
59965
59977
|
const [leaderboardLines, setLeaderboardLines] = useState([]);
|
|
59966
59978
|
const [leaderboardLinesLoading, setLeaderboardLinesLoading] = useState(false);
|
|
@@ -59988,6 +60000,13 @@ var KPIsOverviewView = ({
|
|
|
59988
60000
|
const [monthlyError, setMonthlyError] = useState(null);
|
|
59989
60001
|
const dailyRequestKeyRef = useRef(null);
|
|
59990
60002
|
const monthlyRequestKeyRef = useRef(null);
|
|
60003
|
+
useEffect(() => {
|
|
60004
|
+
if (!router.isReady) return;
|
|
60005
|
+
const tab = router.query.tab;
|
|
60006
|
+
if (tab === "leaderboard") {
|
|
60007
|
+
setActiveTab("leaderboard");
|
|
60008
|
+
}
|
|
60009
|
+
}, [router.isReady, router.query.tab]);
|
|
59991
60010
|
const supabase = useSupabase();
|
|
59992
60011
|
const { user } = useAuth();
|
|
59993
60012
|
const dashboardConfig = useDashboardConfig();
|
|
@@ -72256,13 +72275,7 @@ var formatIdleDuration = (seconds) => {
|
|
|
72256
72275
|
if (seconds === null || seconds === void 0 || !Number.isFinite(seconds)) {
|
|
72257
72276
|
return "--";
|
|
72258
72277
|
}
|
|
72259
|
-
|
|
72260
|
-
const minutes = Math.floor(wholeSeconds / 60);
|
|
72261
|
-
const remainingSeconds = wholeSeconds % 60;
|
|
72262
|
-
if (minutes > 0) {
|
|
72263
|
-
return `${minutes}m ${remainingSeconds}s`;
|
|
72264
|
-
}
|
|
72265
|
-
return `${remainingSeconds}s`;
|
|
72278
|
+
return formatIdleTime(Math.max(0, Math.round(seconds)));
|
|
72266
72279
|
};
|
|
72267
72280
|
var formatSignedIdleDuration = (seconds) => {
|
|
72268
72281
|
const sign = seconds > 0 ? "+" : "-";
|
|
@@ -72389,6 +72402,7 @@ var PlantHeadView = () => {
|
|
|
72389
72402
|
const [trendFetchNonce, setTrendFetchNonce] = React141__default.useState(0);
|
|
72390
72403
|
const [trendViewOpenNonce] = React141__default.useState(() => Date.now());
|
|
72391
72404
|
const [idleReasonBreakdown, setIdleReasonBreakdown] = React141__default.useState([]);
|
|
72405
|
+
const [idleReasonScope, setIdleReasonScope] = React141__default.useState(null);
|
|
72392
72406
|
const [isIdleReasonBreakdownLoading, setIsIdleReasonBreakdownLoading] = React141__default.useState(false);
|
|
72393
72407
|
const [improvements, setImprovements] = React141__default.useState([]);
|
|
72394
72408
|
const [isImprovementsLoading, setIsImprovementsLoading] = React141__default.useState(false);
|
|
@@ -72396,6 +72410,35 @@ var PlantHeadView = () => {
|
|
|
72396
72410
|
const filterRef = React141__default.useRef(null);
|
|
72397
72411
|
const filterButtonRef = React141__default.useRef(null);
|
|
72398
72412
|
const mobileFilterButtonRef = React141__default.useRef(null);
|
|
72413
|
+
React141__default.useEffect(() => {
|
|
72414
|
+
trackCorePageView("Operations Overview");
|
|
72415
|
+
}, []);
|
|
72416
|
+
const handleDateRangeChange = React141__default.useCallback((range) => {
|
|
72417
|
+
trackCoreEvent("Operations Overview Date Range Changed", {
|
|
72418
|
+
start_date: range.startKey,
|
|
72419
|
+
end_date: range.endKey
|
|
72420
|
+
});
|
|
72421
|
+
setDateRange(range);
|
|
72422
|
+
}, []);
|
|
72423
|
+
const handleFilterToggle = React141__default.useCallback(() => {
|
|
72424
|
+
trackCoreEvent("Operations Overview Filter Toggled", {
|
|
72425
|
+
action: !isFilterOpen ? "open" : "close"
|
|
72426
|
+
});
|
|
72427
|
+
setIsFilterOpen(!isFilterOpen);
|
|
72428
|
+
}, [isFilterOpen]);
|
|
72429
|
+
const handleTrendModeChange = React141__default.useCallback((e) => {
|
|
72430
|
+
const newMode = e.target.value;
|
|
72431
|
+
trackCoreEvent("Operations Overview Shift Filter Changed", {
|
|
72432
|
+
shift_mode: newMode
|
|
72433
|
+
});
|
|
72434
|
+
setTrendMode(newMode);
|
|
72435
|
+
}, []);
|
|
72436
|
+
const handlePoorestLineModeChange = React141__default.useCallback((mode) => {
|
|
72437
|
+
trackCoreEvent("Operations Overview Poorest Line Mode Changed", {
|
|
72438
|
+
mode
|
|
72439
|
+
});
|
|
72440
|
+
setPoorestLineMode(mode);
|
|
72441
|
+
}, []);
|
|
72399
72442
|
React141__default.useEffect(() => {
|
|
72400
72443
|
function handleClickOutside(event) {
|
|
72401
72444
|
if (filterRef.current && !filterRef.current.contains(event.target) && filterButtonRef.current && !filterButtonRef.current.contains(event.target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(event.target)) {
|
|
@@ -72545,11 +72588,13 @@ var PlantHeadView = () => {
|
|
|
72545
72588
|
React141__default.useEffect(() => {
|
|
72546
72589
|
if (!supabase || !companyId) return void 0;
|
|
72547
72590
|
if (scopedLineIds.length === 0) {
|
|
72591
|
+
setIdleReasonScope(null);
|
|
72548
72592
|
setIdleReasonBreakdown([]);
|
|
72549
72593
|
setIsIdleReasonBreakdownLoading(false);
|
|
72550
72594
|
return void 0;
|
|
72551
72595
|
}
|
|
72552
72596
|
let cancelled = false;
|
|
72597
|
+
setIdleReasonScope(null);
|
|
72553
72598
|
setIdleReasonBreakdown([]);
|
|
72554
72599
|
setIsIdleReasonBreakdownLoading(true);
|
|
72555
72600
|
const fetchIdleReasonBreakdown = async () => {
|
|
@@ -72565,12 +72610,14 @@ var PlantHeadView = () => {
|
|
|
72565
72610
|
`/api/dashboard/operations-overview/idle-reason-breakdown?${params.toString()}`
|
|
72566
72611
|
);
|
|
72567
72612
|
if (!cancelled) {
|
|
72613
|
+
setIdleReasonScope(response.scope || null);
|
|
72568
72614
|
setIdleReasonBreakdown(response.idle_reason_breakdown || []);
|
|
72569
72615
|
}
|
|
72570
72616
|
};
|
|
72571
72617
|
fetchIdleReasonBreakdown().catch((error) => {
|
|
72572
72618
|
console.error("[PlantHeadView] Failed to fetch idle reason breakdown", error);
|
|
72573
72619
|
if (!cancelled) {
|
|
72620
|
+
setIdleReasonScope(null);
|
|
72574
72621
|
setIdleReasonBreakdown([]);
|
|
72575
72622
|
}
|
|
72576
72623
|
}).finally(() => {
|
|
@@ -72666,13 +72713,17 @@ var PlantHeadView = () => {
|
|
|
72666
72713
|
});
|
|
72667
72714
|
}, [comparisonLabel, overview.summary?.avg_idle_per_workstation?.delta_seconds]);
|
|
72668
72715
|
const trendData = React141__default.useMemo(() => {
|
|
72669
|
-
return (overview.trend?.points || []).map((point) =>
|
|
72670
|
-
|
|
72671
|
-
|
|
72672
|
-
|
|
72673
|
-
|
|
72674
|
-
|
|
72675
|
-
|
|
72716
|
+
return (overview.trend?.points || []).map((point) => {
|
|
72717
|
+
const pointDate = point.date ? parseDateKeyToDate(point.date) : null;
|
|
72718
|
+
return {
|
|
72719
|
+
name: pointDate ? format(pointDate, "MMM d") : "",
|
|
72720
|
+
dayOfWeek: pointDate ? format(pointDate, "EEEE") : "",
|
|
72721
|
+
efficiency: (() => {
|
|
72722
|
+
const value = toNumber3(point.avg_efficiency);
|
|
72723
|
+
return value === null ? void 0 : value;
|
|
72724
|
+
})()
|
|
72725
|
+
};
|
|
72726
|
+
});
|
|
72676
72727
|
}, [overview.trend?.points]);
|
|
72677
72728
|
const trendPlayKey = React141__default.useMemo(() => {
|
|
72678
72729
|
return `${trendViewOpenNonce}:${trendFetchNonce}`;
|
|
@@ -72691,6 +72742,10 @@ var PlantHeadView = () => {
|
|
|
72691
72742
|
}))
|
|
72692
72743
|
})).filter((item) => item.value > 0);
|
|
72693
72744
|
}, [idleReasonBreakdown]);
|
|
72745
|
+
const showIdleModuleNotEnabledState = React141__default.useMemo(() => {
|
|
72746
|
+
const enabledLineCount = idleReasonScope?.idle_time_vlm_enabled_line_count;
|
|
72747
|
+
return !isIdleReasonBreakdownLoading && scopedLineIds.length > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
|
|
72748
|
+
}, [idleReasonScope?.idle_time_vlm_enabled_line_count, isIdleReasonBreakdownLoading, scopedLineIds.length]);
|
|
72694
72749
|
const mergedPoorestLines = React141__default.useMemo(() => {
|
|
72695
72750
|
const rows = overview.poorest_lines?.[poorestLineMode] || [];
|
|
72696
72751
|
return rows.slice(0, 3).map((line) => {
|
|
@@ -72711,6 +72766,11 @@ var PlantHeadView = () => {
|
|
|
72711
72766
|
const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
|
|
72712
72767
|
availableLineModes?.has_uptime && !availableLineModes?.has_output ? "Uptime" : "Output";
|
|
72713
72768
|
const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
|
|
72769
|
+
const trendTooltipLabelFormatter = React141__default.useCallback((label, payload) => {
|
|
72770
|
+
const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
|
|
72771
|
+
if (!dayOfWeek || typeof label !== "string") return label;
|
|
72772
|
+
return `${label} (${dayOfWeek})`;
|
|
72773
|
+
}, []);
|
|
72714
72774
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col min-h-screen bg-slate-50 w-full font-sans", children: [
|
|
72715
72775
|
/* @__PURE__ */ jsx("header", { className: "sticky top-0 z-10 bg-white border-b flex-shrink-0 shadow-sm", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-4 md:px-6 py-2 sm:py-3 relative", children: [
|
|
72716
72776
|
/* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
@@ -72737,7 +72797,7 @@ var PlantHeadView = () => {
|
|
|
72737
72797
|
year: parseDateKeyToDate(dateRange.startKey).getFullYear(),
|
|
72738
72798
|
timezone: appTimezone,
|
|
72739
72799
|
value: dateRange,
|
|
72740
|
-
onChange:
|
|
72800
|
+
onChange: handleDateRangeChange,
|
|
72741
72801
|
showLabel: false
|
|
72742
72802
|
}
|
|
72743
72803
|
),
|
|
@@ -72745,7 +72805,7 @@ var PlantHeadView = () => {
|
|
|
72745
72805
|
"button",
|
|
72746
72806
|
{
|
|
72747
72807
|
ref: mobileFilterButtonRef,
|
|
72748
|
-
onClick:
|
|
72808
|
+
onClick: handleFilterToggle,
|
|
72749
72809
|
className: `p-2 rounded-full transition-colors relative ${isFilterOpen || trendMode !== "all" ? "bg-blue-50" : "active:bg-gray-100"}`,
|
|
72750
72810
|
"aria-label": "Open filters",
|
|
72751
72811
|
children: [
|
|
@@ -72773,7 +72833,7 @@ var PlantHeadView = () => {
|
|
|
72773
72833
|
year: parseDateKeyToDate(dateRange.startKey).getFullYear(),
|
|
72774
72834
|
timezone: appTimezone,
|
|
72775
72835
|
value: dateRange,
|
|
72776
|
-
onChange:
|
|
72836
|
+
onChange: handleDateRangeChange,
|
|
72777
72837
|
showLabel: false
|
|
72778
72838
|
}
|
|
72779
72839
|
) }),
|
|
@@ -72781,7 +72841,7 @@ var PlantHeadView = () => {
|
|
|
72781
72841
|
"button",
|
|
72782
72842
|
{
|
|
72783
72843
|
ref: filterButtonRef,
|
|
72784
|
-
onClick:
|
|
72844
|
+
onClick: handleFilterToggle,
|
|
72785
72845
|
className: `flex items-center gap-2 px-3 py-1.5 rounded-lg border text-sm font-medium transition-all shadow-sm ${isFilterOpen || trendMode !== "all" ? "border-blue-500 bg-blue-50 text-blue-700 ring-1 ring-blue-500" : "border-slate-200 bg-white text-slate-700 hover:bg-slate-50"}`,
|
|
72786
72846
|
"aria-label": "Open filters",
|
|
72787
72847
|
children: [
|
|
@@ -72814,7 +72874,7 @@ var PlantHeadView = () => {
|
|
|
72814
72874
|
"select",
|
|
72815
72875
|
{
|
|
72816
72876
|
value: trendMode,
|
|
72817
|
-
onChange:
|
|
72877
|
+
onChange: handleTrendModeChange,
|
|
72818
72878
|
className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
|
|
72819
72879
|
style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
|
|
72820
72880
|
children: [
|
|
@@ -72876,7 +72936,7 @@ var PlantHeadView = () => {
|
|
|
72876
72936
|
"button",
|
|
72877
72937
|
{
|
|
72878
72938
|
type: "button",
|
|
72879
|
-
onClick: () =>
|
|
72939
|
+
onClick: () => handlePoorestLineModeChange("output"),
|
|
72880
72940
|
className: `px-3 py-1 text-[11px] font-bold rounded-md ${poorestLineMode === "output" ? "bg-white text-slate-800 shadow-sm" : "text-slate-500 hover:text-slate-800"}`,
|
|
72881
72941
|
children: "Output"
|
|
72882
72942
|
}
|
|
@@ -72885,7 +72945,7 @@ var PlantHeadView = () => {
|
|
|
72885
72945
|
"button",
|
|
72886
72946
|
{
|
|
72887
72947
|
type: "button",
|
|
72888
|
-
onClick: () =>
|
|
72948
|
+
onClick: () => handlePoorestLineModeChange("uptime"),
|
|
72889
72949
|
className: `px-3 py-1 text-[11px] font-bold rounded-md ${poorestLineMode === "uptime" ? "bg-white text-slate-800 shadow-sm" : "text-slate-500 hover:text-slate-800"}`,
|
|
72890
72950
|
children: "Uptime"
|
|
72891
72951
|
}
|
|
@@ -72896,7 +72956,10 @@ var PlantHeadView = () => {
|
|
|
72896
72956
|
"button",
|
|
72897
72957
|
{
|
|
72898
72958
|
type: "button",
|
|
72899
|
-
onClick: () =>
|
|
72959
|
+
onClick: () => {
|
|
72960
|
+
trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
|
|
72961
|
+
navigate("/kpis?tab=leaderboard");
|
|
72962
|
+
},
|
|
72900
72963
|
className: "text-[11px] font-bold text-slate-500 hover:text-slate-800 transition-colors",
|
|
72901
72964
|
children: "View All"
|
|
72902
72965
|
}
|
|
@@ -72912,7 +72975,10 @@ var PlantHeadView = () => {
|
|
|
72912
72975
|
return /* @__PURE__ */ jsx(
|
|
72913
72976
|
"div",
|
|
72914
72977
|
{
|
|
72915
|
-
onClick: () =>
|
|
72978
|
+
onClick: () => {
|
|
72979
|
+
trackCoreEvent("Operations Overview Line Clicked", { line_id: line.id, line_name: line.name });
|
|
72980
|
+
navigate(`/kpis/${line.id}`);
|
|
72981
|
+
},
|
|
72916
72982
|
className: "block py-3 hover:bg-slate-50/50 transition-colors cursor-pointer group relative",
|
|
72917
72983
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-4", children: [
|
|
72918
72984
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 min-w-0", children: [
|
|
@@ -72952,7 +73018,10 @@ var PlantHeadView = () => {
|
|
|
72952
73018
|
className: "bg-white rounded-xl shadow-sm border border-slate-100 flex flex-col overflow-hidden text-left",
|
|
72953
73019
|
children: [
|
|
72954
73020
|
/* @__PURE__ */ jsx("div", { className: "px-5 py-4 flex-none flex justify-between items-center border-b border-slate-50/50 relative", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Idle Time Breakdown" }) }),
|
|
72955
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 p-4 pt-2 relative", children: isIdleReasonBreakdownLoading ? /* @__PURE__ */ jsx(OverviewIdleBreakdownSkeleton, {}) : /* @__PURE__ */ jsx(
|
|
73021
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 p-4 pt-2 relative", children: isIdleReasonBreakdownLoading ? /* @__PURE__ */ jsx(OverviewIdleBreakdownSkeleton, {}) : showIdleModuleNotEnabledState ? /* @__PURE__ */ jsx("div", { className: "h-full flex items-center justify-center rounded-xl border border-dashed border-slate-200 bg-slate-50/80 px-6 text-center", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
73022
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-slate-700", children: "Module not enabled" }),
|
|
73023
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-slate-500", children: "Enable idle-time VLM on at least one line to view this breakdown." })
|
|
73024
|
+
] }) }) : /* @__PURE__ */ jsx(
|
|
72956
73025
|
IdleTimeReasonChart,
|
|
72957
73026
|
{
|
|
72958
73027
|
data: idleBreakdown,
|
|
@@ -72981,7 +73050,8 @@ var PlantHeadView = () => {
|
|
|
72981
73050
|
yAxisDomain: [0, 100],
|
|
72982
73051
|
showLegend: false,
|
|
72983
73052
|
showGrid: true,
|
|
72984
|
-
fillContainer: true
|
|
73053
|
+
fillContainer: true,
|
|
73054
|
+
tooltipLabelFormatter: trendTooltipLabelFormatter
|
|
72985
73055
|
},
|
|
72986
73056
|
trendPlayKey
|
|
72987
73057
|
) }) })
|
|
@@ -72995,7 +73065,10 @@ var PlantHeadView = () => {
|
|
|
72995
73065
|
"button",
|
|
72996
73066
|
{
|
|
72997
73067
|
type: "button",
|
|
72998
|
-
onClick: () =>
|
|
73068
|
+
onClick: () => {
|
|
73069
|
+
trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
|
|
73070
|
+
navigate("/improvement-center");
|
|
73071
|
+
},
|
|
72999
73072
|
className: "text-[11px] font-bold text-slate-500 hover:text-slate-800 transition-colors",
|
|
73000
73073
|
children: "View All"
|
|
73001
73074
|
}
|
|
@@ -73004,7 +73077,10 @@ var PlantHeadView = () => {
|
|
|
73004
73077
|
/* @__PURE__ */ jsx("div", { className: "flex-1 p-0 flex flex-col px-5 py-2 justify-start overflow-auto", children: isImprovementsLoading ? /* @__PURE__ */ jsx(OverviewImprovementsSkeleton, {}) : improvements.length > 0 ? improvements.map((item) => /* @__PURE__ */ jsx(
|
|
73005
73078
|
"div",
|
|
73006
73079
|
{
|
|
73007
|
-
onClick: () =>
|
|
73080
|
+
onClick: () => {
|
|
73081
|
+
trackCoreEvent("Operations Overview Improvement Clicked", { issue_id: item.id, title: item.title });
|
|
73082
|
+
navigate("/improvement-center");
|
|
73083
|
+
},
|
|
73008
73084
|
className: "flex items-center justify-between py-3 border-b border-slate-50 last:border-0 group cursor-pointer",
|
|
73009
73085
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 flex-1 min-w-0 pr-4", children: [
|
|
73010
73086
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx(ArrowUpRight, { className: "w-4 h-4 text-slate-400 group-hover:text-indigo-500 transition-colors" }) }),
|