@optifye/dashboard-core 6.12.26 → 6.12.27
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/{automation-C3vudVDH.d.mts → automation-pIVo1XWk.d.mts} +23 -1
- package/dist/{automation-C3vudVDH.d.ts → automation-pIVo1XWk.d.ts} +23 -1
- package/dist/automation.d.mts +1 -1
- package/dist/automation.d.ts +1 -1
- package/dist/index.css +0 -15
- package/dist/index.d.mts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +256 -164
- package/dist/index.mjs +254 -166
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22075,14 +22075,87 @@ var toNumber = (value) => {
|
|
|
22075
22075
|
}
|
|
22076
22076
|
return 0;
|
|
22077
22077
|
};
|
|
22078
|
+
var toOptionalNumber = (value) => {
|
|
22079
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
22080
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
22081
|
+
const parsed = Number(value);
|
|
22082
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
22083
|
+
}
|
|
22084
|
+
return null;
|
|
22085
|
+
};
|
|
22078
22086
|
var EFFICIENCY_ON_TRACK_THRESHOLD = 100;
|
|
22079
22087
|
var isEfficiencyOnTrack = (efficiency) => toNumber(efficiency) >= EFFICIENCY_ON_TRACK_THRESHOLD;
|
|
22088
|
+
var KPI_SIGNAL_LABELS = {
|
|
22089
|
+
stable: "Stable",
|
|
22090
|
+
warning: "Warning",
|
|
22091
|
+
attention: "Attention"
|
|
22092
|
+
};
|
|
22093
|
+
var normalizeLineSignalSource = (source) => source === "recent_flow" ? "recent_flow" : "efficiency";
|
|
22094
|
+
var normalizeLineSignal = (lineSignal, fallbackEfficiency, fallbackWeight) => {
|
|
22095
|
+
if (lineSignal && typeof lineSignal === "object") {
|
|
22096
|
+
const raw = lineSignal;
|
|
22097
|
+
return {
|
|
22098
|
+
source: normalizeLineSignalSource(raw.source),
|
|
22099
|
+
percent: toOptionalNumber(raw.percent),
|
|
22100
|
+
weight: toOptionalNumber(raw.weight),
|
|
22101
|
+
mode: raw.mode === "unavailable" ? "unavailable" : "computed",
|
|
22102
|
+
reason: typeof raw.reason === "string" ? raw.reason : raw.reason ?? null,
|
|
22103
|
+
effectiveEndAt: raw.effective_end_at ?? raw.effectiveEndAt ?? null,
|
|
22104
|
+
computedAt: raw.computed_at ?? raw.computedAt ?? null
|
|
22105
|
+
};
|
|
22106
|
+
}
|
|
22107
|
+
const percent2 = toOptionalNumber(fallbackEfficiency);
|
|
22108
|
+
if (percent2 === null) return null;
|
|
22109
|
+
return {
|
|
22110
|
+
source: "efficiency",
|
|
22111
|
+
percent: percent2,
|
|
22112
|
+
weight: toOptionalNumber(fallbackWeight),
|
|
22113
|
+
mode: "computed",
|
|
22114
|
+
reason: "fallback_efficiency",
|
|
22115
|
+
effectiveEndAt: null,
|
|
22116
|
+
computedAt: null
|
|
22117
|
+
};
|
|
22118
|
+
};
|
|
22119
|
+
var getKpiSignalStatus = (signal, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
22120
|
+
const percent2 = toOptionalNumber(signal?.percent);
|
|
22121
|
+
if (percent2 === null) return null;
|
|
22122
|
+
const color2 = getEfficiencyColor(percent2, legend);
|
|
22123
|
+
if (color2 === "green") return "stable";
|
|
22124
|
+
if (color2 === "yellow") return "warning";
|
|
22125
|
+
return "attention";
|
|
22126
|
+
};
|
|
22127
|
+
var getKpiSignalLabel = (signal, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
22128
|
+
const status = getKpiSignalStatus(signal, legend);
|
|
22129
|
+
return status ? KPI_SIGNAL_LABELS[status] : null;
|
|
22130
|
+
};
|
|
22131
|
+
var aggregateLineSignals = (signals) => {
|
|
22132
|
+
const numericSignals = signals.filter(
|
|
22133
|
+
(signal) => signal !== null && signal !== void 0 && toOptionalNumber(signal.percent) !== null
|
|
22134
|
+
);
|
|
22135
|
+
if (numericSignals.length === 0) return null;
|
|
22136
|
+
const percent2 = numericSignals.reduce(
|
|
22137
|
+
(sum, signal) => sum + (toOptionalNumber(signal.percent) ?? 0),
|
|
22138
|
+
0
|
|
22139
|
+
) / numericSignals.length;
|
|
22140
|
+
const signalSources = new Set(numericSignals.map((signal) => signal.source));
|
|
22141
|
+
const source = signalSources.size === 1 ? numericSignals[0].source : "mixed";
|
|
22142
|
+
return {
|
|
22143
|
+
source,
|
|
22144
|
+
percent: percent2,
|
|
22145
|
+
weight: null,
|
|
22146
|
+
mode: "computed",
|
|
22147
|
+
reason: "average",
|
|
22148
|
+
effectiveEndAt: null,
|
|
22149
|
+
computedAt: null
|
|
22150
|
+
};
|
|
22151
|
+
};
|
|
22080
22152
|
var createDefaultKPIs = () => ({
|
|
22081
22153
|
underperformingWorkers: { current: 0, total: 0, change: 0 },
|
|
22082
22154
|
efficiency: { value: 0, change: 0 },
|
|
22083
22155
|
outputProgress: { current: 0, target: 0, idealOutput: 0, change: 0 },
|
|
22084
22156
|
avgCycleTime: { value: 0, change: 0 },
|
|
22085
|
-
qualityCompliance: { value: 95, change: 0 }
|
|
22157
|
+
qualityCompliance: { value: 95, change: 0 },
|
|
22158
|
+
lineSignal: null
|
|
22086
22159
|
});
|
|
22087
22160
|
var buildKPIsFromLineMetricsRow = (row) => {
|
|
22088
22161
|
if (!row) return createDefaultKPIs();
|
|
@@ -22116,15 +22189,28 @@ var buildKPIsFromLineMetricsRow = (row) => {
|
|
|
22116
22189
|
qualityCompliance: {
|
|
22117
22190
|
value: 95,
|
|
22118
22191
|
change: 0
|
|
22119
|
-
}
|
|
22192
|
+
},
|
|
22193
|
+
lineSignal: normalizeLineSignal(row.line_signal, avgEfficiency, idealOutput || lineThreshold)
|
|
22120
22194
|
};
|
|
22121
22195
|
};
|
|
22122
22196
|
var aggregateKPIsFromLineMetricsRows = (rows) => {
|
|
22123
22197
|
if (!rows || rows.length === 0) return createDefaultKPIs();
|
|
22198
|
+
const lineSignal = aggregateLineSignals(
|
|
22199
|
+
rows.map((row) => normalizeLineSignal(
|
|
22200
|
+
row?.line_signal,
|
|
22201
|
+
row?.avg_efficiency,
|
|
22202
|
+
row?.ideal_output ?? row?.line_threshold
|
|
22203
|
+
))
|
|
22204
|
+
);
|
|
22124
22205
|
const eligibleRows = rows.filter(
|
|
22125
22206
|
(row) => isValidAggregateEfficiency(row?.monitoring_mode ?? row?.monitoringMode, row?.avg_efficiency)
|
|
22126
22207
|
);
|
|
22127
|
-
if (eligibleRows.length === 0)
|
|
22208
|
+
if (eligibleRows.length === 0) {
|
|
22209
|
+
return {
|
|
22210
|
+
...createDefaultKPIs(),
|
|
22211
|
+
lineSignal
|
|
22212
|
+
};
|
|
22213
|
+
}
|
|
22128
22214
|
const currentOutputSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.current_output), 0);
|
|
22129
22215
|
const lineThresholdSum = eligibleRows.reduce(
|
|
22130
22216
|
(sum, row) => sum + (row?.output_target_recalculated !== void 0 && row?.output_target_recalculated !== null ? toNumber(row.output_target_recalculated) : toNumber(row.line_threshold)),
|
|
@@ -22171,7 +22257,8 @@ var aggregateKPIsFromLineMetricsRows = (rows) => {
|
|
|
22171
22257
|
qualityCompliance: {
|
|
22172
22258
|
value: 95,
|
|
22173
22259
|
change: 0
|
|
22174
|
-
}
|
|
22260
|
+
},
|
|
22261
|
+
lineSignal
|
|
22175
22262
|
};
|
|
22176
22263
|
};
|
|
22177
22264
|
|
|
@@ -34725,19 +34812,19 @@ var SkuRow = ({ sku, isSelected, isLive, onSelect }) => {
|
|
|
34725
34812
|
onClick: () => onSelect?.(isSelected ? null : sku.sku_id),
|
|
34726
34813
|
"data-testid": `sku-progress-row-${sku.sku_id}`,
|
|
34727
34814
|
children: [
|
|
34728
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
34729
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
34815
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
34816
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2 flex-1 min-w-0", children: [
|
|
34730
34817
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
34731
34818
|
"span",
|
|
34732
34819
|
{
|
|
34733
|
-
className: "text-sm font-semibold text-gray-800
|
|
34820
|
+
className: "text-xs sm:text-sm font-semibold text-gray-800 break-words line-clamp-2",
|
|
34734
34821
|
title: skuLabel,
|
|
34735
34822
|
children: skuLabel
|
|
34736
34823
|
}
|
|
34737
34824
|
),
|
|
34738
|
-
isLive && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full bg-green-500 shrink-0 shadow-[0_0_4px_rgba(34,197,94,0.6)]", title: "Currently running" })
|
|
34825
|
+
isLive && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full bg-green-500 shrink-0 shadow-[0_0_4px_rgba(34,197,94,0.6)] mt-1.5", title: "Currently running" })
|
|
34739
34826
|
] }),
|
|
34740
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500 font-medium tabular-nums shrink-0", children: [
|
|
34827
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500 font-medium tabular-nums shrink-0 pt-0.5", children: [
|
|
34741
34828
|
Math.round(current),
|
|
34742
34829
|
" / ",
|
|
34743
34830
|
Math.round(target)
|
|
@@ -45075,7 +45162,7 @@ var FileManagerFilters = ({
|
|
|
45075
45162
|
onClick: () => {
|
|
45076
45163
|
onIdleClipSortChange?.(idleClipSort === "latest" ? "idle_duration_desc" : "latest");
|
|
45077
45164
|
},
|
|
45078
|
-
className: `p-2 rounded-xl transition-all duration-200 ${idleClipSort === "idle_duration_desc" ? "bg-
|
|
45165
|
+
className: `p-2 rounded-xl transition-all duration-200 ${idleClipSort === "idle_duration_desc" ? "bg-blue-100 text-blue-600 hover:bg-blue-200 shadow-sm" : "bg-slate-100 text-slate-600 hover:bg-slate-200"}`,
|
|
45079
45166
|
title: idleClipSort === "idle_duration_desc" ? "Sort by newest first" : "Sort by longest idle first",
|
|
45080
45167
|
"aria-label": idleClipSort === "idle_duration_desc" ? "Sort idle clips by newest first" : "Sort idle clips by longest idle first",
|
|
45081
45168
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownWideNarrow, { className: "h-5 w-5" })
|
|
@@ -45142,7 +45229,7 @@ var FileManagerFilters = ({
|
|
|
45142
45229
|
}
|
|
45143
45230
|
)
|
|
45144
45231
|
] }),
|
|
45145
|
-
activeFilter === "idle_time" && idleClipSort === "idle_duration_desc" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-fit items-center gap-2 rounded-full border border-
|
|
45232
|
+
activeFilter === "idle_time" && idleClipSort === "idle_duration_desc" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-fit items-center gap-2 rounded-full border border-blue-100 bg-blue-50/70 px-2.5 py-1 text-xs text-blue-700 shadow-sm", children: [
|
|
45146
45233
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownWideNarrow, { className: "h-3.5 w-3.5" }),
|
|
45147
45234
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Longest idle first" }),
|
|
45148
45235
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -45152,7 +45239,7 @@ var FileManagerFilters = ({
|
|
|
45152
45239
|
e.stopPropagation();
|
|
45153
45240
|
onIdleClipSortChange?.("latest");
|
|
45154
45241
|
},
|
|
45155
|
-
className: "rounded-full p-0.5 transition-colors hover:bg-
|
|
45242
|
+
className: "rounded-full p-0.5 transition-colors hover:bg-blue-100",
|
|
45156
45243
|
title: "Clear idle sort",
|
|
45157
45244
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" })
|
|
45158
45245
|
}
|
|
@@ -57614,7 +57701,7 @@ var SideNavBar = React144.memo(({
|
|
|
57614
57701
|
const role = user?.role_level;
|
|
57615
57702
|
const roleNavPaths = React144.useMemo(() => getRoleNavPaths(role), [role]);
|
|
57616
57703
|
const showLiveMonitorLink = roleNavPaths.includes("/live-monitor");
|
|
57617
|
-
const rootDashboardSurface = React144.useMemo(() =>
|
|
57704
|
+
const rootDashboardSurface = React144.useMemo(() => "monitor", []);
|
|
57618
57705
|
const getBasePath = React144.useCallback((path) => {
|
|
57619
57706
|
const firstSegment = path.split("?")[0].split("/").filter(Boolean)[0];
|
|
57620
57707
|
return firstSegment ? `/${firstSegment}` : "/";
|
|
@@ -57665,12 +57752,6 @@ var SideNavBar = React144.memo(({
|
|
|
57665
57752
|
dashboard_surface: dashboardSurface
|
|
57666
57753
|
}
|
|
57667
57754
|
}), []);
|
|
57668
|
-
const handleHomeClick = React144.useCallback(() => {
|
|
57669
|
-
navigate("/", {
|
|
57670
|
-
trackingEvent: buildDashboardSurfaceTrackingEvent("side_nav", "/", rootDashboardSurface)
|
|
57671
|
-
});
|
|
57672
|
-
onMobileMenuClose?.();
|
|
57673
|
-
}, [navigate, onMobileMenuClose, buildDashboardSurfaceTrackingEvent, rootDashboardSurface]);
|
|
57674
57755
|
const handleLeaderboardClick = React144.useCallback(() => {
|
|
57675
57756
|
navigate(`/leaderboard`, {
|
|
57676
57757
|
trackingEvent: {
|
|
@@ -57976,7 +58057,6 @@ var SideNavBar = React144.memo(({
|
|
|
57976
58057
|
});
|
|
57977
58058
|
onMobileMenuClose?.();
|
|
57978
58059
|
}, [navigate, onMobileMenuClose, buildDashboardSurfaceTrackingEvent, rootDashboardSurface]);
|
|
57979
|
-
const homeButtonClasses = React144.useMemo(() => getButtonClasses("/"), [getButtonClasses]);
|
|
57980
58060
|
const liveButtonClasses = React144.useMemo(() => getButtonClasses("/live-monitor"), [getButtonClasses]);
|
|
57981
58061
|
const leaderboardButtonClasses = React144.useMemo(() => getButtonClasses("/leaderboard"), [getButtonClasses]);
|
|
57982
58062
|
const kpisButtonClasses = React144.useMemo(() => getButtonClasses("/kpis"), [getButtonClasses]);
|
|
@@ -58007,118 +58087,99 @@ var SideNavBar = React144.memo(({
|
|
|
58007
58087
|
children: /* @__PURE__ */ jsxRuntime.jsx(Logo, { className: "w-12 h-12 object-contain cursor-pointer" })
|
|
58008
58088
|
}
|
|
58009
58089
|
) }),
|
|
58010
|
-
/* @__PURE__ */ jsxRuntime.
|
|
58011
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
58012
|
-
|
|
58013
|
-
|
|
58014
|
-
|
|
58015
|
-
|
|
58016
|
-
|
|
58017
|
-
|
|
58018
|
-
|
|
58019
|
-
|
|
58020
|
-
|
|
58021
|
-
|
|
58022
|
-
|
|
58023
|
-
|
|
58024
|
-
|
|
58025
|
-
|
|
58026
|
-
|
|
58027
|
-
|
|
58028
|
-
|
|
58029
|
-
|
|
58030
|
-
|
|
58031
|
-
|
|
58032
|
-
|
|
58033
|
-
|
|
58034
|
-
|
|
58035
|
-
|
|
58036
|
-
|
|
58037
|
-
|
|
58038
|
-
|
|
58039
|
-
|
|
58040
|
-
|
|
58041
|
-
|
|
58042
|
-
|
|
58043
|
-
|
|
58044
|
-
|
|
58045
|
-
|
|
58046
|
-
|
|
58047
|
-
|
|
58048
|
-
|
|
58049
|
-
|
|
58050
|
-
|
|
58051
|
-
|
|
58052
|
-
"
|
|
58053
|
-
|
|
58054
|
-
|
|
58055
|
-
|
|
58056
|
-
|
|
58057
|
-
|
|
58058
|
-
|
|
58059
|
-
|
|
58060
|
-
|
|
58061
|
-
|
|
58062
|
-
|
|
58063
|
-
|
|
58064
|
-
|
|
58065
|
-
|
|
58066
|
-
|
|
58067
|
-
"
|
|
58068
|
-
|
|
58069
|
-
|
|
58070
|
-
|
|
58071
|
-
|
|
58072
|
-
|
|
58073
|
-
|
|
58074
|
-
|
|
58075
|
-
|
|
58076
|
-
|
|
58077
|
-
|
|
58078
|
-
|
|
58079
|
-
|
|
58080
|
-
|
|
58081
|
-
|
|
58082
|
-
|
|
58083
|
-
children:
|
|
58084
|
-
|
|
58085
|
-
|
|
58086
|
-
|
|
58087
|
-
|
|
58088
|
-
|
|
58089
|
-
|
|
58090
|
-
|
|
58091
|
-
|
|
58092
|
-
|
|
58093
|
-
|
|
58094
|
-
|
|
58095
|
-
|
|
58096
|
-
|
|
58097
|
-
|
|
58098
|
-
"
|
|
58099
|
-
|
|
58100
|
-
|
|
58101
|
-
|
|
58102
|
-
|
|
58103
|
-
}
|
|
58104
|
-
),
|
|
58105
|
-
canAccessPath("/health") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58106
|
-
"button",
|
|
58107
|
-
{
|
|
58108
|
-
onClick: handleHealthClick,
|
|
58109
|
-
className: healthButtonClasses,
|
|
58110
|
-
"aria-label": "System Health",
|
|
58111
|
-
tabIndex: 0,
|
|
58112
|
-
role: "tab",
|
|
58113
|
-
"aria-selected": isPathActive("/health"),
|
|
58114
|
-
children: [
|
|
58115
|
-
/* @__PURE__ */ jsxRuntime.jsx(outline.HeartIcon, { className: "w-5 h-5 mb-1" }),
|
|
58116
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Health" })
|
|
58117
|
-
]
|
|
58118
|
-
}
|
|
58119
|
-
)
|
|
58120
|
-
] })
|
|
58121
|
-
] }),
|
|
58090
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full py-6 px-4 overflow-y-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
58091
|
+
showLiveMonitorLink && canAccessPath("/live-monitor") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58092
|
+
"button",
|
|
58093
|
+
{
|
|
58094
|
+
onClick: handleLiveClick,
|
|
58095
|
+
className: liveButtonClasses,
|
|
58096
|
+
"aria-label": "Monitor",
|
|
58097
|
+
tabIndex: 0,
|
|
58098
|
+
role: "tab",
|
|
58099
|
+
"aria-selected": isPathActive("/live-monitor"),
|
|
58100
|
+
children: [
|
|
58101
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.VideoCameraIcon, { className: "w-5 h-5 mb-1" }),
|
|
58102
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Monitor" })
|
|
58103
|
+
]
|
|
58104
|
+
}
|
|
58105
|
+
),
|
|
58106
|
+
canAccessPath("/leaderboard") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58107
|
+
"button",
|
|
58108
|
+
{
|
|
58109
|
+
onClick: handleLeaderboardClick,
|
|
58110
|
+
className: leaderboardButtonClasses,
|
|
58111
|
+
"aria-label": "Leaderboard",
|
|
58112
|
+
tabIndex: 0,
|
|
58113
|
+
role: "tab",
|
|
58114
|
+
"aria-selected": isPathActive("/leaderboard"),
|
|
58115
|
+
children: [
|
|
58116
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.TrophyIcon, { className: "w-5 h-5 mb-1" }),
|
|
58117
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Leaders" })
|
|
58118
|
+
]
|
|
58119
|
+
}
|
|
58120
|
+
),
|
|
58121
|
+
canAccessPath("/kpis") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58122
|
+
"button",
|
|
58123
|
+
{
|
|
58124
|
+
onClick: handleKPIsClick,
|
|
58125
|
+
className: kpisButtonClasses,
|
|
58126
|
+
"aria-label": "Lines",
|
|
58127
|
+
tabIndex: 0,
|
|
58128
|
+
role: "tab",
|
|
58129
|
+
"aria-selected": isPathActive("/kpis"),
|
|
58130
|
+
children: [
|
|
58131
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: "w-5 h-5 mb-1" }),
|
|
58132
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Lines" })
|
|
58133
|
+
]
|
|
58134
|
+
}
|
|
58135
|
+
),
|
|
58136
|
+
canAccessPath("/improvement-center") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58137
|
+
"button",
|
|
58138
|
+
{
|
|
58139
|
+
onClick: handleImprovementClick,
|
|
58140
|
+
className: improvementButtonClasses,
|
|
58141
|
+
"aria-label": "Improvement Center",
|
|
58142
|
+
tabIndex: 0,
|
|
58143
|
+
role: "tab",
|
|
58144
|
+
"aria-selected": isPathActive("/improvement-center"),
|
|
58145
|
+
children: [
|
|
58146
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.LightBulbIcon, { className: "w-5 h-5 mb-1" }),
|
|
58147
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight text-center", children: "Improve" })
|
|
58148
|
+
]
|
|
58149
|
+
}
|
|
58150
|
+
),
|
|
58151
|
+
showSupervisorManagement,
|
|
58152
|
+
skuEnabled && canAccessPath("/skus") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58153
|
+
"button",
|
|
58154
|
+
{
|
|
58155
|
+
onClick: handleSKUsClick,
|
|
58156
|
+
className: skusButtonClasses,
|
|
58157
|
+
"aria-label": "SKU Management",
|
|
58158
|
+
tabIndex: 0,
|
|
58159
|
+
role: "tab",
|
|
58160
|
+
"aria-selected": isPathActive("/skus"),
|
|
58161
|
+
children: [
|
|
58162
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.CubeIcon, { className: "w-5 h-5 mb-1" }),
|
|
58163
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "SKUs" })
|
|
58164
|
+
]
|
|
58165
|
+
}
|
|
58166
|
+
),
|
|
58167
|
+
canAccessPath("/health") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58168
|
+
"button",
|
|
58169
|
+
{
|
|
58170
|
+
onClick: handleHealthClick,
|
|
58171
|
+
className: healthButtonClasses,
|
|
58172
|
+
"aria-label": "System Health",
|
|
58173
|
+
tabIndex: 0,
|
|
58174
|
+
role: "tab",
|
|
58175
|
+
"aria-selected": isPathActive("/health"),
|
|
58176
|
+
children: [
|
|
58177
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.HeartIcon, { className: "w-5 h-5 mb-1" }),
|
|
58178
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Health" })
|
|
58179
|
+
]
|
|
58180
|
+
}
|
|
58181
|
+
)
|
|
58182
|
+
] }) }),
|
|
58122
58183
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full py-4 px-4 border-t border-gray-100 flex-shrink-0 flex flex-col gap-2", children: settingsItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58123
58184
|
"button",
|
|
58124
58185
|
{
|
|
@@ -58155,23 +58216,11 @@ var SideNavBar = React144.memo(({
|
|
|
58155
58216
|
};
|
|
58156
58217
|
};
|
|
58157
58218
|
return /* @__PURE__ */ jsxRuntime.jsxs("nav", { className: "px-5 py-6", children: [
|
|
58158
|
-
canAccessPath("/") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58159
|
-
"button",
|
|
58160
|
-
{
|
|
58161
|
-
onClick: handleMobileNavClick(handleHomeClick),
|
|
58162
|
-
className: getMobileButtonClass("/"),
|
|
58163
|
-
"aria-label": "Home",
|
|
58164
|
-
children: [
|
|
58165
|
-
/* @__PURE__ */ jsxRuntime.jsx(outline.HomeIcon, { className: getIconClass("/") }),
|
|
58166
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-medium", children: "Home" })
|
|
58167
|
-
]
|
|
58168
|
-
}
|
|
58169
|
-
),
|
|
58170
58219
|
showLiveMonitorLink && canAccessPath("/live-monitor") && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
58171
58220
|
"button",
|
|
58172
58221
|
{
|
|
58173
58222
|
onClick: handleMobileNavClick(handleLiveClick),
|
|
58174
|
-
className:
|
|
58223
|
+
className: getMobileButtonClass("/live-monitor"),
|
|
58175
58224
|
"aria-label": "Monitor",
|
|
58176
58225
|
children: [
|
|
58177
58226
|
/* @__PURE__ */ jsxRuntime.jsx(outline.VideoCameraIcon, { className: getIconClass("/live-monitor") }),
|
|
@@ -69737,6 +69786,19 @@ var formatDateKey2 = (dateKey, timezone, options) => {
|
|
|
69737
69786
|
return dateKey;
|
|
69738
69787
|
}
|
|
69739
69788
|
};
|
|
69789
|
+
var getFirstName = (displayName) => {
|
|
69790
|
+
const trimmedName = displayName.trim();
|
|
69791
|
+
if (!trimmedName) return "";
|
|
69792
|
+
return trimmedName.split(/\s+/)[0];
|
|
69793
|
+
};
|
|
69794
|
+
var formatSupervisorFirstNames = (supervisors, fallbackSupervisorNames) => {
|
|
69795
|
+
const firstNames = supervisors.map((supervisor) => getFirstName(supervisor.displayName)).filter((name) => name.length > 0);
|
|
69796
|
+
if (firstNames.length > 0) {
|
|
69797
|
+
return Array.from(new Set(firstNames)).join(", ");
|
|
69798
|
+
}
|
|
69799
|
+
const fallbackFirstNames = fallbackSupervisorNames.flatMap((names) => names.split(",")).map(getFirstName).filter((name) => name.length > 0);
|
|
69800
|
+
return fallbackFirstNames.length > 0 ? Array.from(new Set(fallbackFirstNames)).join(", ") : "Unassigned";
|
|
69801
|
+
};
|
|
69740
69802
|
var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Finished", placeholder = "--", onFinished }) => {
|
|
69741
69803
|
const [time2, setTime] = React144.useState("");
|
|
69742
69804
|
const hasFinishedRef = React144.useRef(false);
|
|
@@ -69862,7 +69924,7 @@ var LinesLeaderboard = ({
|
|
|
69862
69924
|
});
|
|
69863
69925
|
const supervisors = Array.from(supervisorByUserId.values());
|
|
69864
69926
|
const primarySupervisor = supervisors[0];
|
|
69865
|
-
const supervisorName = supervisors
|
|
69927
|
+
const supervisorName = formatSupervisorFirstNames(supervisors, fallbackSupervisorNames);
|
|
69866
69928
|
const supervisorImage = primarySupervisor?.profilePhotoUrl || null;
|
|
69867
69929
|
return {
|
|
69868
69930
|
...row,
|
|
@@ -70122,21 +70184,49 @@ var LinesLeaderboard = ({
|
|
|
70122
70184
|
] }) }) }) })
|
|
70123
70185
|
] });
|
|
70124
70186
|
};
|
|
70187
|
+
var SIGNAL_PILL_STYLES = {
|
|
70188
|
+
stable: {
|
|
70189
|
+
container: "bg-emerald-100 text-emerald-700 border border-emerald-200",
|
|
70190
|
+
dot: "bg-emerald-500"
|
|
70191
|
+
},
|
|
70192
|
+
warning: {
|
|
70193
|
+
container: "bg-amber-100 text-amber-700 border border-amber-200",
|
|
70194
|
+
dot: "bg-amber-500"
|
|
70195
|
+
},
|
|
70196
|
+
attention: {
|
|
70197
|
+
container: "bg-red-100 text-red-700 border border-red-200",
|
|
70198
|
+
dot: "bg-red-500"
|
|
70199
|
+
}
|
|
70200
|
+
};
|
|
70201
|
+
var KpiSignalPill = ({ signal, efficiencyLegend }) => {
|
|
70202
|
+
const status = getKpiSignalStatus(signal, efficiencyLegend);
|
|
70203
|
+
const label = getKpiSignalLabel(signal, efficiencyLegend);
|
|
70204
|
+
if (!status || !label) return null;
|
|
70205
|
+
const styles2 = SIGNAL_PILL_STYLES[status];
|
|
70206
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
70207
|
+
"div",
|
|
70208
|
+
{
|
|
70209
|
+
className: `flex items-center gap-1.5 px-2.5 sm:px-3 py-1 sm:py-1.5 rounded-full text-xs font-medium flex-shrink-0 ${styles2.container}`,
|
|
70210
|
+
style: { minWidth: "fit-content" },
|
|
70211
|
+
children: [
|
|
70212
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-2 h-2 rounded-full ${styles2.dot} animate-pulse` }),
|
|
70213
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: label })
|
|
70214
|
+
]
|
|
70215
|
+
}
|
|
70216
|
+
);
|
|
70217
|
+
};
|
|
70125
70218
|
var LineCard = ({
|
|
70126
70219
|
line,
|
|
70127
70220
|
kpis,
|
|
70128
70221
|
isLoading,
|
|
70129
70222
|
error,
|
|
70130
70223
|
onClick,
|
|
70224
|
+
efficiencyLegend,
|
|
70131
70225
|
supervisorEnabled = false,
|
|
70132
70226
|
supervisorName,
|
|
70133
70227
|
supervisors
|
|
70134
70228
|
}) => {
|
|
70135
70229
|
const isUptimeLine = (line.monitoring_mode ?? "output") === "uptime";
|
|
70136
|
-
const isOnTrack = React144__namespace.default.useMemo(() => {
|
|
70137
|
-
if (!kpis) return null;
|
|
70138
|
-
return isEfficiencyOnTrack(kpis.efficiency.value);
|
|
70139
|
-
}, [kpis]);
|
|
70140
70230
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
70141
70231
|
motion.div,
|
|
70142
70232
|
{
|
|
@@ -70208,10 +70298,7 @@ var LineCard = ({
|
|
|
70208
70298
|
] })
|
|
70209
70299
|
] })
|
|
70210
70300
|
] }),
|
|
70211
|
-
!isUptimeLine && kpis &&
|
|
70212
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-2 h-2 rounded-full ${isOnTrack ? "bg-emerald-500" : "bg-red-500"} animate-pulse` }),
|
|
70213
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: isOnTrack ? "On Track" : "Behind" })
|
|
70214
|
-
] })
|
|
70301
|
+
!isUptimeLine && kpis && /* @__PURE__ */ jsxRuntime.jsx(KpiSignalPill, { signal: kpis.lineSignal, efficiencyLegend })
|
|
70215
70302
|
] }) }),
|
|
70216
70303
|
isLoading && !kpis && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
70217
70304
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse", children: [
|
|
@@ -70279,12 +70366,9 @@ var KpiGroupCard = ({
|
|
|
70279
70366
|
isLoading,
|
|
70280
70367
|
error,
|
|
70281
70368
|
isUptimeMode,
|
|
70369
|
+
efficiencyLegend,
|
|
70282
70370
|
onClick
|
|
70283
70371
|
}) => {
|
|
70284
|
-
const isOnTrack = React144__namespace.default.useMemo(() => {
|
|
70285
|
-
if (!kpis) return null;
|
|
70286
|
-
return isEfficiencyOnTrack(kpis.efficiency.value);
|
|
70287
|
-
}, [kpis]);
|
|
70288
70372
|
const outputTarget = Number(kpis?.outputProgress?.target ?? 0);
|
|
70289
70373
|
const outputCurrent = Number(kpis?.outputProgress?.current ?? 0);
|
|
70290
70374
|
const progressPercent = outputTarget > 0 ? Math.min(outputCurrent / outputTarget * 100, 100) : 0;
|
|
@@ -70308,10 +70392,7 @@ var KpiGroupCard = ({
|
|
|
70308
70392
|
),
|
|
70309
70393
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-1 text-xs font-medium text-gray-500", children: subtitle })
|
|
70310
70394
|
] }),
|
|
70311
|
-
!isUptimeMode && kpis &&
|
|
70312
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-2 h-2 rounded-full ${isOnTrack ? "bg-emerald-500" : "bg-red-500"} animate-pulse` }),
|
|
70313
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: isOnTrack ? "On Track" : "Behind" })
|
|
70314
|
-
] })
|
|
70395
|
+
!isUptimeMode && kpis && /* @__PURE__ */ jsxRuntime.jsx(KpiSignalPill, { signal: kpis.lineSignal, efficiencyLegend })
|
|
70315
70396
|
] }) }),
|
|
70316
70397
|
isLoading && !kpis && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
|
|
70317
70398
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse", children: [
|
|
@@ -70628,7 +70709,8 @@ var KPIsOverviewView = ({
|
|
|
70628
70709
|
const {
|
|
70629
70710
|
lineMetrics,
|
|
70630
70711
|
isLoading: metricsLoading,
|
|
70631
|
-
error: metricsError
|
|
70712
|
+
error: metricsError,
|
|
70713
|
+
efficiencyLegend
|
|
70632
70714
|
} = useDashboardMetrics({
|
|
70633
70715
|
lineId: factoryViewId,
|
|
70634
70716
|
userAccessibleLineIds: metricsLineIds
|
|
@@ -70972,7 +71054,11 @@ var KPIsOverviewView = ({
|
|
|
70972
71054
|
trackProps.output_current = kpis.outputProgress?.current;
|
|
70973
71055
|
trackProps.output_target = kpis.outputProgress?.target;
|
|
70974
71056
|
trackProps.underperforming_workers = kpis.underperformingWorkers?.current;
|
|
70975
|
-
|
|
71057
|
+
const signalLabel = getKpiSignalLabel(kpis.lineSignal, efficiencyLegend);
|
|
71058
|
+
if (signalLabel) {
|
|
71059
|
+
trackProps.status = signalLabel;
|
|
71060
|
+
trackProps.signal_source = kpis.lineSignal?.source ?? null;
|
|
71061
|
+
}
|
|
70976
71062
|
}
|
|
70977
71063
|
trackCoreEvent("Line Card Clicked", trackProps);
|
|
70978
71064
|
if (activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily) {
|
|
@@ -71058,6 +71144,7 @@ var KPIsOverviewView = ({
|
|
|
71058
71144
|
isLoading: metricsLoading,
|
|
71059
71145
|
error: metricsError,
|
|
71060
71146
|
onClick: (kpis) => handleLineClick(line, kpis),
|
|
71147
|
+
efficiencyLegend,
|
|
71061
71148
|
supervisorEnabled,
|
|
71062
71149
|
supervisorName: supervisorNamesByLineId.get(line.id) || null,
|
|
71063
71150
|
supervisors: supervisorsByLineId?.get(line.id)
|
|
@@ -71079,6 +71166,7 @@ var KPIsOverviewView = ({
|
|
|
71079
71166
|
isLoading: metricsLoading,
|
|
71080
71167
|
error: metricsError,
|
|
71081
71168
|
isUptimeMode: viewType === "machine",
|
|
71169
|
+
efficiencyLegend,
|
|
71082
71170
|
onClick
|
|
71083
71171
|
},
|
|
71084
71172
|
key
|
|
@@ -87265,6 +87353,7 @@ exports.KPIDetailView = KPIDetailView_default;
|
|
|
87265
87353
|
exports.KPIGrid = KPIGrid;
|
|
87266
87354
|
exports.KPIHeader = KPIHeader;
|
|
87267
87355
|
exports.KPISection = KPISection;
|
|
87356
|
+
exports.KPI_SIGNAL_LABELS = KPI_SIGNAL_LABELS;
|
|
87268
87357
|
exports.KPIsOverviewView = KPIsOverviewView_default;
|
|
87269
87358
|
exports.LINE_1_UUID = LINE_1_UUID;
|
|
87270
87359
|
exports.LINE_2_UUID = LINE_2_UUID;
|
|
@@ -87398,6 +87487,7 @@ exports.WorkspaceWhatsAppShareButton = WorkspaceWhatsAppShareButton;
|
|
|
87398
87487
|
exports.actionService = actionService;
|
|
87399
87488
|
exports.addSentryBreadcrumb = addSentryBreadcrumb;
|
|
87400
87489
|
exports.aggregateKPIsFromLineMetricsRows = aggregateKPIsFromLineMetricsRows;
|
|
87490
|
+
exports.aggregateLineSignals = aggregateLineSignals;
|
|
87401
87491
|
exports.alertsService = alertsService;
|
|
87402
87492
|
exports.apiUtils = apiUtils;
|
|
87403
87493
|
exports.areAllLinesOnSameShift = areAllLinesOnSameShift;
|
|
@@ -87502,6 +87592,8 @@ exports.getDefaultCameraStreamUrl = getDefaultCameraStreamUrl;
|
|
|
87502
87592
|
exports.getDefaultLineId = getDefaultLineId;
|
|
87503
87593
|
exports.getDefaultTabForWorkspace = getDefaultTabForWorkspace;
|
|
87504
87594
|
exports.getInitials = getInitials;
|
|
87595
|
+
exports.getKpiSignalLabel = getKpiSignalLabel;
|
|
87596
|
+
exports.getKpiSignalStatus = getKpiSignalStatus;
|
|
87505
87597
|
exports.getLineDisplayName = getLineDisplayName;
|
|
87506
87598
|
exports.getManufacturingInsights = getManufacturingInsights;
|
|
87507
87599
|
exports.getMetricsTablePrefix = getMetricsTablePrefix;
|