@optifye/dashboard-core 6.11.42 → 6.11.44
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 +5 -0
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +836 -245
- package/dist/index.mjs +836 -245
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13458,10 +13458,19 @@ function getEfficiencyTextColorClasses(efficiency, legend = DEFAULT_EFFICIENCY_L
|
|
|
13458
13458
|
|
|
13459
13459
|
// src/lib/hooks/useDashboardMetrics.ts
|
|
13460
13460
|
var DEBUG_DASHBOARD_LOGS = process.env.NEXT_PUBLIC_DEBUG_DASHBOARD === "true";
|
|
13461
|
+
var REALTIME_REFRESH_DEBOUNCE_MS = 1500;
|
|
13462
|
+
var REALTIME_REFRESH_MIN_INTERVAL_MS = 5e3;
|
|
13461
13463
|
var logDebug = (...args) => {
|
|
13462
13464
|
if (!DEBUG_DASHBOARD_LOGS) return;
|
|
13463
13465
|
console.log(...args);
|
|
13464
13466
|
};
|
|
13467
|
+
var buildMetricsScopeKey = (lineId, lineIds) => {
|
|
13468
|
+
const normalizedLineIds = Array.from(new Set((lineIds || []).filter(Boolean))).sort();
|
|
13469
|
+
if (normalizedLineIds.length > 0) {
|
|
13470
|
+
return `${lineId}|${normalizedLineIds.join(",")}`;
|
|
13471
|
+
}
|
|
13472
|
+
return lineId;
|
|
13473
|
+
};
|
|
13465
13474
|
var parseEfficiencyLegend = (legend) => {
|
|
13466
13475
|
if (!legend) return null;
|
|
13467
13476
|
const coerce = (value, fallback) => {
|
|
@@ -13541,6 +13550,7 @@ var useDashboardMetrics = ({
|
|
|
13541
13550
|
const supabase = useSupabase();
|
|
13542
13551
|
const [metrics2, setMetrics] = useState({ workspaceMetrics: [], lineMetrics: [] });
|
|
13543
13552
|
const [metricsLineId, setMetricsLineId] = useState(lineId ?? null);
|
|
13553
|
+
const [metricsScopeKey, setMetricsScopeKey] = useState(() => buildMetricsScopeKey(lineId, lineIds));
|
|
13544
13554
|
const [isLoading, setIsLoading] = useState(true);
|
|
13545
13555
|
const [error, setError] = useState(null);
|
|
13546
13556
|
const lineIdRef = useRef(lineId);
|
|
@@ -13550,8 +13560,10 @@ var useDashboardMetrics = ({
|
|
|
13550
13560
|
const abortControllerRef = useRef(null);
|
|
13551
13561
|
const lastFetchKeyRef = useRef(null);
|
|
13552
13562
|
const inFlightFetchKeyRef = useRef(null);
|
|
13553
|
-
const updateQueueRef = useRef(false);
|
|
13554
13563
|
const onLineMetricsUpdateRef = useRef(onLineMetricsUpdate);
|
|
13564
|
+
const pendingRealtimeRefreshRef = useRef(false);
|
|
13565
|
+
const realtimeRefreshTimerRef = useRef(null);
|
|
13566
|
+
const lastRealtimeRefreshStartedAtRef = useRef(0);
|
|
13555
13567
|
const shiftGroupsRef = useRef(shiftGroups);
|
|
13556
13568
|
const operationalShiftKeyRef = useRef(operationalShiftKey);
|
|
13557
13569
|
const configuredLineIdsRef = useRef(configuredLineIds);
|
|
@@ -13579,15 +13591,17 @@ var useDashboardMetrics = ({
|
|
|
13579
13591
|
() => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
|
|
13580
13592
|
[entityConfig.companyId]
|
|
13581
13593
|
);
|
|
13594
|
+
const requestedScopeKey = useMemo(
|
|
13595
|
+
() => buildMetricsScopeKey(lineId, isFactoryView ? targetFactoryLineIds : void 0),
|
|
13596
|
+
[isFactoryView, lineId, targetFactoryLineIds]
|
|
13597
|
+
);
|
|
13582
13598
|
useEffect(() => {
|
|
13583
13599
|
lineIdRef.current = lineId;
|
|
13584
|
-
setMetrics({ workspaceMetrics: [], lineMetrics: [], metadata: void 0, efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND });
|
|
13585
|
-
setMetricsLineId(null);
|
|
13586
13600
|
setIsLoading(true);
|
|
13587
13601
|
setError(null);
|
|
13588
13602
|
lastFetchKeyRef.current = null;
|
|
13589
13603
|
inFlightFetchKeyRef.current = null;
|
|
13590
|
-
}, [lineId]);
|
|
13604
|
+
}, [lineId, requestedScopeKey]);
|
|
13591
13605
|
const fetchAllMetrics = useCallback(async (options = {}) => {
|
|
13592
13606
|
const { force = false } = options;
|
|
13593
13607
|
const currentLineIdToUse = lineIdRef.current;
|
|
@@ -13600,7 +13614,6 @@ var useDashboardMetrics = ({
|
|
|
13600
13614
|
companySpecificMetricsTable
|
|
13601
13615
|
});
|
|
13602
13616
|
if (!currentLineIdToUse || !supabase || !enabled || shiftLoading || isTimezoneLoading || companySpecificMetricsTable.includes("unknown_company")) {
|
|
13603
|
-
updateQueueRef.current = false;
|
|
13604
13617
|
if (!metrics2?.workspaceMetrics?.length && !metrics2?.lineMetrics?.length && !shiftLoading) setIsLoading(false);
|
|
13605
13618
|
if (companySpecificMetricsTable.includes("unknown_company") && !error) {
|
|
13606
13619
|
setError({ message: "Company ID not configured for metrics table.", code: "CONFIG_ERROR" });
|
|
@@ -13613,6 +13626,10 @@ var useDashboardMetrics = ({
|
|
|
13613
13626
|
const usesShiftGroups = isFactory && shiftGroups.length > 0;
|
|
13614
13627
|
const singleShiftDetails = usesShiftGroups ? null : shiftConfig ? getCurrentShift(defaultTimezone, shiftConfig) : shiftGroups.length === 1 ? { date: shiftGroups[0].date, shiftId: shiftGroups[0].shiftId } : getCurrentShift(defaultTimezone, staticShiftConfig);
|
|
13615
13628
|
const fetchKey = usesShiftGroups ? `factory|${companyId || "unknown"}|${shiftGroupsKey}` : isFactory ? `factory|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}|${targetLineIdsKey}` : `${currentLineIdToUse}|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}`;
|
|
13629
|
+
const responseScopeKey = buildMetricsScopeKey(
|
|
13630
|
+
currentLineIdToUse,
|
|
13631
|
+
isFactory ? targetLineIds : void 0
|
|
13632
|
+
);
|
|
13616
13633
|
logDebug("[useDashboardMetrics] Fetch key details:", {
|
|
13617
13634
|
isFactory,
|
|
13618
13635
|
usesShiftGroups,
|
|
@@ -13622,14 +13639,8 @@ var useDashboardMetrics = ({
|
|
|
13622
13639
|
singleShiftDetails,
|
|
13623
13640
|
fetchKey
|
|
13624
13641
|
});
|
|
13625
|
-
if (inFlightFetchKeyRef.current === fetchKey)
|
|
13626
|
-
|
|
13627
|
-
return;
|
|
13628
|
-
}
|
|
13629
|
-
if (!force && lastFetchKeyRef.current === fetchKey) {
|
|
13630
|
-
updateQueueRef.current = false;
|
|
13631
|
-
return;
|
|
13632
|
-
}
|
|
13642
|
+
if (inFlightFetchKeyRef.current === fetchKey) return;
|
|
13643
|
+
if (!force && lastFetchKeyRef.current === fetchKey) return;
|
|
13633
13644
|
const requestId = ++activeRequestIdRef.current;
|
|
13634
13645
|
const requestLineId = currentLineIdToUse;
|
|
13635
13646
|
isFetchingRef.current = true;
|
|
@@ -13652,6 +13663,7 @@ var useDashboardMetrics = ({
|
|
|
13652
13663
|
efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND
|
|
13653
13664
|
});
|
|
13654
13665
|
setMetricsLineId(requestLineId);
|
|
13666
|
+
setMetricsScopeKey(responseScopeKey);
|
|
13655
13667
|
lastFetchKeyRef.current = inFlightFetchKeyRef.current;
|
|
13656
13668
|
return;
|
|
13657
13669
|
}
|
|
@@ -13861,6 +13873,7 @@ var useDashboardMetrics = ({
|
|
|
13861
13873
|
hydrateFromBackend(idleTimeVlmByLine);
|
|
13862
13874
|
setMetrics(newMetricsState);
|
|
13863
13875
|
setMetricsLineId(requestLineId);
|
|
13876
|
+
setMetricsScopeKey(responseScopeKey);
|
|
13864
13877
|
lastFetchKeyRef.current = inFlightFetchKeyRef.current;
|
|
13865
13878
|
} catch (err) {
|
|
13866
13879
|
if (abortController.signal.aborted || err?.name === "AbortError") {
|
|
@@ -13883,9 +13896,24 @@ var useDashboardMetrics = ({
|
|
|
13883
13896
|
if (requestId === activeRequestIdRef.current) {
|
|
13884
13897
|
setIsLoading(false);
|
|
13885
13898
|
isFetchingRef.current = false;
|
|
13886
|
-
updateQueueRef.current = false;
|
|
13887
13899
|
activeFetchLineIdRef.current = null;
|
|
13888
13900
|
inFlightFetchKeyRef.current = null;
|
|
13901
|
+
if (pendingRealtimeRefreshRef.current) {
|
|
13902
|
+
const elapsedSinceLastRealtimeRefresh = Date.now() - lastRealtimeRefreshStartedAtRef.current;
|
|
13903
|
+
const minIntervalRemaining = Math.max(0, REALTIME_REFRESH_MIN_INTERVAL_MS - elapsedSinceLastRealtimeRefresh);
|
|
13904
|
+
const nextDelay = Math.max(REALTIME_REFRESH_DEBOUNCE_MS, minIntervalRemaining);
|
|
13905
|
+
if (realtimeRefreshTimerRef.current === null) {
|
|
13906
|
+
realtimeRefreshTimerRef.current = window.setTimeout(() => {
|
|
13907
|
+
realtimeRefreshTimerRef.current = null;
|
|
13908
|
+
if (!pendingRealtimeRefreshRef.current || isFetchingRef.current || inFlightFetchKeyRef.current) {
|
|
13909
|
+
return;
|
|
13910
|
+
}
|
|
13911
|
+
pendingRealtimeRefreshRef.current = false;
|
|
13912
|
+
lastRealtimeRefreshStartedAtRef.current = Date.now();
|
|
13913
|
+
fetchAllMetricsRef.current({ force: true, reason: "subscription" });
|
|
13914
|
+
}, nextDelay);
|
|
13915
|
+
}
|
|
13916
|
+
}
|
|
13889
13917
|
}
|
|
13890
13918
|
}
|
|
13891
13919
|
}, [
|
|
@@ -13915,20 +13943,59 @@ var useDashboardMetrics = ({
|
|
|
13915
13943
|
useEffect(() => {
|
|
13916
13944
|
fetchAllMetricsRef.current = fetchAllMetrics;
|
|
13917
13945
|
}, [fetchAllMetrics]);
|
|
13918
|
-
const
|
|
13919
|
-
if (
|
|
13920
|
-
|
|
13921
|
-
|
|
13946
|
+
const clearRealtimeRefreshTimer = useCallback(() => {
|
|
13947
|
+
if (realtimeRefreshTimerRef.current !== null) {
|
|
13948
|
+
window.clearTimeout(realtimeRefreshTimerRef.current);
|
|
13949
|
+
realtimeRefreshTimerRef.current = null;
|
|
13950
|
+
}
|
|
13951
|
+
}, []);
|
|
13952
|
+
const scheduleRealtimeRefresh = useCallback(() => {
|
|
13953
|
+
if (!enabled || !supabase) {
|
|
13954
|
+
pendingRealtimeRefreshRef.current = false;
|
|
13955
|
+
clearRealtimeRefreshTimer();
|
|
13956
|
+
return;
|
|
13957
|
+
}
|
|
13958
|
+
if (!pendingRealtimeRefreshRef.current || realtimeRefreshTimerRef.current !== null) {
|
|
13959
|
+
return;
|
|
13960
|
+
}
|
|
13961
|
+
const elapsedSinceLastRealtimeRefresh = Date.now() - lastRealtimeRefreshStartedAtRef.current;
|
|
13962
|
+
const minIntervalRemaining = Math.max(0, REALTIME_REFRESH_MIN_INTERVAL_MS - elapsedSinceLastRealtimeRefresh);
|
|
13963
|
+
const nextDelay = Math.max(REALTIME_REFRESH_DEBOUNCE_MS, minIntervalRemaining);
|
|
13964
|
+
realtimeRefreshTimerRef.current = window.setTimeout(() => {
|
|
13965
|
+
realtimeRefreshTimerRef.current = null;
|
|
13966
|
+
if (!pendingRealtimeRefreshRef.current) {
|
|
13967
|
+
return;
|
|
13922
13968
|
}
|
|
13969
|
+
if (isFetchingRef.current || inFlightFetchKeyRef.current) {
|
|
13970
|
+
scheduleRealtimeRefresh();
|
|
13971
|
+
return;
|
|
13972
|
+
}
|
|
13973
|
+
pendingRealtimeRefreshRef.current = false;
|
|
13974
|
+
lastRealtimeRefreshStartedAtRef.current = Date.now();
|
|
13975
|
+
fetchAllMetricsRef.current({ force: true, reason: "subscription" });
|
|
13976
|
+
}, nextDelay);
|
|
13977
|
+
}, [clearRealtimeRefreshTimer, enabled, supabase]);
|
|
13978
|
+
useEffect(() => {
|
|
13979
|
+
return () => {
|
|
13980
|
+
clearRealtimeRefreshTimer();
|
|
13981
|
+
pendingRealtimeRefreshRef.current = false;
|
|
13982
|
+
};
|
|
13983
|
+
}, [clearRealtimeRefreshTimer]);
|
|
13984
|
+
const queueUpdate = useCallback(() => {
|
|
13985
|
+
if (!enabled) {
|
|
13986
|
+
logDebug("[useDashboardMetrics] queueUpdate skipped: metrics disabled");
|
|
13987
|
+
return;
|
|
13988
|
+
}
|
|
13989
|
+
if (!supabase) {
|
|
13923
13990
|
if (!supabase) {
|
|
13924
13991
|
logDebug("[useDashboardMetrics] queueUpdate skipped: supabase not ready");
|
|
13925
13992
|
}
|
|
13926
13993
|
return;
|
|
13927
13994
|
}
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
|
|
13931
|
-
}, [
|
|
13995
|
+
pendingRealtimeRefreshRef.current = true;
|
|
13996
|
+
logDebug("[useDashboardMetrics] queueUpdate queued realtime refresh");
|
|
13997
|
+
scheduleRealtimeRefresh();
|
|
13998
|
+
}, [enabled, scheduleRealtimeRefresh, supabase]);
|
|
13932
13999
|
useEffect(() => {
|
|
13933
14000
|
if (enabled && lineId && supabase && !shiftLoading && !isTimezoneLoading) {
|
|
13934
14001
|
fetchAllMetrics({ reason: "line-change" });
|
|
@@ -14048,7 +14115,7 @@ var useDashboardMetrics = ({
|
|
|
14048
14115
|
{ event: "*", schema, table: companySpecificMetricsTable, filter: filter2 },
|
|
14049
14116
|
(payload) => {
|
|
14050
14117
|
const payloadData = payload.new || payload.old;
|
|
14051
|
-
|
|
14118
|
+
logDebug("[useDashboardMetrics] \u{1F4E1} WS_METRICS payload received:", {
|
|
14052
14119
|
eventType: payload.eventType,
|
|
14053
14120
|
lineId: payloadData?.line_id,
|
|
14054
14121
|
workspaceId: payloadData?.workspace_id,
|
|
@@ -14070,14 +14137,14 @@ var useDashboardMetrics = ({
|
|
|
14070
14137
|
shiftId: payloadData?.shift_id
|
|
14071
14138
|
});
|
|
14072
14139
|
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
14073
|
-
|
|
14140
|
+
logDebug("[useDashboardMetrics] \u2705 WS Date/shift match - triggering update");
|
|
14074
14141
|
queueUpdate();
|
|
14075
14142
|
} else {
|
|
14076
|
-
|
|
14143
|
+
logDebug("[useDashboardMetrics] \u274C WS Date/shift mismatch - update SKIPPED");
|
|
14077
14144
|
}
|
|
14078
14145
|
}
|
|
14079
14146
|
).subscribe((status) => {
|
|
14080
|
-
|
|
14147
|
+
logDebug("[useDashboardMetrics] \u{1F4F6} WS metrics subscription:", {
|
|
14081
14148
|
channel: wsChannelName,
|
|
14082
14149
|
status,
|
|
14083
14150
|
table: companySpecificMetricsTable,
|
|
@@ -14095,7 +14162,7 @@ var useDashboardMetrics = ({
|
|
|
14095
14162
|
{ event: "*", schema, table: configuredLineMetricsTable, filter: filter2 },
|
|
14096
14163
|
(payload) => {
|
|
14097
14164
|
const payloadData = payload.new || payload.old;
|
|
14098
|
-
|
|
14165
|
+
logDebug("[useDashboardMetrics] \u{1F4E1} LINE_METRICS payload received:", {
|
|
14099
14166
|
eventType: payload.eventType,
|
|
14100
14167
|
lineId: payloadData?.line_id,
|
|
14101
14168
|
date: payloadData?.date,
|
|
@@ -14115,15 +14182,15 @@ var useDashboardMetrics = ({
|
|
|
14115
14182
|
shiftId: payloadData?.shift_id
|
|
14116
14183
|
});
|
|
14117
14184
|
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
14118
|
-
|
|
14185
|
+
logDebug("[useDashboardMetrics] \u2705 Date/shift match - triggering update");
|
|
14119
14186
|
queueUpdate();
|
|
14120
14187
|
onLineMetricsUpdateRef.current?.();
|
|
14121
14188
|
} else {
|
|
14122
|
-
|
|
14189
|
+
logDebug("[useDashboardMetrics] \u274C Date/shift mismatch - update SKIPPED");
|
|
14123
14190
|
}
|
|
14124
14191
|
}
|
|
14125
14192
|
).subscribe((status) => {
|
|
14126
|
-
|
|
14193
|
+
logDebug("[useDashboardMetrics] \u{1F4F6} Line metrics subscription:", {
|
|
14127
14194
|
channel: lmChannelName,
|
|
14128
14195
|
status,
|
|
14129
14196
|
table: configuredLineMetricsTable,
|
|
@@ -14219,7 +14286,7 @@ var useDashboardMetrics = ({
|
|
|
14219
14286
|
{ event: "*", schema, table, filter: filter2 },
|
|
14220
14287
|
(payload) => {
|
|
14221
14288
|
const payloadData = payload.new || payload.old;
|
|
14222
|
-
|
|
14289
|
+
logDebug(`[useDashboardMetrics] \u{1F4E1} ${table.toUpperCase()} payload received (single-line):`, {
|
|
14223
14290
|
eventType: payload.eventType,
|
|
14224
14291
|
table: payload.table,
|
|
14225
14292
|
lineId: payloadData?.line_id,
|
|
@@ -14243,14 +14310,14 @@ var useDashboardMetrics = ({
|
|
|
14243
14310
|
shiftId: payloadData?.shift_id
|
|
14244
14311
|
});
|
|
14245
14312
|
if (payloadData?.date === operationalDateForSubscription && payloadData?.shift_id === currentShiftDetails.shiftId) {
|
|
14246
|
-
|
|
14313
|
+
logDebug(`[useDashboardMetrics] \u2705 ${table} Date/shift match - triggering update`);
|
|
14247
14314
|
callback();
|
|
14248
14315
|
} else {
|
|
14249
|
-
|
|
14316
|
+
logDebug(`[useDashboardMetrics] \u274C ${table} Date/shift mismatch - update SKIPPED`);
|
|
14250
14317
|
}
|
|
14251
14318
|
}
|
|
14252
14319
|
).subscribe((status) => {
|
|
14253
|
-
|
|
14320
|
+
logDebug(`[useDashboardMetrics] \u{1F4F6} ${table} subscription:`, {
|
|
14254
14321
|
channel: channelName,
|
|
14255
14322
|
status,
|
|
14256
14323
|
table,
|
|
@@ -14299,14 +14366,17 @@ var useDashboardMetrics = ({
|
|
|
14299
14366
|
lineId
|
|
14300
14367
|
// NOTE: userAccessibleLineIds removed - accessed via ref
|
|
14301
14368
|
]);
|
|
14302
|
-
const
|
|
14303
|
-
const
|
|
14369
|
+
const isCurrentScopeResolved = metricsScopeKey === requestedScopeKey;
|
|
14370
|
+
const hasLastGoodMetrics = metrics2.workspaceMetrics.length > 0 || metrics2.lineMetrics.length > 0;
|
|
14371
|
+
const canReuseLastGoodMetrics = hasLastGoodMetrics && !isCurrentScopeResolved && (isLoading || !!error);
|
|
14372
|
+
const safeMetrics = isCurrentScopeResolved || canReuseLastGoodMetrics ? metrics2 : { workspaceMetrics: [], lineMetrics: [], metadata: void 0, efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND };
|
|
14304
14373
|
return {
|
|
14305
14374
|
workspaceMetrics: safeMetrics?.workspaceMetrics || [],
|
|
14306
14375
|
lineMetrics: safeMetrics?.lineMetrics || [],
|
|
14307
14376
|
efficiencyLegend: safeMetrics?.efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND,
|
|
14308
14377
|
metadata: safeMetrics?.metadata,
|
|
14309
|
-
isLoading: enabled ? isLoading || !
|
|
14378
|
+
isLoading: enabled ? isLoading || !isCurrentScopeResolved && !canReuseLastGoodMetrics : false,
|
|
14379
|
+
isCurrentScopeResolved,
|
|
14310
14380
|
error,
|
|
14311
14381
|
refetch: () => {
|
|
14312
14382
|
if (!enabled) {
|
|
@@ -16754,6 +16824,7 @@ var isInitialized = false;
|
|
|
16754
16824
|
var isInitializing = false;
|
|
16755
16825
|
var initializedWithLineIds = [];
|
|
16756
16826
|
var missingLineContextWarnings = /* @__PURE__ */ new Set();
|
|
16827
|
+
var lineLoadPromises = /* @__PURE__ */ new Map();
|
|
16757
16828
|
var initializationPromise = null;
|
|
16758
16829
|
var workspaceDisplayNamesListeners = /* @__PURE__ */ new Set();
|
|
16759
16830
|
var notifyWorkspaceDisplayNamesListeners = (changedLineId) => {
|
|
@@ -16769,6 +16840,30 @@ var subscribeWorkspaceDisplayNames = (listener) => {
|
|
|
16769
16840
|
workspaceDisplayNamesListeners.add(listener);
|
|
16770
16841
|
return () => workspaceDisplayNamesListeners.delete(listener);
|
|
16771
16842
|
};
|
|
16843
|
+
var storeLineDisplayNames = (lineId, lineDisplayNamesMap) => {
|
|
16844
|
+
runtimeWorkspaceDisplayNames[lineId] = {};
|
|
16845
|
+
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16846
|
+
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16847
|
+
});
|
|
16848
|
+
};
|
|
16849
|
+
var ensureLineWorkspaceDisplayNamesLoaded = async (lineId) => {
|
|
16850
|
+
if (!lineId || runtimeWorkspaceDisplayNames[lineId]) {
|
|
16851
|
+
return;
|
|
16852
|
+
}
|
|
16853
|
+
const existingPromise = lineLoadPromises.get(lineId);
|
|
16854
|
+
if (existingPromise) {
|
|
16855
|
+
await existingPromise;
|
|
16856
|
+
return;
|
|
16857
|
+
}
|
|
16858
|
+
const loadPromise = workspaceService.getWorkspaceDisplayNames(void 0, lineId).then((lineDisplayNamesMap) => {
|
|
16859
|
+
storeLineDisplayNames(lineId, lineDisplayNamesMap);
|
|
16860
|
+
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
16861
|
+
}).finally(() => {
|
|
16862
|
+
lineLoadPromises.delete(lineId);
|
|
16863
|
+
});
|
|
16864
|
+
lineLoadPromises.set(lineId, loadPromise);
|
|
16865
|
+
await loadPromise;
|
|
16866
|
+
};
|
|
16772
16867
|
var getAllWorkspaceDisplayNamesSnapshot = (lineId) => {
|
|
16773
16868
|
if (lineId && runtimeWorkspaceDisplayNames[lineId]) {
|
|
16774
16869
|
return { ...runtimeWorkspaceDisplayNames[lineId] };
|
|
@@ -16833,6 +16928,7 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
16833
16928
|
}
|
|
16834
16929
|
console.log("\u{1F504} Target line IDs for workspace filtering:", targetLineIds);
|
|
16835
16930
|
runtimeWorkspaceDisplayNames = {};
|
|
16931
|
+
lineLoadPromises.clear();
|
|
16836
16932
|
if (targetLineIds.length > 0) {
|
|
16837
16933
|
const results = await Promise.all(
|
|
16838
16934
|
targetLineIds.map(async (lineId) => {
|
|
@@ -16842,10 +16938,7 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
16842
16938
|
})
|
|
16843
16939
|
);
|
|
16844
16940
|
results.forEach(({ lineId, lineDisplayNamesMap }) => {
|
|
16845
|
-
|
|
16846
|
-
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16847
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16848
|
-
});
|
|
16941
|
+
storeLineDisplayNames(lineId, lineDisplayNamesMap);
|
|
16849
16942
|
console.log(`\u2705 Stored ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
|
|
16850
16943
|
});
|
|
16851
16944
|
} else {
|
|
@@ -16877,13 +16970,8 @@ var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
|
16877
16970
|
if (lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16878
16971
|
console.log(`\u{1F504} Line ${lineId} not in cache, fetching...`);
|
|
16879
16972
|
try {
|
|
16880
|
-
|
|
16881
|
-
|
|
16882
|
-
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16883
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16884
|
-
});
|
|
16885
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
|
|
16886
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
16973
|
+
await ensureLineWorkspaceDisplayNamesLoaded(lineId);
|
|
16974
|
+
console.log(`\u2705 Added workspaces for line ${lineId}`);
|
|
16887
16975
|
} catch (error) {
|
|
16888
16976
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16889
16977
|
}
|
|
@@ -16896,13 +16984,8 @@ var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
|
16896
16984
|
if (lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16897
16985
|
console.log(`\u{1F504} Line ${lineId} not in cache after init, fetching...`);
|
|
16898
16986
|
try {
|
|
16899
|
-
|
|
16900
|
-
|
|
16901
|
-
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16902
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16903
|
-
});
|
|
16904
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
|
|
16905
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
16987
|
+
await ensureLineWorkspaceDisplayNamesLoaded(lineId);
|
|
16988
|
+
console.log(`\u2705 Added workspaces for line ${lineId}`);
|
|
16906
16989
|
} catch (error) {
|
|
16907
16990
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16908
16991
|
}
|
|
@@ -16939,13 +17022,8 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
16939
17022
|
}
|
|
16940
17023
|
if (isInitialized && lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16941
17024
|
console.log(`\u{1F504} Line ${lineId} not in cache, fetching its workspaces...`);
|
|
16942
|
-
|
|
16943
|
-
|
|
16944
|
-
lineDisplayNamesMap.forEach((displayName2, workspaceId2) => {
|
|
16945
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId2] = displayName2;
|
|
16946
|
-
});
|
|
16947
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId} to cache`);
|
|
16948
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
17025
|
+
ensureLineWorkspaceDisplayNamesLoaded(lineId).then(() => {
|
|
17026
|
+
console.log(`\u2705 Added workspaces for line ${lineId} to cache`);
|
|
16949
17027
|
}).catch((error) => {
|
|
16950
17028
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16951
17029
|
});
|
|
@@ -16987,13 +17065,8 @@ var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
16987
17065
|
}
|
|
16988
17066
|
if (isInitialized && lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16989
17067
|
console.log(`\u{1F504} Line ${lineId} not in cache, fetching its workspaces...`);
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
lineDisplayNamesMap.forEach((displayName2, workspaceId2) => {
|
|
16993
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId2] = displayName2;
|
|
16994
|
-
});
|
|
16995
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId} to cache`);
|
|
16996
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
17068
|
+
ensureLineWorkspaceDisplayNamesLoaded(lineId).then(() => {
|
|
17069
|
+
console.log(`\u2705 Added workspaces for line ${lineId} to cache`);
|
|
16997
17070
|
}).catch((error) => {
|
|
16998
17071
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16999
17072
|
});
|
|
@@ -17073,6 +17146,7 @@ var refreshWorkspaceDisplayNames = async (companyId) => {
|
|
|
17073
17146
|
workspaceService.clearWorkspaceDisplayNamesCache();
|
|
17074
17147
|
runtimeWorkspaceDisplayNames = {};
|
|
17075
17148
|
isInitialized = false;
|
|
17149
|
+
lineLoadPromises.clear();
|
|
17076
17150
|
await initializeWorkspaceDisplayNames();
|
|
17077
17151
|
notifyWorkspaceDisplayNamesListeners();
|
|
17078
17152
|
};
|
|
@@ -17082,6 +17156,7 @@ var clearWorkspaceDisplayNamesCache = () => {
|
|
|
17082
17156
|
isInitialized = false;
|
|
17083
17157
|
isInitializing = false;
|
|
17084
17158
|
initializedWithLineIds = [];
|
|
17159
|
+
lineLoadPromises.clear();
|
|
17085
17160
|
initializationPromise = null;
|
|
17086
17161
|
notifyWorkspaceDisplayNamesListeners();
|
|
17087
17162
|
};
|
|
@@ -17211,7 +17286,16 @@ var useWorkspaceDisplayNamesMap = (workspaceIds, lineId, companyId) => {
|
|
|
17211
17286
|
refetch: fetchDisplayNames
|
|
17212
17287
|
};
|
|
17213
17288
|
};
|
|
17214
|
-
var useWorkspaceVideoStreams = (workspaces) => {
|
|
17289
|
+
var useWorkspaceVideoStreams = (workspaces, options = {}) => {
|
|
17290
|
+
const explicitLineIdsKey = useMemo(() => {
|
|
17291
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17292
|
+
for (const lineId of options.lineIds || []) {
|
|
17293
|
+
if (lineId) {
|
|
17294
|
+
ids.add(lineId);
|
|
17295
|
+
}
|
|
17296
|
+
}
|
|
17297
|
+
return Array.from(ids).sort().join(",");
|
|
17298
|
+
}, [options.lineIds]);
|
|
17215
17299
|
const workspaceIdsKey = useMemo(() => {
|
|
17216
17300
|
const ids = /* @__PURE__ */ new Set();
|
|
17217
17301
|
for (const workspace of workspaces) {
|
|
@@ -17221,7 +17305,7 @@ var useWorkspaceVideoStreams = (workspaces) => {
|
|
|
17221
17305
|
}
|
|
17222
17306
|
return Array.from(ids).sort().join(",");
|
|
17223
17307
|
}, [workspaces]);
|
|
17224
|
-
const
|
|
17308
|
+
const inferredLineIdsKey = useMemo(() => {
|
|
17225
17309
|
const ids = /* @__PURE__ */ new Set();
|
|
17226
17310
|
for (const workspace of workspaces) {
|
|
17227
17311
|
if (workspace.line_id) {
|
|
@@ -17230,18 +17314,19 @@ var useWorkspaceVideoStreams = (workspaces) => {
|
|
|
17230
17314
|
}
|
|
17231
17315
|
return Array.from(ids).sort().join(",");
|
|
17232
17316
|
}, [workspaces]);
|
|
17317
|
+
const lineIdsKey = explicitLineIdsKey || inferredLineIdsKey;
|
|
17233
17318
|
const requestKey = useMemo(() => {
|
|
17234
|
-
if (workspaceIdsKey) {
|
|
17235
|
-
return `workspaces:${workspaceIdsKey}`;
|
|
17236
|
-
}
|
|
17237
17319
|
if (lineIdsKey) {
|
|
17238
17320
|
return `lines:${lineIdsKey}`;
|
|
17239
17321
|
}
|
|
17322
|
+
if (workspaceIdsKey) {
|
|
17323
|
+
return `workspaces:${workspaceIdsKey}`;
|
|
17324
|
+
}
|
|
17240
17325
|
return "";
|
|
17241
17326
|
}, [workspaceIdsKey, lineIdsKey]);
|
|
17242
17327
|
const workspaceIds = useMemo(
|
|
17243
|
-
() => workspaceIdsKey ? workspaceIdsKey.split(",") : [],
|
|
17244
|
-
[workspaceIdsKey]
|
|
17328
|
+
() => lineIdsKey ? [] : workspaceIdsKey ? workspaceIdsKey.split(",") : [],
|
|
17329
|
+
[lineIdsKey, workspaceIdsKey]
|
|
17245
17330
|
);
|
|
17246
17331
|
const lineIds = useMemo(
|
|
17247
17332
|
() => lineIdsKey ? lineIdsKey.split(",") : [],
|
|
@@ -18785,6 +18870,7 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18785
18870
|
const supabase = useSupabase();
|
|
18786
18871
|
const databaseConfig = useDatabaseConfig();
|
|
18787
18872
|
const refreshInterval = options.refreshInterval ?? DEFAULT_REFRESH_INTERVAL_MS;
|
|
18873
|
+
const enabled = options.enabled ?? true;
|
|
18788
18874
|
const workspaceIdsKey = useMemo(() => {
|
|
18789
18875
|
const ids = Array.from(new Set(workspaceIds.filter(Boolean)));
|
|
18790
18876
|
return ids.sort().join(",");
|
|
@@ -18795,7 +18881,7 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18795
18881
|
const isFetchingRef = useRef(false);
|
|
18796
18882
|
const refreshIntervalRef = useRef(null);
|
|
18797
18883
|
const fetchLastSeen = useCallback(async () => {
|
|
18798
|
-
if (!supabase || !workspaceIdsKey || isFetchingRef.current) return;
|
|
18884
|
+
if (!enabled || !supabase || !workspaceIdsKey || isFetchingRef.current) return;
|
|
18799
18885
|
const healthTable = databaseConfig?.tables?.workspace_health || "workspace_health_status";
|
|
18800
18886
|
try {
|
|
18801
18887
|
isFetchingRef.current = true;
|
|
@@ -18827,12 +18913,18 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18827
18913
|
setIsLoading(false);
|
|
18828
18914
|
isFetchingRef.current = false;
|
|
18829
18915
|
}
|
|
18830
|
-
}, [
|
|
18916
|
+
}, [databaseConfig?.tables?.workspace_health, enabled, supabase, workspaceIdsKey]);
|
|
18831
18917
|
useEffect(() => {
|
|
18918
|
+
if (!enabled) {
|
|
18919
|
+
setIsLoading(false);
|
|
18920
|
+
setError(null);
|
|
18921
|
+
setLastSeenByWorkspaceId({});
|
|
18922
|
+
return;
|
|
18923
|
+
}
|
|
18832
18924
|
fetchLastSeen();
|
|
18833
|
-
}, [fetchLastSeen]);
|
|
18925
|
+
}, [enabled, fetchLastSeen]);
|
|
18834
18926
|
useEffect(() => {
|
|
18835
|
-
if (!refreshInterval || !workspaceIdsKey) return;
|
|
18927
|
+
if (!enabled || !refreshInterval || !workspaceIdsKey) return;
|
|
18836
18928
|
refreshIntervalRef.current = setInterval(() => {
|
|
18837
18929
|
fetchLastSeen();
|
|
18838
18930
|
}, refreshInterval);
|
|
@@ -18842,7 +18934,7 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18842
18934
|
refreshIntervalRef.current = null;
|
|
18843
18935
|
}
|
|
18844
18936
|
};
|
|
18845
|
-
}, [fetchLastSeen, refreshInterval, workspaceIdsKey]);
|
|
18937
|
+
}, [enabled, fetchLastSeen, refreshInterval, workspaceIdsKey]);
|
|
18846
18938
|
return {
|
|
18847
18939
|
lastSeenByWorkspaceId,
|
|
18848
18940
|
isLoading,
|
|
@@ -34675,7 +34767,7 @@ var VideoCard = React143__default.memo(({
|
|
|
34675
34767
|
});
|
|
34676
34768
|
const showOffline = Boolean(isStreamStale);
|
|
34677
34769
|
const lastSeenText = lastSeenLabel || "Unknown";
|
|
34678
|
-
const workspaceDisplayName = displayName ||
|
|
34770
|
+
const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
|
|
34679
34771
|
const videoGridMetricValue = getVideoGridMetricValue(workspace);
|
|
34680
34772
|
const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
|
|
34681
34773
|
const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
|
|
@@ -34888,7 +34980,10 @@ var VideoGridView = React143__default.memo(({
|
|
|
34888
34980
|
}
|
|
34889
34981
|
return Array.from(ids);
|
|
34890
34982
|
}, [workspaces]);
|
|
34891
|
-
const
|
|
34983
|
+
const healthFetchEnabled = !videoStreamsLoading && workspaces.length > 0;
|
|
34984
|
+
const { lastSeenByWorkspaceId } = useWorkspaceHealthLastSeen(workspaceHealthIds, {
|
|
34985
|
+
enabled: healthFetchEnabled
|
|
34986
|
+
});
|
|
34892
34987
|
useEffect(() => {
|
|
34893
34988
|
const sample = workspaces.slice(0, 3).map((workspace) => ({
|
|
34894
34989
|
id: workspace.workspace_uuid || workspace.workspace_name,
|
|
@@ -34987,6 +35082,9 @@ var VideoGridView = React143__default.memo(({
|
|
|
34987
35082
|
}, [sortedWorkspaces, lineOrder, lineNames]);
|
|
34988
35083
|
lineGroups.length > 1;
|
|
34989
35084
|
const streamsReady = !videoStreamsLoading;
|
|
35085
|
+
const resolveWorkspaceDisplayName = useCallback((workspace) => {
|
|
35086
|
+
return workspace.displayName || displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || workspace.workspace_name;
|
|
35087
|
+
}, [displayNames]);
|
|
34990
35088
|
const calculateOptimalGrid = useCallback(() => {
|
|
34991
35089
|
if (!containerRef.current) return;
|
|
34992
35090
|
const containerPadding = 16;
|
|
@@ -35117,11 +35215,11 @@ var VideoGridView = React143__default.memo(({
|
|
|
35117
35215
|
efficiency: workspace.efficiency,
|
|
35118
35216
|
action_count: workspace.action_count
|
|
35119
35217
|
});
|
|
35120
|
-
const displayName =
|
|
35218
|
+
const displayName = resolveWorkspaceDisplayName(workspace);
|
|
35121
35219
|
const currentPath = (router.asPath || "/").split("#")[0];
|
|
35122
35220
|
const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
|
|
35123
35221
|
router.push(`/workspace/${workspaceId}${navParams}`);
|
|
35124
|
-
}, [router, prewarmClipsInit]);
|
|
35222
|
+
}, [resolveWorkspaceDisplayName, router, prewarmClipsInit]);
|
|
35125
35223
|
const handleStreamError = useCallback((workspaceId, options) => {
|
|
35126
35224
|
const isR2Stream = options?.isR2Stream ?? false;
|
|
35127
35225
|
const hasFallback = Boolean(options?.fallbackUrl);
|
|
@@ -35230,7 +35328,7 @@ var VideoGridView = React143__default.memo(({
|
|
|
35230
35328
|
legend: effectiveLegend,
|
|
35231
35329
|
cropping: card.workspaceCropping,
|
|
35232
35330
|
canvasFps: effectiveCanvasFps,
|
|
35233
|
-
displayName:
|
|
35331
|
+
displayName: resolveWorkspaceDisplayName(card.workspace),
|
|
35234
35332
|
lastSeenLabel: card.lastSeenLabel,
|
|
35235
35333
|
useRAF: effectiveUseRAF,
|
|
35236
35334
|
displayMinuteBucket,
|
|
@@ -35242,16 +35340,15 @@ var VideoGridView = React143__default.memo(({
|
|
|
35242
35340
|
},
|
|
35243
35341
|
card.workspaceKey
|
|
35244
35342
|
), [
|
|
35245
|
-
displayNames,
|
|
35246
35343
|
displayMinuteBucket,
|
|
35247
35344
|
effectiveCanvasFps,
|
|
35248
35345
|
effectiveLegend,
|
|
35249
35346
|
effectiveUseRAF,
|
|
35250
|
-
getWorkspaceDisplayName,
|
|
35251
35347
|
handleStreamError,
|
|
35252
35348
|
handleWorkspaceClick,
|
|
35253
35349
|
onWorkspaceHover,
|
|
35254
35350
|
onWorkspaceHoverEnd,
|
|
35351
|
+
resolveWorkspaceDisplayName,
|
|
35255
35352
|
selectedLine
|
|
35256
35353
|
]);
|
|
35257
35354
|
return /* @__PURE__ */ jsx("div", { className: `relative overflow-hidden h-full w-full bg-slate-50/30 ${className}`, children: /* @__PURE__ */ jsx(
|
|
@@ -35337,6 +35434,9 @@ var MapGridView = React143__default.memo(({
|
|
|
35337
35434
|
prewarmInFlightRef.current.delete(workspaceId);
|
|
35338
35435
|
});
|
|
35339
35436
|
}, [dashboardConfig, timezone, supabase]);
|
|
35437
|
+
const resolveWorkspaceDisplayName = useCallback((workspace) => {
|
|
35438
|
+
return workspace.displayName || displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || workspace.workspace_name;
|
|
35439
|
+
}, [displayNames]);
|
|
35340
35440
|
const handleWorkspaceClick = useCallback((workspace) => {
|
|
35341
35441
|
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
35342
35442
|
prewarmClipsInit(workspace);
|
|
@@ -35348,12 +35448,11 @@ var MapGridView = React143__default.memo(({
|
|
|
35348
35448
|
efficiency: workspace.efficiency,
|
|
35349
35449
|
action_count: workspace.action_count
|
|
35350
35450
|
});
|
|
35351
|
-
const displayName =
|
|
35352
|
-
getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
35451
|
+
const displayName = resolveWorkspaceDisplayName(workspace);
|
|
35353
35452
|
const currentPath = (router.asPath || "/").split("#")[0];
|
|
35354
35453
|
const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
|
|
35355
35454
|
router.push(`/workspace/${workspaceId}${navParams}`);
|
|
35356
|
-
}, [
|
|
35455
|
+
}, [resolveWorkspaceDisplayName, router, prewarmClipsInit]);
|
|
35357
35456
|
const activePositions = useMemo(() => {
|
|
35358
35457
|
return workspacePositions.filter((pos) => {
|
|
35359
35458
|
const wsKey = pos.id.toUpperCase();
|
|
@@ -35383,7 +35482,18 @@ var MapGridView = React143__default.memo(({
|
|
|
35383
35482
|
workspace_uuid: position.id,
|
|
35384
35483
|
// Use config ID as temporary UUID
|
|
35385
35484
|
line_id: "",
|
|
35485
|
+
// Empty line ID
|
|
35486
|
+
company_id: "",
|
|
35487
|
+
shift_id: 0,
|
|
35488
|
+
date: "",
|
|
35386
35489
|
efficiency: 0,
|
|
35490
|
+
performance_score: 0,
|
|
35491
|
+
action_count: 0,
|
|
35492
|
+
pph: 0,
|
|
35493
|
+
avg_cycle_time: 0,
|
|
35494
|
+
trend: 0,
|
|
35495
|
+
predicted_output: 0,
|
|
35496
|
+
action_threshold: 0,
|
|
35387
35497
|
show_exclamation: false
|
|
35388
35498
|
};
|
|
35389
35499
|
const workspaceId = effectiveWorkspace.workspace_uuid || effectiveWorkspace.workspace_name;
|
|
@@ -35392,7 +35502,7 @@ var MapGridView = React143__default.memo(({
|
|
|
35392
35502
|
const performanceColor = isInactivePlaceholder || isConveyorRow ? "bg-slate-200 border-slate-300 text-slate-500" : getPerformanceColor(effectiveWorkspace.efficiency);
|
|
35393
35503
|
!isInactivePlaceholder && !isConveyorRow && (effectiveWorkspace.show_exclamation ?? (effectiveWorkspace.efficiency < 50 && effectiveWorkspace.efficiency >= 10));
|
|
35394
35504
|
const configLabel = position.label;
|
|
35395
|
-
const workspaceDisplayName = configLabel || (isInactivePlaceholder ? "INACTIVE" :
|
|
35505
|
+
const workspaceDisplayName = configLabel || (isInactivePlaceholder ? "INACTIVE" : resolveWorkspaceDisplayName(effectiveWorkspace) || position.id);
|
|
35396
35506
|
return /* @__PURE__ */ jsx(
|
|
35397
35507
|
motion.div,
|
|
35398
35508
|
{
|
|
@@ -39359,9 +39469,12 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
|
39359
39469
|
var LoadingOverlay = ({
|
|
39360
39470
|
isVisible,
|
|
39361
39471
|
message = "Loading...",
|
|
39362
|
-
className
|
|
39472
|
+
className,
|
|
39473
|
+
contentClassName,
|
|
39474
|
+
contentVariant = "card"
|
|
39363
39475
|
}) => {
|
|
39364
39476
|
if (!isVisible) return null;
|
|
39477
|
+
const contentClasses = contentVariant === "plain" ? "flex flex-col items-center justify-center" : "flex flex-col items-center space-y-3 rounded-lg bg-white p-8 shadow-xl";
|
|
39365
39478
|
return /* @__PURE__ */ jsx(
|
|
39366
39479
|
motion.div,
|
|
39367
39480
|
{
|
|
@@ -39372,7 +39485,7 @@ var LoadingOverlay = ({
|
|
|
39372
39485
|
className: `fixed inset-0 z-[100] flex items-center justify-center bg-black/30 backdrop-blur-sm ${className || ""}`,
|
|
39373
39486
|
"aria-modal": "true",
|
|
39374
39487
|
role: "dialog",
|
|
39375
|
-
children: /* @__PURE__ */ jsx("div", { className:
|
|
39488
|
+
children: /* @__PURE__ */ jsx("div", { className: `${contentClasses} ${contentClassName || ""}`, children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message }) })
|
|
39376
39489
|
}
|
|
39377
39490
|
);
|
|
39378
39491
|
};
|
|
@@ -60702,6 +60815,353 @@ var HelpView = ({
|
|
|
60702
60815
|
};
|
|
60703
60816
|
var AuthenticatedHelpView = withAuth(HelpView);
|
|
60704
60817
|
var HelpView_default = HelpView;
|
|
60818
|
+
var sortWorkspaceMetrics = (left, right) => {
|
|
60819
|
+
if (left.line_id !== right.line_id) {
|
|
60820
|
+
return left.line_id.localeCompare(right.line_id);
|
|
60821
|
+
}
|
|
60822
|
+
return left.workspace_name.localeCompare(right.workspace_name, void 0, { numeric: true });
|
|
60823
|
+
};
|
|
60824
|
+
var transformWorkspaceMetrics = (rows) => (rows || []).map((item) => {
|
|
60825
|
+
const actionFamily = normalizeActionFamily({
|
|
60826
|
+
actionFamily: item.action_family,
|
|
60827
|
+
actionType: item.action_type,
|
|
60828
|
+
actionName: item.action_name
|
|
60829
|
+
});
|
|
60830
|
+
const actionType = actionFamily === "assembly" || actionFamily === "output" ? actionFamily : null;
|
|
60831
|
+
const metric = {
|
|
60832
|
+
company_id: item.company_id || "",
|
|
60833
|
+
line_id: item.line_id,
|
|
60834
|
+
shift_id: item.shift_id,
|
|
60835
|
+
date: item.date,
|
|
60836
|
+
workspace_uuid: item.workspace_id,
|
|
60837
|
+
workspace_name: item.workspace_name,
|
|
60838
|
+
displayName: item.workspace_display_name || item.display_name || void 0,
|
|
60839
|
+
action_count: item.total_output || 0,
|
|
60840
|
+
pph: item.avg_pph || 0,
|
|
60841
|
+
performance_score: item.performance_score || 0,
|
|
60842
|
+
avg_cycle_time: item.avg_cycle_time || 0,
|
|
60843
|
+
ideal_cycle_time: item.ideal_cycle_time || void 0,
|
|
60844
|
+
trend: item.trend_score === 1 ? 2 : 0,
|
|
60845
|
+
predicted_output: item.ideal_output || 0,
|
|
60846
|
+
efficiency: item.efficiency || 0,
|
|
60847
|
+
action_threshold: item.total_day_output || 0,
|
|
60848
|
+
monitoring_mode: item.monitoring_mode ?? void 0,
|
|
60849
|
+
idle_time: typeof item.idle_time === "number" ? item.idle_time : Number(item.idle_time),
|
|
60850
|
+
idle_time_hourly: item.idle_time_hourly ?? null,
|
|
60851
|
+
shift_start: item.shift_start ?? void 0,
|
|
60852
|
+
shift_end: item.shift_end ?? void 0,
|
|
60853
|
+
assembly_enabled: item.assembly_enabled ?? false,
|
|
60854
|
+
video_grid_metric_mode: normalizeVideoGridMetricMode(
|
|
60855
|
+
item.video_grid_metric_mode,
|
|
60856
|
+
item.assembly_enabled ?? false
|
|
60857
|
+
),
|
|
60858
|
+
action_type: actionType,
|
|
60859
|
+
action_family: actionFamily,
|
|
60860
|
+
action_display_name: getActionDisplayName({
|
|
60861
|
+
displayName: item.action_display_name,
|
|
60862
|
+
actionFamily: item.action_family,
|
|
60863
|
+
actionType: item.action_type,
|
|
60864
|
+
actionName: item.action_name
|
|
60865
|
+
}),
|
|
60866
|
+
recent_flow_percent: item.recent_flow_percent ?? null,
|
|
60867
|
+
recent_flow_window_minutes: item.recent_flow_window_minutes ?? null,
|
|
60868
|
+
recent_flow_effective_end_at: item.recent_flow_effective_end_at ?? null,
|
|
60869
|
+
recent_flow_computed_at: item.recent_flow_computed_at ?? null,
|
|
60870
|
+
scheduled_break_active: item.scheduled_break_active ?? false,
|
|
60871
|
+
incoming_wip_current: item.incoming_wip_current ?? null,
|
|
60872
|
+
incoming_wip_effective_at: item.incoming_wip_effective_at ?? null,
|
|
60873
|
+
incoming_wip_buffer_name: item.incoming_wip_buffer_name ?? null,
|
|
60874
|
+
show_exclamation: item.show_exclamation ?? void 0
|
|
60875
|
+
};
|
|
60876
|
+
workspaceMetricsStore.setOverview(metric);
|
|
60877
|
+
return metric;
|
|
60878
|
+
}).sort(sortWorkspaceMetrics);
|
|
60879
|
+
var transformActiveBreaks = (activeBreaksByLine) => {
|
|
60880
|
+
if (!activeBreaksByLine) return [];
|
|
60881
|
+
return Object.values(activeBreaksByLine).flat().map((item) => ({
|
|
60882
|
+
lineId: item.line_id,
|
|
60883
|
+
shiftName: item.shift_name || "",
|
|
60884
|
+
startTime: item.start_time,
|
|
60885
|
+
endTime: item.end_time,
|
|
60886
|
+
duration: item.duration || 0,
|
|
60887
|
+
remarks: item.remarks || "",
|
|
60888
|
+
elapsedMinutes: item.elapsed_minutes || 0,
|
|
60889
|
+
remainingMinutes: item.remaining_minutes || 0
|
|
60890
|
+
})).sort((left, right) => {
|
|
60891
|
+
if (left.lineId !== right.lineId) return left.lineId.localeCompare(right.lineId);
|
|
60892
|
+
if (left.shiftName !== right.shiftName) return left.shiftName.localeCompare(right.shiftName);
|
|
60893
|
+
return left.startTime.localeCompare(right.startTime);
|
|
60894
|
+
});
|
|
60895
|
+
};
|
|
60896
|
+
var createEmptyState = () => ({
|
|
60897
|
+
requestKey: null,
|
|
60898
|
+
resolvedScope: [],
|
|
60899
|
+
scopeKey: null,
|
|
60900
|
+
lines: [],
|
|
60901
|
+
workspaceMetrics: [],
|
|
60902
|
+
lineMetrics: [],
|
|
60903
|
+
kpiTrend: null,
|
|
60904
|
+
activeBreaks: [],
|
|
60905
|
+
videoStreamsByWorkspaceId: {},
|
|
60906
|
+
efficiencyLegend: null,
|
|
60907
|
+
metadata: {}
|
|
60908
|
+
});
|
|
60909
|
+
var normalizeMetadata = (metadata) => ({
|
|
60910
|
+
hasFlowBuffers: Boolean(metadata?.has_flow_buffers),
|
|
60911
|
+
idleTimeVlmByLine: metadata?.idle_time_vlm_by_line ?? {},
|
|
60912
|
+
generatedAt: metadata?.generated_at,
|
|
60913
|
+
cacheStatus: metadata?.cache_status,
|
|
60914
|
+
warnings: metadata?.warnings ?? []
|
|
60915
|
+
});
|
|
60916
|
+
var useLiveMonitorBootstrap = ({
|
|
60917
|
+
lineIds,
|
|
60918
|
+
companyId,
|
|
60919
|
+
enabled = true
|
|
60920
|
+
}) => {
|
|
60921
|
+
const supabase = useSupabase();
|
|
60922
|
+
const entityConfig = useEntityConfig();
|
|
60923
|
+
const { hydrateFromBackend } = useIdleTimeVlmConfig();
|
|
60924
|
+
const resolvedCompanyId = companyId || entityConfig?.companyId;
|
|
60925
|
+
const rawLineIdsKey = (lineIds || []).filter(Boolean).join(",");
|
|
60926
|
+
const normalizedLineIds = useMemo(
|
|
60927
|
+
() => Array.from(new Set(rawLineIdsKey ? rawLineIdsKey.split(",") : [])),
|
|
60928
|
+
[rawLineIdsKey]
|
|
60929
|
+
);
|
|
60930
|
+
const requestKey = useMemo(
|
|
60931
|
+
() => normalizedLineIds.slice().sort().join(","),
|
|
60932
|
+
[normalizedLineIds]
|
|
60933
|
+
);
|
|
60934
|
+
const [state, setState] = useState(() => createEmptyState());
|
|
60935
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
60936
|
+
const [error, setError] = useState(null);
|
|
60937
|
+
const activeRequestIdRef = useRef(0);
|
|
60938
|
+
const fetchBootstrap = useCallback(async (force = false) => {
|
|
60939
|
+
if (!enabled || !supabase || !resolvedCompanyId || normalizedLineIds.length === 0) {
|
|
60940
|
+
return;
|
|
60941
|
+
}
|
|
60942
|
+
const requestId = ++activeRequestIdRef.current;
|
|
60943
|
+
setIsLoading(true);
|
|
60944
|
+
setError(null);
|
|
60945
|
+
try {
|
|
60946
|
+
const searchParams = new URLSearchParams();
|
|
60947
|
+
searchParams.set("company_id", resolvedCompanyId);
|
|
60948
|
+
searchParams.set("line_ids", normalizedLineIds.join(","));
|
|
60949
|
+
if (force) {
|
|
60950
|
+
searchParams.set("force_refresh", "true");
|
|
60951
|
+
}
|
|
60952
|
+
const response = await fetchBackendJson(
|
|
60953
|
+
supabase,
|
|
60954
|
+
`/api/dashboard/monitor-bootstrap?${searchParams.toString()}`,
|
|
60955
|
+
{
|
|
60956
|
+
method: "GET",
|
|
60957
|
+
timeoutMs: 2e4,
|
|
60958
|
+
retries: 0,
|
|
60959
|
+
dedupeKey: `monitor-bootstrap::${requestKey}::${force ? "force" : "cached"}`
|
|
60960
|
+
}
|
|
60961
|
+
);
|
|
60962
|
+
if (requestId !== activeRequestIdRef.current) {
|
|
60963
|
+
return;
|
|
60964
|
+
}
|
|
60965
|
+
const workspaceMetrics = transformWorkspaceMetrics(response.workspace_metrics || []);
|
|
60966
|
+
const activeBreaks = transformActiveBreaks(response.active_breaks_by_line);
|
|
60967
|
+
const metadata = normalizeMetadata(response.metadata);
|
|
60968
|
+
if (metadata.idleTimeVlmByLine) {
|
|
60969
|
+
hydrateFromBackend(metadata.idleTimeVlmByLine);
|
|
60970
|
+
}
|
|
60971
|
+
setState({
|
|
60972
|
+
requestKey,
|
|
60973
|
+
resolvedScope: response.resolved_scope || [],
|
|
60974
|
+
scopeKey: response.scope_key || null,
|
|
60975
|
+
lines: response.lines || [],
|
|
60976
|
+
workspaceMetrics,
|
|
60977
|
+
lineMetrics: response.line_metrics || [],
|
|
60978
|
+
kpiTrend: response.kpi_trend || null,
|
|
60979
|
+
activeBreaks,
|
|
60980
|
+
videoStreamsByWorkspaceId: response.video_streams_by_workspace_id || {},
|
|
60981
|
+
efficiencyLegend: response.efficiency_legend || null,
|
|
60982
|
+
metadata
|
|
60983
|
+
});
|
|
60984
|
+
} catch (fetchError) {
|
|
60985
|
+
if (requestId !== activeRequestIdRef.current) {
|
|
60986
|
+
return;
|
|
60987
|
+
}
|
|
60988
|
+
setError(fetchError instanceof Error ? fetchError : new Error("Failed to load live monitor bootstrap"));
|
|
60989
|
+
} finally {
|
|
60990
|
+
if (requestId === activeRequestIdRef.current) {
|
|
60991
|
+
setIsLoading(false);
|
|
60992
|
+
}
|
|
60993
|
+
}
|
|
60994
|
+
}, [enabled, supabase, resolvedCompanyId, normalizedLineIds, requestKey, hydrateFromBackend]);
|
|
60995
|
+
useEffect(() => {
|
|
60996
|
+
if (!enabled) {
|
|
60997
|
+
setIsLoading(false);
|
|
60998
|
+
return;
|
|
60999
|
+
}
|
|
61000
|
+
if (!resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
61001
|
+
setState(createEmptyState());
|
|
61002
|
+
setIsLoading(false);
|
|
61003
|
+
setError(null);
|
|
61004
|
+
return;
|
|
61005
|
+
}
|
|
61006
|
+
void fetchBootstrap(false);
|
|
61007
|
+
}, [enabled, resolvedCompanyId, normalizedLineIds, supabase, fetchBootstrap]);
|
|
61008
|
+
useEffect(() => {
|
|
61009
|
+
if (!enabled || !resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
61010
|
+
return void 0;
|
|
61011
|
+
}
|
|
61012
|
+
let intervalId = null;
|
|
61013
|
+
let timeoutId = null;
|
|
61014
|
+
const runMinuteTick = () => {
|
|
61015
|
+
void fetchBootstrap(true);
|
|
61016
|
+
};
|
|
61017
|
+
const startInterval = () => {
|
|
61018
|
+
runMinuteTick();
|
|
61019
|
+
intervalId = window.setInterval(runMinuteTick, 6e4);
|
|
61020
|
+
};
|
|
61021
|
+
const msUntilNextMinute = (() => {
|
|
61022
|
+
const remainder = Date.now() % 6e4;
|
|
61023
|
+
return remainder === 0 ? 6e4 : 6e4 - remainder;
|
|
61024
|
+
})();
|
|
61025
|
+
timeoutId = window.setTimeout(startInterval, msUntilNextMinute);
|
|
61026
|
+
return () => {
|
|
61027
|
+
if (timeoutId !== null) {
|
|
61028
|
+
window.clearTimeout(timeoutId);
|
|
61029
|
+
}
|
|
61030
|
+
if (intervalId !== null) {
|
|
61031
|
+
window.clearInterval(intervalId);
|
|
61032
|
+
}
|
|
61033
|
+
};
|
|
61034
|
+
}, [enabled, resolvedCompanyId, normalizedLineIds, supabase, fetchBootstrap]);
|
|
61035
|
+
const isCurrentScopeResolved = state.requestKey === requestKey;
|
|
61036
|
+
return {
|
|
61037
|
+
resolvedScope: state.resolvedScope,
|
|
61038
|
+
scopeKey: state.scopeKey,
|
|
61039
|
+
lines: state.lines,
|
|
61040
|
+
workspaceMetrics: state.workspaceMetrics,
|
|
61041
|
+
lineMetrics: state.lineMetrics,
|
|
61042
|
+
kpiTrend: state.kpiTrend,
|
|
61043
|
+
activeBreaks: state.activeBreaks,
|
|
61044
|
+
videoStreamsByWorkspaceId: state.videoStreamsByWorkspaceId,
|
|
61045
|
+
efficiencyLegend: state.efficiencyLegend,
|
|
61046
|
+
metadata: state.metadata,
|
|
61047
|
+
isLoading: enabled ? isLoading || !isCurrentScopeResolved : false,
|
|
61048
|
+
isCurrentScopeResolved,
|
|
61049
|
+
error,
|
|
61050
|
+
refetch: () => fetchBootstrap(true)
|
|
61051
|
+
};
|
|
61052
|
+
};
|
|
61053
|
+
|
|
61054
|
+
// src/lib/utils/liveMonitorBootstrap.ts
|
|
61055
|
+
var toNumber3 = (value) => {
|
|
61056
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
61057
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
61058
|
+
const parsed = Number(value);
|
|
61059
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
61060
|
+
}
|
|
61061
|
+
return 0;
|
|
61062
|
+
};
|
|
61063
|
+
var normalizeNullableNumber = (value) => {
|
|
61064
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
61065
|
+
return toNumber3(value);
|
|
61066
|
+
};
|
|
61067
|
+
var getLiveMonitorBootstrapMode = () => {
|
|
61068
|
+
const rawMode = (process.env.NEXT_PUBLIC_MONITOR_BOOTSTRAP_MODE || "").trim().toLowerCase();
|
|
61069
|
+
if (rawMode === "legacy" || rawMode === "shadow" || rawMode === "bootstrap") {
|
|
61070
|
+
return rawMode;
|
|
61071
|
+
}
|
|
61072
|
+
return "bootstrap";
|
|
61073
|
+
};
|
|
61074
|
+
var normalizeMonitorShadowSnapshot = (input) => {
|
|
61075
|
+
const sortedSelectedLineIds = Array.from(new Set((input.selectedLineIds || []).filter(Boolean))).sort();
|
|
61076
|
+
const resolvedScope = (input.resolvedScope || []).filter((entry) => entry?.line_id && entry?.date && entry?.shift_id !== void 0 && entry?.shift_id !== null).map((entry) => ({
|
|
61077
|
+
line_id: entry.line_id,
|
|
61078
|
+
date: entry.date,
|
|
61079
|
+
shift_id: entry.shift_id
|
|
61080
|
+
})).sort((left, right) => {
|
|
61081
|
+
if (left.line_id !== right.line_id) return left.line_id.localeCompare(right.line_id);
|
|
61082
|
+
if (left.date !== right.date) return left.date.localeCompare(right.date);
|
|
61083
|
+
return left.shift_id - right.shift_id;
|
|
61084
|
+
});
|
|
61085
|
+
const lines = (input.lines || []).filter((entry) => entry?.line_id).map((entry) => ({
|
|
61086
|
+
line_id: entry.line_id,
|
|
61087
|
+
line_name: entry.line_name || "Unknown Line"
|
|
61088
|
+
})).sort((left, right) => left.line_id.localeCompare(right.line_id));
|
|
61089
|
+
const workspaces = (input.workspaces || []).map((workspace) => {
|
|
61090
|
+
const workspaceId = workspace.workspace_uuid || null;
|
|
61091
|
+
const stream = workspaceId ? input.videoStreamsByWorkspaceId?.[workspaceId] || null : null;
|
|
61092
|
+
return {
|
|
61093
|
+
workspace_id: workspaceId,
|
|
61094
|
+
line_id: workspace.line_id,
|
|
61095
|
+
workspace_name: workspace.workspace_name,
|
|
61096
|
+
display_name: workspace.displayName || null,
|
|
61097
|
+
efficiency: toNumber3(workspace.efficiency),
|
|
61098
|
+
trend: toNumber3(workspace.trend),
|
|
61099
|
+
show_exclamation: Boolean(workspace.show_exclamation),
|
|
61100
|
+
scheduled_break_active: Boolean(workspace.scheduled_break_active),
|
|
61101
|
+
action_count: toNumber3(workspace.action_count),
|
|
61102
|
+
action_threshold: toNumber3(workspace.action_threshold),
|
|
61103
|
+
predicted_output: toNumber3(workspace.predicted_output),
|
|
61104
|
+
avg_cycle_time: toNumber3(workspace.avg_cycle_time),
|
|
61105
|
+
pph: toNumber3(workspace.pph),
|
|
61106
|
+
recent_flow_percent: normalizeNullableNumber(workspace.recent_flow_percent),
|
|
61107
|
+
incoming_wip_current: normalizeNullableNumber(workspace.incoming_wip_current),
|
|
61108
|
+
video_stream: stream ? {
|
|
61109
|
+
workspace_id: stream.workspace_id,
|
|
61110
|
+
camera_uuid: stream.camera_uuid,
|
|
61111
|
+
stream_camera_uuid: stream.stream_camera_uuid,
|
|
61112
|
+
hls_url: stream.hls_url,
|
|
61113
|
+
crop: stream.crop
|
|
61114
|
+
} : null
|
|
61115
|
+
};
|
|
61116
|
+
}).sort((left, right) => {
|
|
61117
|
+
if (left.line_id !== right.line_id) return left.line_id.localeCompare(right.line_id);
|
|
61118
|
+
return left.workspace_name.localeCompare(right.workspace_name, void 0, { numeric: true });
|
|
61119
|
+
});
|
|
61120
|
+
const activeBreaks = (input.activeBreaks || []).map((activeBreak) => ({
|
|
61121
|
+
lineId: activeBreak.lineId,
|
|
61122
|
+
shiftName: activeBreak.shiftName,
|
|
61123
|
+
startTime: activeBreak.startTime,
|
|
61124
|
+
endTime: activeBreak.endTime,
|
|
61125
|
+
remainingMinutes: toNumber3(activeBreak.remainingMinutes)
|
|
61126
|
+
})).sort((left, right) => {
|
|
61127
|
+
if (left.lineId !== right.lineId) return left.lineId.localeCompare(right.lineId);
|
|
61128
|
+
if (left.shiftName !== right.shiftName) return left.shiftName.localeCompare(right.shiftName);
|
|
61129
|
+
return left.startTime.localeCompare(right.startTime);
|
|
61130
|
+
});
|
|
61131
|
+
return {
|
|
61132
|
+
selectedLineIds: sortedSelectedLineIds,
|
|
61133
|
+
resolvedScope,
|
|
61134
|
+
lines,
|
|
61135
|
+
workspaces,
|
|
61136
|
+
activeBreaks,
|
|
61137
|
+
kpis: input.kpis || null,
|
|
61138
|
+
kpiTrend: input.kpiTrend || null,
|
|
61139
|
+
efficiencyLegend: input.efficiencyLegend || null
|
|
61140
|
+
};
|
|
61141
|
+
};
|
|
61142
|
+
var diffMonitorShadowSnapshots = (legacySnapshot, bootstrapSnapshot) => {
|
|
61143
|
+
const mismatches = [];
|
|
61144
|
+
const compareSection = (section) => {
|
|
61145
|
+
const legacyValue = legacySnapshot[section];
|
|
61146
|
+
const bootstrapValue = bootstrapSnapshot[section];
|
|
61147
|
+
if (JSON.stringify(legacyValue) !== JSON.stringify(bootstrapValue)) {
|
|
61148
|
+
mismatches.push({
|
|
61149
|
+
section,
|
|
61150
|
+
legacy: legacyValue,
|
|
61151
|
+
bootstrap: bootstrapValue
|
|
61152
|
+
});
|
|
61153
|
+
}
|
|
61154
|
+
};
|
|
61155
|
+
compareSection("selectedLineIds");
|
|
61156
|
+
compareSection("resolvedScope");
|
|
61157
|
+
compareSection("lines");
|
|
61158
|
+
compareSection("workspaces");
|
|
61159
|
+
compareSection("activeBreaks");
|
|
61160
|
+
compareSection("kpis");
|
|
61161
|
+
compareSection("kpiTrend");
|
|
61162
|
+
compareSection("efficiencyLegend");
|
|
61163
|
+
return mismatches;
|
|
61164
|
+
};
|
|
60705
61165
|
|
|
60706
61166
|
// src/lib/services/notificationService.ts
|
|
60707
61167
|
var API_BASE_URL = process.env.NEXT_PUBLIC_BACKEND_URL;
|
|
@@ -60843,7 +61303,10 @@ var logDebug3 = (...args) => {
|
|
|
60843
61303
|
if (!DEBUG_DASHBOARD_LOGS3) return;
|
|
60844
61304
|
console.log(...args);
|
|
60845
61305
|
};
|
|
61306
|
+
var EMPTY_LINE_IDS = [];
|
|
61307
|
+
var EMPTY_WORKSPACES = [];
|
|
60846
61308
|
var LoadingPageCmp = LoadingPage_default;
|
|
61309
|
+
var LoadingOverlayCmp = LoadingOverlay_default;
|
|
60847
61310
|
function HomeView({
|
|
60848
61311
|
defaultLineId,
|
|
60849
61312
|
factoryViewId,
|
|
@@ -60991,6 +61454,7 @@ function HomeView({
|
|
|
60991
61454
|
return createNotificationService(supabaseClient);
|
|
60992
61455
|
}, [supabaseClient]);
|
|
60993
61456
|
const [bottleneckNotification, setBottleneckNotification] = useState(null);
|
|
61457
|
+
const showBottleneckNotificationRef = useRef(null);
|
|
60994
61458
|
const [bottleneckModalOpen, setBottleneckModalOpen] = useState(false);
|
|
60995
61459
|
const [bottleneckModalData, setBottleneckModalData] = useState(null);
|
|
60996
61460
|
const [diagnosisModalOpen, setDiagnosisModalOpen] = useState(false);
|
|
@@ -61001,6 +61465,11 @@ function HomeView({
|
|
|
61001
61465
|
dashboardConfig?.shiftConfig
|
|
61002
61466
|
);
|
|
61003
61467
|
const shouldEnableMetricsFetch = authStatus === "ready";
|
|
61468
|
+
const liveMonitorMode = useMemo(() => getLiveMonitorBootstrapMode(), []);
|
|
61469
|
+
const isLegacyMonitorMode = liveMonitorMode === "legacy";
|
|
61470
|
+
const isShadowMonitorMode = liveMonitorMode === "shadow";
|
|
61471
|
+
const isBootstrapMonitorMode = liveMonitorMode === "bootstrap";
|
|
61472
|
+
const lastShadowMismatchSignatureRef = useRef(null);
|
|
61004
61473
|
const handleLineMetricsUpdate = useCallback(() => {
|
|
61005
61474
|
if (trendRefreshTimerRef.current) {
|
|
61006
61475
|
window.clearTimeout(trendRefreshTimerRef.current);
|
|
@@ -61016,45 +61485,24 @@ function HomeView({
|
|
|
61016
61485
|
}
|
|
61017
61486
|
}, []);
|
|
61018
61487
|
const {
|
|
61019
|
-
workspaceMetrics,
|
|
61020
|
-
lineMetrics,
|
|
61021
|
-
efficiencyLegend,
|
|
61022
|
-
metadata:
|
|
61023
|
-
isLoading:
|
|
61024
|
-
|
|
61025
|
-
|
|
61488
|
+
workspaceMetrics: legacyWorkspaceMetrics,
|
|
61489
|
+
lineMetrics: legacyLineMetrics,
|
|
61490
|
+
efficiencyLegend: legacyEfficiencyLegend,
|
|
61491
|
+
metadata: legacyMetricsMetadata,
|
|
61492
|
+
isLoading: legacyMetricsLoading,
|
|
61493
|
+
isCurrentScopeResolved: legacyIsCurrentScopeResolved,
|
|
61494
|
+
error: legacyMetricsError,
|
|
61495
|
+
refetch: refetchLegacyMetrics
|
|
61026
61496
|
} = useDashboardMetrics({
|
|
61027
61497
|
lineId: metricsScopeLineId,
|
|
61028
61498
|
lineIds: selectedLineIds,
|
|
61029
61499
|
onLineMetricsUpdate: handleLineMetricsUpdate,
|
|
61030
61500
|
userAccessibleLineIds: visibleLineIds,
|
|
61031
|
-
|
|
61032
|
-
enabled: shouldEnableMetricsFetch
|
|
61501
|
+
enabled: shouldEnableMetricsFetch && !isBootstrapMonitorMode
|
|
61033
61502
|
});
|
|
61034
|
-
const
|
|
61035
|
-
|
|
61036
|
-
|
|
61037
|
-
if (!workspace.displayName) {
|
|
61038
|
-
return;
|
|
61039
|
-
}
|
|
61040
|
-
nextDisplayNames[`${workspace.line_id}_${workspace.workspace_name}`] = workspace.displayName;
|
|
61041
|
-
});
|
|
61042
|
-
return nextDisplayNames;
|
|
61043
|
-
}, [workspaceMetrics]);
|
|
61044
|
-
useEffect(() => {
|
|
61045
|
-
workspaceMetrics.forEach((workspace) => {
|
|
61046
|
-
if (!workspace.displayName) {
|
|
61047
|
-
return;
|
|
61048
|
-
}
|
|
61049
|
-
upsertWorkspaceDisplayNameInCache({
|
|
61050
|
-
lineId: workspace.line_id,
|
|
61051
|
-
workspaceId: workspace.workspace_name,
|
|
61052
|
-
displayName: workspace.displayName
|
|
61053
|
-
});
|
|
61054
|
-
});
|
|
61055
|
-
}, [workspaceMetrics]);
|
|
61056
|
-
const trendGroups = useMemo(() => {
|
|
61057
|
-
const lineMetricsRows = lineMetrics || [];
|
|
61503
|
+
const legacyTrendGroups = useMemo(() => {
|
|
61504
|
+
if (isBootstrapMonitorMode) return null;
|
|
61505
|
+
const lineMetricsRows = legacyLineMetrics || [];
|
|
61058
61506
|
if (!lineMetricsRows.length) return null;
|
|
61059
61507
|
if (selectedLineIds.length > 1) {
|
|
61060
61508
|
const rowsForLines = lineMetricsRows.filter((row2) => selectedLineIdSet.has(row2?.line_id));
|
|
@@ -61080,7 +61528,7 @@ function HomeView({
|
|
|
61080
61528
|
shiftId: group.shiftId
|
|
61081
61529
|
}));
|
|
61082
61530
|
}
|
|
61083
|
-
const row = lineMetricsRows.find((
|
|
61531
|
+
const row = lineMetricsRows.find((candidate) => candidate?.line_id === primarySelectedLineId);
|
|
61084
61532
|
if (!row?.date || row?.shift_id === void 0 || row?.shift_id === null) {
|
|
61085
61533
|
return null;
|
|
61086
61534
|
}
|
|
@@ -61089,69 +61537,115 @@ function HomeView({
|
|
|
61089
61537
|
date: row.date,
|
|
61090
61538
|
shiftId: row.shift_id
|
|
61091
61539
|
}];
|
|
61092
|
-
}, [
|
|
61093
|
-
const
|
|
61094
|
-
if (!
|
|
61540
|
+
}, [isBootstrapMonitorMode, legacyLineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
61541
|
+
const legacyTrendOptions = useMemo(() => {
|
|
61542
|
+
if (isBootstrapMonitorMode || !legacyTrendGroups || !userCompanyId) return null;
|
|
61095
61543
|
return {
|
|
61096
|
-
groups:
|
|
61544
|
+
groups: legacyTrendGroups,
|
|
61097
61545
|
companyId: userCompanyId,
|
|
61098
61546
|
refreshKey: trendRefreshKey,
|
|
61099
61547
|
forceRefresh: trendRefreshKey > 0
|
|
61100
61548
|
};
|
|
61101
|
-
}, [
|
|
61102
|
-
const { trend:
|
|
61103
|
-
const
|
|
61549
|
+
}, [isBootstrapMonitorMode, legacyTrendGroups, userCompanyId, trendRefreshKey]);
|
|
61550
|
+
const { trend: legacyKpiTrend } = useKpiTrends(legacyTrendOptions);
|
|
61551
|
+
const bootstrapMonitor = useLiveMonitorBootstrap({
|
|
61552
|
+
lineIds: selectedLineIds,
|
|
61553
|
+
companyId: userCompanyId,
|
|
61554
|
+
enabled: shouldEnableMetricsFetch && !isLegacyMonitorMode
|
|
61555
|
+
});
|
|
61556
|
+
const currentWorkspaceMetrics = isBootstrapMonitorMode ? bootstrapMonitor.workspaceMetrics : legacyWorkspaceMetrics;
|
|
61557
|
+
const currentLineMetrics = isBootstrapMonitorMode ? bootstrapMonitor.lineMetrics : legacyLineMetrics;
|
|
61558
|
+
const currentEfficiencyLegend = isBootstrapMonitorMode ? bootstrapMonitor.efficiencyLegend : legacyEfficiencyLegend;
|
|
61559
|
+
const currentMetricsMetadata = isBootstrapMonitorMode ? bootstrapMonitor.metadata : legacyMetricsMetadata;
|
|
61560
|
+
const currentMetricsLoading = isBootstrapMonitorMode ? bootstrapMonitor.isLoading : legacyMetricsLoading;
|
|
61561
|
+
const currentIsCurrentScopeResolved = isBootstrapMonitorMode ? bootstrapMonitor.isCurrentScopeResolved : legacyIsCurrentScopeResolved;
|
|
61562
|
+
const currentMetricsError = isBootstrapMonitorMode ? bootstrapMonitor.error : legacyMetricsError;
|
|
61563
|
+
const currentRefetchMetrics = isBootstrapMonitorMode ? bootstrapMonitor.refetch : refetchLegacyMetrics;
|
|
61564
|
+
const metricsDisplayNames = useMemo(() => {
|
|
61565
|
+
const nextDisplayNames = {};
|
|
61566
|
+
currentWorkspaceMetrics.forEach((workspace) => {
|
|
61567
|
+
if (!workspace.displayName) {
|
|
61568
|
+
return;
|
|
61569
|
+
}
|
|
61570
|
+
nextDisplayNames[`${workspace.line_id}_${workspace.workspace_name}`] = workspace.displayName;
|
|
61571
|
+
});
|
|
61572
|
+
return nextDisplayNames;
|
|
61573
|
+
}, [currentWorkspaceMetrics]);
|
|
61574
|
+
useEffect(() => {
|
|
61575
|
+
currentWorkspaceMetrics.forEach((workspace) => {
|
|
61576
|
+
if (!workspace.displayName) {
|
|
61577
|
+
return;
|
|
61578
|
+
}
|
|
61579
|
+
upsertWorkspaceDisplayNameInCache({
|
|
61580
|
+
lineId: workspace.line_id,
|
|
61581
|
+
workspaceId: workspace.workspace_name,
|
|
61582
|
+
displayName: workspace.displayName
|
|
61583
|
+
});
|
|
61584
|
+
});
|
|
61585
|
+
}, [currentWorkspaceMetrics]);
|
|
61586
|
+
const hasFlowBuffers = Boolean(currentMetricsMetadata?.hasFlowBuffers);
|
|
61104
61587
|
useEffect(() => {
|
|
61105
|
-
const sample =
|
|
61588
|
+
const sample = currentWorkspaceMetrics.slice(0, 3).map((workspace) => ({
|
|
61106
61589
|
id: workspace.workspace_uuid || workspace.workspace_name,
|
|
61107
61590
|
efficiency: workspace.efficiency,
|
|
61108
61591
|
trend: workspace.trend,
|
|
61109
61592
|
lineId: workspace.line_id
|
|
61110
61593
|
}));
|
|
61111
61594
|
logDebug3("[HomeView] workspaceMetrics update:", {
|
|
61112
|
-
count:
|
|
61113
|
-
isLoading:
|
|
61114
|
-
error:
|
|
61595
|
+
count: currentWorkspaceMetrics.length,
|
|
61596
|
+
isLoading: currentMetricsLoading,
|
|
61597
|
+
error: currentMetricsError?.message,
|
|
61115
61598
|
sample
|
|
61116
61599
|
});
|
|
61117
|
-
}, [
|
|
61118
|
-
const
|
|
61119
|
-
const lineMetricsRows =
|
|
61600
|
+
}, [currentWorkspaceMetrics, currentMetricsLoading, currentMetricsError]);
|
|
61601
|
+
const buildDisplayKpis = useCallback((sourceLineMetrics, sourceIsLoading, sourceKpiTrend) => {
|
|
61602
|
+
const lineMetricsRows = sourceLineMetrics || [];
|
|
61603
|
+
let baseKpis = null;
|
|
61120
61604
|
if (selectedLineIds.length > 1) {
|
|
61121
|
-
const rowsForSelectedLines = lineMetricsRows.filter((
|
|
61122
|
-
if (
|
|
61123
|
-
|
|
61124
|
-
}
|
|
61125
|
-
|
|
61126
|
-
|
|
61127
|
-
|
|
61128
|
-
|
|
61129
|
-
|
|
61130
|
-
|
|
61131
|
-
|
|
61132
|
-
|
|
61133
|
-
if (!
|
|
61134
|
-
|
|
61605
|
+
const rowsForSelectedLines = lineMetricsRows.filter((row) => selectedLineIdSet.has(row?.line_id));
|
|
61606
|
+
if (sourceIsLoading && rowsForSelectedLines.length === 0) return null;
|
|
61607
|
+
baseKpis = aggregateKPIsFromLineMetricsRows(rowsForSelectedLines);
|
|
61608
|
+
} else {
|
|
61609
|
+
const row = lineMetricsRows.find((candidate) => candidate?.line_id === primarySelectedLineId);
|
|
61610
|
+
if (!row) {
|
|
61611
|
+
if (sourceIsLoading) return null;
|
|
61612
|
+
baseKpis = buildKPIsFromLineMetricsRow(null);
|
|
61613
|
+
} else {
|
|
61614
|
+
baseKpis = buildKPIsFromLineMetricsRow(row);
|
|
61615
|
+
}
|
|
61616
|
+
}
|
|
61617
|
+
if (!baseKpis || !sourceKpiTrend) {
|
|
61618
|
+
return baseKpis;
|
|
61619
|
+
}
|
|
61135
61620
|
return {
|
|
61136
|
-
...
|
|
61621
|
+
...baseKpis,
|
|
61137
61622
|
efficiency: {
|
|
61138
|
-
...
|
|
61139
|
-
change:
|
|
61623
|
+
...baseKpis.efficiency,
|
|
61624
|
+
change: sourceKpiTrend.efficiency?.delta_pp ?? baseKpis.efficiency.change
|
|
61140
61625
|
},
|
|
61141
61626
|
outputProgress: {
|
|
61142
|
-
...
|
|
61143
|
-
change:
|
|
61627
|
+
...baseKpis.outputProgress,
|
|
61628
|
+
change: sourceKpiTrend.outputProgress?.delta_pp ?? baseKpis.outputProgress.change
|
|
61144
61629
|
},
|
|
61145
61630
|
underperformingWorkers: {
|
|
61146
|
-
...
|
|
61147
|
-
change:
|
|
61631
|
+
...baseKpis.underperformingWorkers,
|
|
61632
|
+
change: sourceKpiTrend.underperformingWorkers?.delta_count ?? baseKpis.underperformingWorkers.change
|
|
61148
61633
|
},
|
|
61149
61634
|
avgCycleTime: {
|
|
61150
|
-
...
|
|
61151
|
-
change:
|
|
61635
|
+
...baseKpis.avgCycleTime,
|
|
61636
|
+
change: sourceKpiTrend.avgCycleTime?.delta_seconds ?? baseKpis.avgCycleTime.change
|
|
61152
61637
|
}
|
|
61153
61638
|
};
|
|
61154
|
-
}, [
|
|
61639
|
+
}, [primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
61640
|
+
const legacyKpisWithTrend = useMemo(
|
|
61641
|
+
() => buildDisplayKpis(legacyLineMetrics, legacyMetricsLoading, legacyKpiTrend),
|
|
61642
|
+
[buildDisplayKpis, legacyLineMetrics, legacyMetricsLoading, legacyKpiTrend]
|
|
61643
|
+
);
|
|
61644
|
+
const bootstrapKpisWithTrend = useMemo(
|
|
61645
|
+
() => buildDisplayKpis(bootstrapMonitor.lineMetrics, bootstrapMonitor.isLoading, bootstrapMonitor.kpiTrend),
|
|
61646
|
+
[buildDisplayKpis, bootstrapMonitor.lineMetrics, bootstrapMonitor.isLoading, bootstrapMonitor.kpiTrend]
|
|
61647
|
+
);
|
|
61648
|
+
const currentKpisWithTrend = isBootstrapMonitorMode ? bootstrapKpisWithTrend : legacyKpisWithTrend;
|
|
61155
61649
|
const selectedLineMeta = useMemo(
|
|
61156
61650
|
() => selectedLineIds.length === 1 ? dbLines.find((line) => line.id === primarySelectedLineId) : void 0,
|
|
61157
61651
|
[dbLines, primarySelectedLineId, selectedLineIds.length]
|
|
@@ -61160,40 +61654,121 @@ function HomeView({
|
|
|
61160
61654
|
const isUptimeMode = selectedMonitoringMode === "uptime";
|
|
61161
61655
|
const averageIdleTimeSeconds = useMemo(() => {
|
|
61162
61656
|
if (!isUptimeMode) return null;
|
|
61163
|
-
const targetWorkspaces =
|
|
61657
|
+
const targetWorkspaces = currentWorkspaceMetrics.filter((ws) => ws.line_id === primarySelectedLineId);
|
|
61164
61658
|
const idleValues = targetWorkspaces.map((ws) => ws.idle_time).filter((value) => Number.isFinite(value));
|
|
61165
61659
|
if (idleValues.length === 0) return 0;
|
|
61166
61660
|
const totalIdle = idleValues.reduce((sum, value) => sum + value, 0);
|
|
61167
61661
|
return totalIdle / idleValues.length;
|
|
61168
|
-
}, [isUptimeMode, primarySelectedLineId,
|
|
61662
|
+
}, [isUptimeMode, primarySelectedLineId, currentWorkspaceMetrics]);
|
|
61169
61663
|
const {
|
|
61170
|
-
activeBreaks:
|
|
61171
|
-
isLoading:
|
|
61172
|
-
error:
|
|
61173
|
-
} = useActiveBreaks(visibleLineIds);
|
|
61174
|
-
const
|
|
61664
|
+
activeBreaks: legacyAllActiveBreaks,
|
|
61665
|
+
isLoading: legacyBreaksLoading,
|
|
61666
|
+
error: legacyBreaksError
|
|
61667
|
+
} = useActiveBreaks(isBootstrapMonitorMode ? EMPTY_LINE_IDS : visibleLineIds);
|
|
61668
|
+
const legacyActiveBreaks = useMemo(() => {
|
|
61175
61669
|
if (isAllLinesSelection(selectedLineIds)) {
|
|
61176
|
-
return
|
|
61670
|
+
return legacyAllActiveBreaks;
|
|
61177
61671
|
}
|
|
61178
|
-
return
|
|
61179
|
-
}, [
|
|
61672
|
+
return legacyAllActiveBreaks.filter((breakItem) => selectedLineIdSet.has(breakItem.lineId));
|
|
61673
|
+
}, [legacyAllActiveBreaks, selectedLineIdSet, selectedLineIds]);
|
|
61674
|
+
const currentActiveBreaks = isBootstrapMonitorMode ? bootstrapMonitor.activeBreaks : legacyActiveBreaks;
|
|
61675
|
+
const currentBreaksLoading = isBootstrapMonitorMode ? bootstrapMonitor.isLoading : legacyBreaksLoading;
|
|
61676
|
+
const currentBreaksError = isBootstrapMonitorMode ? bootstrapMonitor.error?.message || null : legacyBreaksError;
|
|
61180
61677
|
const activeBreakLineIds = useMemo(
|
|
61181
|
-
() => new Set(
|
|
61182
|
-
[
|
|
61678
|
+
() => new Set(currentActiveBreaks.map((breakItem) => breakItem.lineId)),
|
|
61679
|
+
[currentActiveBreaks]
|
|
61183
61680
|
);
|
|
61184
61681
|
const workspaceMetricsWithBreakState = useMemo(
|
|
61185
|
-
() =>
|
|
61682
|
+
() => currentWorkspaceMetrics.map((workspace) => ({
|
|
61186
61683
|
...workspace,
|
|
61187
61684
|
scheduled_break_active: activeBreakLineIds.has(workspace.line_id)
|
|
61188
61685
|
})),
|
|
61189
|
-
[
|
|
61686
|
+
[currentWorkspaceMetrics, activeBreakLineIds]
|
|
61190
61687
|
);
|
|
61191
61688
|
const [breakNotificationsDismissed, setBreakNotificationsDismissed] = useState(false);
|
|
61192
61689
|
useEffect(() => {
|
|
61193
|
-
if (
|
|
61690
|
+
if (currentActiveBreaks.length > 0) {
|
|
61194
61691
|
setBreakNotificationsDismissed(false);
|
|
61195
61692
|
}
|
|
61196
|
-
}, [
|
|
61693
|
+
}, [currentActiveBreaks.length]);
|
|
61694
|
+
const {
|
|
61695
|
+
streamsByWorkspaceId: legacyVideoStreamsByWorkspaceId,
|
|
61696
|
+
isLoading: legacyVideoStreamsLoading
|
|
61697
|
+
} = useWorkspaceVideoStreams(isBootstrapMonitorMode ? EMPTY_WORKSPACES : legacyWorkspaceMetrics, {
|
|
61698
|
+
lineIds: isBootstrapMonitorMode ? EMPTY_LINE_IDS : selectedLineIds
|
|
61699
|
+
});
|
|
61700
|
+
const currentVideoStreamsByWorkspaceId = isBootstrapMonitorMode ? bootstrapMonitor.videoStreamsByWorkspaceId : legacyVideoStreamsByWorkspaceId;
|
|
61701
|
+
const currentVideoStreamsLoading = isBootstrapMonitorMode ? bootstrapMonitor.isLoading : legacyVideoStreamsLoading;
|
|
61702
|
+
useEffect(() => {
|
|
61703
|
+
if (!isShadowMonitorMode) {
|
|
61704
|
+
lastShadowMismatchSignatureRef.current = null;
|
|
61705
|
+
return;
|
|
61706
|
+
}
|
|
61707
|
+
if (!shouldEnableMetricsFetch || legacyMetricsLoading || !legacyIsCurrentScopeResolved || bootstrapMonitor.isLoading || !bootstrapMonitor.isCurrentScopeResolved) {
|
|
61708
|
+
return;
|
|
61709
|
+
}
|
|
61710
|
+
const legacySnapshot = normalizeMonitorShadowSnapshot({
|
|
61711
|
+
selectedLineIds,
|
|
61712
|
+
workspaces: workspaceMetricsWithBreakState,
|
|
61713
|
+
kpis: legacyKpisWithTrend,
|
|
61714
|
+
kpiTrend: legacyKpiTrend,
|
|
61715
|
+
activeBreaks: legacyActiveBreaks,
|
|
61716
|
+
videoStreamsByWorkspaceId: legacyVideoStreamsByWorkspaceId,
|
|
61717
|
+
efficiencyLegend: legacyEfficiencyLegend
|
|
61718
|
+
});
|
|
61719
|
+
const bootstrapSnapshot = normalizeMonitorShadowSnapshot({
|
|
61720
|
+
selectedLineIds,
|
|
61721
|
+
resolvedScope: bootstrapMonitor.resolvedScope,
|
|
61722
|
+
lines: bootstrapMonitor.lines,
|
|
61723
|
+
workspaces: bootstrapMonitor.workspaceMetrics.map((workspace) => ({
|
|
61724
|
+
...workspace,
|
|
61725
|
+
scheduled_break_active: bootstrapMonitor.activeBreaks.some((activeBreak) => activeBreak.lineId === workspace.line_id)
|
|
61726
|
+
})),
|
|
61727
|
+
kpis: bootstrapKpisWithTrend,
|
|
61728
|
+
kpiTrend: bootstrapMonitor.kpiTrend,
|
|
61729
|
+
activeBreaks: bootstrapMonitor.activeBreaks,
|
|
61730
|
+
videoStreamsByWorkspaceId: bootstrapMonitor.videoStreamsByWorkspaceId,
|
|
61731
|
+
efficiencyLegend: bootstrapMonitor.efficiencyLegend
|
|
61732
|
+
});
|
|
61733
|
+
const mismatches = diffMonitorShadowSnapshots(legacySnapshot, bootstrapSnapshot);
|
|
61734
|
+
const signature = JSON.stringify(mismatches);
|
|
61735
|
+
if (mismatches.length === 0) {
|
|
61736
|
+
lastShadowMismatchSignatureRef.current = null;
|
|
61737
|
+
return;
|
|
61738
|
+
}
|
|
61739
|
+
if (lastShadowMismatchSignatureRef.current === signature) {
|
|
61740
|
+
return;
|
|
61741
|
+
}
|
|
61742
|
+
lastShadowMismatchSignatureRef.current = signature;
|
|
61743
|
+
console.error("[HomeView][monitor-shadow-mismatch]", {
|
|
61744
|
+
selectedLineIds,
|
|
61745
|
+
mismatches,
|
|
61746
|
+
legacySnapshot,
|
|
61747
|
+
bootstrapSnapshot
|
|
61748
|
+
});
|
|
61749
|
+
}, [
|
|
61750
|
+
bootstrapKpisWithTrend,
|
|
61751
|
+
bootstrapMonitor.activeBreaks,
|
|
61752
|
+
bootstrapMonitor.efficiencyLegend,
|
|
61753
|
+
bootstrapMonitor.isCurrentScopeResolved,
|
|
61754
|
+
bootstrapMonitor.isLoading,
|
|
61755
|
+
bootstrapMonitor.kpiTrend,
|
|
61756
|
+
bootstrapMonitor.lines,
|
|
61757
|
+
bootstrapMonitor.resolvedScope,
|
|
61758
|
+
bootstrapMonitor.videoStreamsByWorkspaceId,
|
|
61759
|
+
bootstrapMonitor.workspaceMetrics,
|
|
61760
|
+
isShadowMonitorMode,
|
|
61761
|
+
legacyActiveBreaks,
|
|
61762
|
+
legacyEfficiencyLegend,
|
|
61763
|
+
legacyIsCurrentScopeResolved,
|
|
61764
|
+
legacyKpiTrend,
|
|
61765
|
+
legacyKpisWithTrend,
|
|
61766
|
+
legacyMetricsLoading,
|
|
61767
|
+
legacyVideoStreamsByWorkspaceId,
|
|
61768
|
+
selectedLineIds,
|
|
61769
|
+
shouldEnableMetricsFetch,
|
|
61770
|
+
workspaceMetricsWithBreakState
|
|
61771
|
+
]);
|
|
61197
61772
|
const showBottleneckNotification = useCallback(async (bottleneck) => {
|
|
61198
61773
|
try {
|
|
61199
61774
|
logDebug3("\u{1F514} [Notification] Raw bottleneck data:", bottleneck);
|
|
@@ -61371,6 +61946,9 @@ function HomeView({
|
|
|
61371
61946
|
setBottleneckNotification(errorNotification);
|
|
61372
61947
|
}
|
|
61373
61948
|
}, [notificationService, timezone, dashboardConfig, lineShiftConfigs]);
|
|
61949
|
+
useEffect(() => {
|
|
61950
|
+
showBottleneckNotificationRef.current = showBottleneckNotification;
|
|
61951
|
+
}, [showBottleneckNotification]);
|
|
61374
61952
|
useEffect(() => {
|
|
61375
61953
|
const ticketsEnabled = dashboardConfig?.ticketsConfig?.enabled ?? true;
|
|
61376
61954
|
if (!ticketsEnabled) {
|
|
@@ -61440,7 +62018,7 @@ function HomeView({
|
|
|
61440
62018
|
});
|
|
61441
62019
|
if (latestTicket.event_type === "bottleneck") {
|
|
61442
62020
|
logDebug3("\u{1F514} [Polling] Showing bottleneck notification for:", latestTicket.log_number);
|
|
61443
|
-
|
|
62021
|
+
await showBottleneckNotificationRef.current?.(latestTicket);
|
|
61444
62022
|
} else {
|
|
61445
62023
|
logDebug3("\u26A0\uFE0F [Polling] Non-bottleneck ticket found but no handler configured:", latestTicket.event_type);
|
|
61446
62024
|
}
|
|
@@ -61460,29 +62038,30 @@ function HomeView({
|
|
|
61460
62038
|
clearInterval(pollInterval);
|
|
61461
62039
|
clearTimeout(initialPollTimer);
|
|
61462
62040
|
};
|
|
61463
|
-
}, [
|
|
62041
|
+
}, [
|
|
62042
|
+
dashboardConfig?.ticketsConfig?.enabled,
|
|
62043
|
+
notificationService,
|
|
62044
|
+
user?.email,
|
|
62045
|
+
user?.role_level,
|
|
62046
|
+
userCompanyId
|
|
62047
|
+
]);
|
|
61464
62048
|
const handleWorkspaceHover = useCallback((workspaceId) => {
|
|
61465
62049
|
}, []);
|
|
61466
62050
|
const handleWorkspaceHoverEnd = useCallback((workspaceId) => {
|
|
61467
62051
|
}, []);
|
|
61468
|
-
const
|
|
61469
|
-
streamsByWorkspaceId: videoStreamsByWorkspaceId,
|
|
61470
|
-
isLoading: videoStreamsLoading
|
|
61471
|
-
} = useWorkspaceVideoStreams(workspaceMetrics);
|
|
61472
|
-
const memoizedKPIs = useMemo(() => kpisWithTrend, [
|
|
62052
|
+
const memoizedKPIs = useMemo(() => currentKpisWithTrend, [
|
|
61473
62053
|
// Only update reference when values change by at least 1%
|
|
61474
|
-
|
|
61475
|
-
|
|
61476
|
-
|
|
61477
|
-
|
|
61478
|
-
|
|
61479
|
-
|
|
61480
|
-
|
|
61481
|
-
|
|
61482
|
-
|
|
61483
|
-
|
|
61484
|
-
|
|
61485
|
-
kpisWithTrend?.qualityCompliance?.value ? Math.round(kpisWithTrend.qualityCompliance.value) : null,
|
|
62054
|
+
currentKpisWithTrend?.efficiency?.value ? Math.round(currentKpisWithTrend.efficiency.value) : null,
|
|
62055
|
+
currentKpisWithTrend?.efficiency?.change,
|
|
62056
|
+
currentKpisWithTrend?.underperformingWorkers?.current,
|
|
62057
|
+
currentKpisWithTrend?.underperformingWorkers?.total,
|
|
62058
|
+
currentKpisWithTrend?.underperformingWorkers?.change,
|
|
62059
|
+
currentKpisWithTrend?.outputProgress?.current,
|
|
62060
|
+
currentKpisWithTrend?.outputProgress?.target,
|
|
62061
|
+
currentKpisWithTrend?.outputProgress?.change,
|
|
62062
|
+
currentKpisWithTrend?.avgCycleTime?.value ? Math.round(currentKpisWithTrend.avgCycleTime.value * 10) / 10 : null,
|
|
62063
|
+
currentKpisWithTrend?.avgCycleTime?.change,
|
|
62064
|
+
currentKpisWithTrend?.qualityCompliance?.value ? Math.round(currentKpisWithTrend.qualityCompliance.value) : null,
|
|
61486
62065
|
selectedLineIdsKey
|
|
61487
62066
|
]);
|
|
61488
62067
|
useEffect(() => {
|
|
@@ -61493,13 +62072,13 @@ function HomeView({
|
|
|
61493
62072
|
dashboard_surface: "monitor"
|
|
61494
62073
|
});
|
|
61495
62074
|
}, []);
|
|
61496
|
-
const metricsErrorMessage =
|
|
62075
|
+
const metricsErrorMessage = currentMetricsError?.message || null;
|
|
61497
62076
|
const handleRetryDashboardData = useCallback(async () => {
|
|
61498
62077
|
if (isRecoveringSession) {
|
|
61499
62078
|
await retrySessionHydration();
|
|
61500
62079
|
}
|
|
61501
|
-
|
|
61502
|
-
}, [
|
|
62080
|
+
await currentRefetchMetrics();
|
|
62081
|
+
}, [currentRefetchMetrics, isRecoveringSession, retrySessionHydration]);
|
|
61503
62082
|
const getTrackedLineScope = useCallback((lineIdsForScope) => {
|
|
61504
62083
|
if (isAllLinesSelection(lineIdsForScope)) {
|
|
61505
62084
|
return factoryViewId;
|
|
@@ -61552,12 +62131,15 @@ function HomeView({
|
|
|
61552
62131
|
updateSelectedLineIds(Array.from(currentSelection));
|
|
61553
62132
|
}, [selectedLineIds, updateSelectedLineIds]);
|
|
61554
62133
|
useEffect(() => {
|
|
61555
|
-
if (!
|
|
62134
|
+
if (!isChangingFilter) {
|
|
62135
|
+
return;
|
|
62136
|
+
}
|
|
62137
|
+
if (!currentMetricsLoading && currentIsCurrentScopeResolved || currentMetricsError) {
|
|
61556
62138
|
setIsChangingFilter(false);
|
|
61557
62139
|
}
|
|
61558
|
-
}, [
|
|
62140
|
+
}, [currentIsCurrentScopeResolved, currentMetricsError, currentMetricsLoading, isChangingFilter]);
|
|
61559
62141
|
useEffect(() => {
|
|
61560
|
-
if (shouldEnableMetricsFetch && !
|
|
62142
|
+
if (shouldEnableMetricsFetch && !currentMetricsLoading && !currentMetricsError && !hasInitialDataLoaded) {
|
|
61561
62143
|
setHasInitialDataLoaded(true);
|
|
61562
62144
|
trackCoreEvent("monitor page loaded", {
|
|
61563
62145
|
default_line_id: defaultLineId,
|
|
@@ -61566,7 +62148,7 @@ function HomeView({
|
|
|
61566
62148
|
dashboard_surface: "monitor"
|
|
61567
62149
|
});
|
|
61568
62150
|
}
|
|
61569
|
-
}, [shouldEnableMetricsFetch,
|
|
62151
|
+
}, [shouldEnableMetricsFetch, currentMetricsLoading, currentMetricsError, hasInitialDataLoaded, defaultLineId, factoryViewId, isSupervisor]);
|
|
61570
62152
|
const lineTitle = useMemo(() => {
|
|
61571
62153
|
return factoryName;
|
|
61572
62154
|
}, [factoryName]);
|
|
@@ -61717,15 +62299,15 @@ function HomeView({
|
|
|
61717
62299
|
return showLoading;
|
|
61718
62300
|
};
|
|
61719
62301
|
const isAuthBootstrapping = authStatus === "loading";
|
|
61720
|
-
const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (isAuthBootstrapping || shouldEnableMetricsFetch &&
|
|
61721
|
-
const isDataLoading =
|
|
62302
|
+
const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (isAuthBootstrapping || shouldEnableMetricsFetch && currentMetricsLoading);
|
|
62303
|
+
const isDataLoading = currentMetricsLoading;
|
|
61722
62304
|
const hasKpiDataReady = useMemo(() => {
|
|
61723
|
-
const lineMetricsRows =
|
|
62305
|
+
const lineMetricsRows = currentLineMetrics || [];
|
|
61724
62306
|
if (selectedLineIds.length > 1) {
|
|
61725
62307
|
return lineMetricsRows.some((row) => selectedLineIdSet.has(row?.line_id));
|
|
61726
62308
|
}
|
|
61727
62309
|
return lineMetricsRows.some((row) => row?.line_id === primarySelectedLineId);
|
|
61728
|
-
}, [
|
|
62310
|
+
}, [currentLineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
61729
62311
|
const isKpiLoading = !hasKpiDataReady;
|
|
61730
62312
|
const shouldShowReconnectScreen = !hasInitialDataLoaded && (isRecoveringSession || !shouldEnableMetricsFetch && authStatus !== "failed" || !!metricsErrorMessage && authStatus !== "failed");
|
|
61731
62313
|
const shouldShowFatalLoadFailure = !hasInitialDataLoaded && !!metricsErrorMessage && authStatus === "failed";
|
|
@@ -61753,6 +62335,7 @@ function HomeView({
|
|
|
61753
62335
|
return () => clearTimeout(timer);
|
|
61754
62336
|
}, [isDataLoading]);
|
|
61755
62337
|
const shouldShowDataLoading = showDataLoading || isDataLoading;
|
|
62338
|
+
const shouldShowFilterChangeLoader = isChangingFilter && !currentIsCurrentScopeResolved;
|
|
61756
62339
|
const shouldShowKpiLoading = useSmoothLoading(isKpiLoading, 400);
|
|
61757
62340
|
const displayKpis = shouldShowKpiLoading ? null : memoizedKPIs;
|
|
61758
62341
|
const kpiSectionControl = useMemo(() => /* @__PURE__ */ jsx(
|
|
@@ -61837,7 +62420,7 @@ function HomeView({
|
|
|
61837
62420
|
}
|
|
61838
62421
|
)
|
|
61839
62422
|
] }) }) : null,
|
|
61840
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative flex flex-col", children: /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsx(
|
|
62423
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative flex flex-col", children: /* @__PURE__ */ jsx("div", { className: "relative flex-1 min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsx(
|
|
61841
62424
|
motion.div,
|
|
61842
62425
|
{
|
|
61843
62426
|
initial: { opacity: 0, scale: 0.98 },
|
|
@@ -61849,10 +62432,10 @@ function HomeView({
|
|
|
61849
62432
|
lineNames: mergedLineNames,
|
|
61850
62433
|
lineOrder: selectedLineIds,
|
|
61851
62434
|
factoryView: factoryViewId,
|
|
61852
|
-
legend:
|
|
62435
|
+
legend: currentEfficiencyLegend,
|
|
61853
62436
|
videoSources,
|
|
61854
|
-
videoStreamsByWorkspaceId,
|
|
61855
|
-
videoStreamsLoading,
|
|
62437
|
+
videoStreamsByWorkspaceId: currentVideoStreamsByWorkspaceId,
|
|
62438
|
+
videoStreamsLoading: currentVideoStreamsLoading,
|
|
61856
62439
|
displayNames: metricsDisplayNames,
|
|
61857
62440
|
hasFlowBuffers,
|
|
61858
62441
|
className: "h-full",
|
|
@@ -61860,8 +62443,7 @@ function HomeView({
|
|
|
61860
62443
|
onWorkspaceHover: handleWorkspaceHover,
|
|
61861
62444
|
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
61862
62445
|
})
|
|
61863
|
-
}
|
|
61864
|
-
selectedLineIdsKey
|
|
62446
|
+
}
|
|
61865
62447
|
) : !shouldShowDataLoading && hasInitialDataLoaded ? /* @__PURE__ */ jsx(
|
|
61866
62448
|
motion.div,
|
|
61867
62449
|
{
|
|
@@ -61883,10 +62465,10 @@ function HomeView({
|
|
|
61883
62465
|
lineNames: mergedLineNames,
|
|
61884
62466
|
lineOrder: selectedLineIds,
|
|
61885
62467
|
factoryView: factoryViewId,
|
|
61886
|
-
legend:
|
|
62468
|
+
legend: currentEfficiencyLegend,
|
|
61887
62469
|
videoSources,
|
|
61888
|
-
videoStreamsByWorkspaceId,
|
|
61889
|
-
videoStreamsLoading,
|
|
62470
|
+
videoStreamsByWorkspaceId: currentVideoStreamsByWorkspaceId,
|
|
62471
|
+
videoStreamsLoading: currentVideoStreamsLoading,
|
|
61890
62472
|
displayNames: metricsDisplayNames,
|
|
61891
62473
|
hasFlowBuffers,
|
|
61892
62474
|
className: "h-full",
|
|
@@ -61894,16 +62476,15 @@ function HomeView({
|
|
|
61894
62476
|
onWorkspaceHover: handleWorkspaceHover,
|
|
61895
62477
|
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
61896
62478
|
})
|
|
61897
|
-
}
|
|
61898
|
-
selectedLineIdsKey
|
|
62479
|
+
}
|
|
61899
62480
|
) }) })
|
|
61900
62481
|
] }),
|
|
61901
62482
|
/* @__PURE__ */ jsx(
|
|
61902
62483
|
BreakNotificationPopup,
|
|
61903
62484
|
{
|
|
61904
|
-
activeBreaks,
|
|
62485
|
+
activeBreaks: currentActiveBreaks,
|
|
61905
62486
|
lineNames: mergedLineNames,
|
|
61906
|
-
isVisible: !
|
|
62487
|
+
isVisible: !currentBreaksLoading && !currentBreaksError && !breakNotificationsDismissed,
|
|
61907
62488
|
onDismiss: () => setBreakNotificationsDismissed(true)
|
|
61908
62489
|
}
|
|
61909
62490
|
),
|
|
@@ -61915,6 +62496,15 @@ function HomeView({
|
|
|
61915
62496
|
onDismiss: () => setBottleneckNotification(null)
|
|
61916
62497
|
}
|
|
61917
62498
|
),
|
|
62499
|
+
/* @__PURE__ */ jsx(
|
|
62500
|
+
LoadingOverlayCmp,
|
|
62501
|
+
{
|
|
62502
|
+
isVisible: shouldShowFilterChangeLoader,
|
|
62503
|
+
message: "Loading Dashboard...",
|
|
62504
|
+
className: "bg-slate-50/30 backdrop-blur-[3px]",
|
|
62505
|
+
contentVariant: "plain"
|
|
62506
|
+
}
|
|
62507
|
+
),
|
|
61918
62508
|
diagnosisModalOpen && bottleneckModalData?.clipId && /* @__PURE__ */ jsx(
|
|
61919
62509
|
DiagnosisVideoModal,
|
|
61920
62510
|
{
|
|
@@ -62165,7 +62755,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
|
|
|
62165
62755
|
}
|
|
62166
62756
|
};
|
|
62167
62757
|
};
|
|
62168
|
-
var
|
|
62758
|
+
var transformWorkspaceMetrics2 = (workspaceData, lineId, companyId, queryDate, queryShiftId) => (workspaceData || []).map((item) => ({
|
|
62169
62759
|
company_id: item.company_id || companyId,
|
|
62170
62760
|
line_id: item.line_id || lineId,
|
|
62171
62761
|
shift_id: item.shift_id ?? queryShiftId,
|
|
@@ -62313,7 +62903,7 @@ var useLineDetailPageData = ({
|
|
|
62313
62903
|
setDetailResponse(nextDetail);
|
|
62314
62904
|
const metrics3 = transformLineMetrics(lineId, nextDetail, queryDate, queryShiftId);
|
|
62315
62905
|
const lineDetails2 = transformLineDetails(lineId, nextDetail);
|
|
62316
|
-
const workspaces2 =
|
|
62906
|
+
const workspaces2 = transformWorkspaceMetrics2(
|
|
62317
62907
|
nextDetail.workspace_metrics || [],
|
|
62318
62908
|
lineId,
|
|
62319
62909
|
companyId,
|
|
@@ -62403,7 +62993,7 @@ var useLineDetailPageData = ({
|
|
|
62403
62993
|
[detailResponse, lineId]
|
|
62404
62994
|
);
|
|
62405
62995
|
const workspaces = useMemo(
|
|
62406
|
-
() => detailResponse && companyId ?
|
|
62996
|
+
() => detailResponse && companyId ? transformWorkspaceMetrics2(detailResponse.workspace_metrics || [], lineId, companyId, queryDate, queryShiftId) : [],
|
|
62407
62997
|
[detailResponse, companyId, lineId, queryDate, queryShiftId]
|
|
62408
62998
|
);
|
|
62409
62999
|
const lineInfo = useMemo(() => buildLineInfoSnapshot(lineDetails, metrics2), [lineDetails, metrics2]);
|
|
@@ -74025,7 +74615,8 @@ var TeamManagementView = ({
|
|
|
74025
74615
|
const bootstrapData = await bootstrapResponse.json();
|
|
74026
74616
|
setAvailableFactories((bootstrapData.factories || []).map((factory) => ({
|
|
74027
74617
|
id: factory.id,
|
|
74028
|
-
factory_name: factory.factory_name
|
|
74618
|
+
factory_name: factory.factory_name,
|
|
74619
|
+
company_id: factory.company_id
|
|
74029
74620
|
})));
|
|
74030
74621
|
setAvailableLines(bootstrapData.lines || []);
|
|
74031
74622
|
setUsers(bootstrapData.users || []);
|
|
@@ -78993,7 +79584,7 @@ var efficiencyLineConfig = [
|
|
|
78993
79584
|
var bumpRenderCounter = (key) => {
|
|
78994
79585
|
if (process.env.NODE_ENV === "test") ;
|
|
78995
79586
|
};
|
|
78996
|
-
var
|
|
79587
|
+
var toNumber4 = (value) => {
|
|
78997
79588
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
78998
79589
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
78999
79590
|
const parsed = Number(value);
|
|
@@ -79528,7 +80119,7 @@ var OverviewSummaryCards = React143__default.memo(({ store }) => {
|
|
|
79528
80119
|
workspaceId: item.workspace_id || "",
|
|
79529
80120
|
workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
|
|
79530
80121
|
lineName: item.line_name?.trim() || "Unknown Line",
|
|
79531
|
-
avgIdleSeconds:
|
|
80122
|
+
avgIdleSeconds: toNumber4(item.avg_idle_seconds)
|
|
79532
80123
|
})).slice(0, 5);
|
|
79533
80124
|
}, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
|
|
79534
80125
|
const showIdleContributorLineNames = React143__default.useMemo(() => {
|
|
@@ -79743,9 +80334,9 @@ var PoorestPerformersCard = React143__default.memo(({
|
|
|
79743
80334
|
return {
|
|
79744
80335
|
id: lineId,
|
|
79745
80336
|
name: line.line_name?.trim() || "Unknown Line",
|
|
79746
|
-
efficiency: roundOne(
|
|
79747
|
-
previousEfficiency:
|
|
79748
|
-
delta:
|
|
80337
|
+
efficiency: roundOne(toNumber4(line.avg_efficiency) || 0),
|
|
80338
|
+
previousEfficiency: toNumber4(line.previous_avg_efficiency),
|
|
80339
|
+
delta: toNumber4(line.delta_pp),
|
|
79749
80340
|
supervisor: supervisor?.displayName || "Unassigned",
|
|
79750
80341
|
supervisorImage: supervisor?.profilePhotoUrl ?? null
|
|
79751
80342
|
};
|
|
@@ -79854,14 +80445,14 @@ var IdleBreakdownCard = React143__default.memo(({
|
|
|
79854
80445
|
paletteToken: item.palette_token?.trim(),
|
|
79855
80446
|
iconToken: item.icon_token?.trim(),
|
|
79856
80447
|
isKnown: item.is_known ?? void 0,
|
|
79857
|
-
value:
|
|
79858
|
-
totalDurationSeconds:
|
|
79859
|
-
efficiencyLossPercentage:
|
|
80448
|
+
value: toNumber4(item.percentage) || 0,
|
|
80449
|
+
totalDurationSeconds: toNumber4(item.total_duration_seconds),
|
|
80450
|
+
efficiencyLossPercentage: toNumber4(item.efficiency_loss_percentage),
|
|
79860
80451
|
contributors: (item.contributors || []).map((contributor) => ({
|
|
79861
80452
|
workspaceId: contributor.workspace_id || "",
|
|
79862
80453
|
workspaceName: contributor.workspace_name?.trim() || "Unknown",
|
|
79863
|
-
totalDurationSeconds:
|
|
79864
|
-
percentageWithinReason:
|
|
80454
|
+
totalDurationSeconds: toNumber4(contributor.total_duration_seconds),
|
|
80455
|
+
percentageWithinReason: toNumber4(contributor.percentage_within_reason)
|
|
79865
80456
|
}))
|
|
79866
80457
|
})).filter((item) => item.value > 0);
|
|
79867
80458
|
}, [idle.data]);
|
|
@@ -79930,7 +80521,7 @@ var EfficiencyTrendCard = React143__default.memo(({
|
|
|
79930
80521
|
return `${hour12}:${minutes.toString().padStart(2, "0")} ${suffix}`;
|
|
79931
80522
|
})(),
|
|
79932
80523
|
efficiency: (() => {
|
|
79933
|
-
const value =
|
|
80524
|
+
const value = toNumber4(point.avg_efficiency);
|
|
79934
80525
|
return value === null ? void 0 : value;
|
|
79935
80526
|
})()
|
|
79936
80527
|
}));
|
|
@@ -79943,7 +80534,7 @@ var EfficiencyTrendCard = React143__default.memo(({
|
|
|
79943
80534
|
name: format(pointDate, "MMM d"),
|
|
79944
80535
|
dayOfWeek: format(pointDate, "EEEE"),
|
|
79945
80536
|
efficiency: (() => {
|
|
79946
|
-
const value =
|
|
80537
|
+
const value = toNumber4(point.avg_efficiency);
|
|
79947
80538
|
return value === null ? void 0 : value;
|
|
79948
80539
|
})()
|
|
79949
80540
|
}]];
|
|
@@ -79967,7 +80558,7 @@ var EfficiencyTrendCard = React143__default.memo(({
|
|
|
79967
80558
|
name: pointDate ? format(pointDate, "MMM d") : "",
|
|
79968
80559
|
dayOfWeek: pointDate ? format(pointDate, "EEEE") : "",
|
|
79969
80560
|
efficiency: (() => {
|
|
79970
|
-
const value =
|
|
80561
|
+
const value = toNumber4(point.avg_efficiency);
|
|
79971
80562
|
return value === null ? void 0 : value;
|
|
79972
80563
|
})()
|
|
79973
80564
|
};
|
|
@@ -80091,7 +80682,7 @@ var debugRefreshLog = (message, payload) => {
|
|
|
80091
80682
|
var isAbortError2 = (error) => {
|
|
80092
80683
|
return error instanceof DOMException && error.name === "AbortError";
|
|
80093
80684
|
};
|
|
80094
|
-
var
|
|
80685
|
+
var toNumber5 = (value) => {
|
|
80095
80686
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
80096
80687
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
80097
80688
|
const parsed = Number(value);
|
|
@@ -80100,11 +80691,11 @@ var toNumber4 = (value) => {
|
|
|
80100
80691
|
return null;
|
|
80101
80692
|
};
|
|
80102
80693
|
var formatImprovementMetric = (recommendation) => {
|
|
80103
|
-
const estimatedGain =
|
|
80694
|
+
const estimatedGain = toNumber5(recommendation.estimated_gain_pieces);
|
|
80104
80695
|
if (estimatedGain !== null && estimatedGain > 0) {
|
|
80105
80696
|
return `+${Math.round(estimatedGain).toLocaleString()} pcs / day`;
|
|
80106
80697
|
}
|
|
80107
|
-
const idleMinutes =
|
|
80698
|
+
const idleMinutes = toNumber5(recommendation.metrics?.idle_minutes);
|
|
80108
80699
|
if (idleMinutes !== null) {
|
|
80109
80700
|
return `-${Math.round(idleMinutes)}m Idle`;
|
|
80110
80701
|
}
|