@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.js
CHANGED
|
@@ -13487,10 +13487,19 @@ function getEfficiencyTextColorClasses(efficiency, legend = DEFAULT_EFFICIENCY_L
|
|
|
13487
13487
|
|
|
13488
13488
|
// src/lib/hooks/useDashboardMetrics.ts
|
|
13489
13489
|
var DEBUG_DASHBOARD_LOGS = process.env.NEXT_PUBLIC_DEBUG_DASHBOARD === "true";
|
|
13490
|
+
var REALTIME_REFRESH_DEBOUNCE_MS = 1500;
|
|
13491
|
+
var REALTIME_REFRESH_MIN_INTERVAL_MS = 5e3;
|
|
13490
13492
|
var logDebug = (...args) => {
|
|
13491
13493
|
if (!DEBUG_DASHBOARD_LOGS) return;
|
|
13492
13494
|
console.log(...args);
|
|
13493
13495
|
};
|
|
13496
|
+
var buildMetricsScopeKey = (lineId, lineIds) => {
|
|
13497
|
+
const normalizedLineIds = Array.from(new Set((lineIds || []).filter(Boolean))).sort();
|
|
13498
|
+
if (normalizedLineIds.length > 0) {
|
|
13499
|
+
return `${lineId}|${normalizedLineIds.join(",")}`;
|
|
13500
|
+
}
|
|
13501
|
+
return lineId;
|
|
13502
|
+
};
|
|
13494
13503
|
var parseEfficiencyLegend = (legend) => {
|
|
13495
13504
|
if (!legend) return null;
|
|
13496
13505
|
const coerce = (value, fallback) => {
|
|
@@ -13570,6 +13579,7 @@ var useDashboardMetrics = ({
|
|
|
13570
13579
|
const supabase = useSupabase();
|
|
13571
13580
|
const [metrics2, setMetrics] = React143.useState({ workspaceMetrics: [], lineMetrics: [] });
|
|
13572
13581
|
const [metricsLineId, setMetricsLineId] = React143.useState(lineId ?? null);
|
|
13582
|
+
const [metricsScopeKey, setMetricsScopeKey] = React143.useState(() => buildMetricsScopeKey(lineId, lineIds));
|
|
13573
13583
|
const [isLoading, setIsLoading] = React143.useState(true);
|
|
13574
13584
|
const [error, setError] = React143.useState(null);
|
|
13575
13585
|
const lineIdRef = React143.useRef(lineId);
|
|
@@ -13579,8 +13589,10 @@ var useDashboardMetrics = ({
|
|
|
13579
13589
|
const abortControllerRef = React143.useRef(null);
|
|
13580
13590
|
const lastFetchKeyRef = React143.useRef(null);
|
|
13581
13591
|
const inFlightFetchKeyRef = React143.useRef(null);
|
|
13582
|
-
const updateQueueRef = React143.useRef(false);
|
|
13583
13592
|
const onLineMetricsUpdateRef = React143.useRef(onLineMetricsUpdate);
|
|
13593
|
+
const pendingRealtimeRefreshRef = React143.useRef(false);
|
|
13594
|
+
const realtimeRefreshTimerRef = React143.useRef(null);
|
|
13595
|
+
const lastRealtimeRefreshStartedAtRef = React143.useRef(0);
|
|
13584
13596
|
const shiftGroupsRef = React143.useRef(shiftGroups);
|
|
13585
13597
|
const operationalShiftKeyRef = React143.useRef(operationalShiftKey);
|
|
13586
13598
|
const configuredLineIdsRef = React143.useRef(configuredLineIds);
|
|
@@ -13608,15 +13620,17 @@ var useDashboardMetrics = ({
|
|
|
13608
13620
|
() => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
|
|
13609
13621
|
[entityConfig.companyId]
|
|
13610
13622
|
);
|
|
13623
|
+
const requestedScopeKey = React143.useMemo(
|
|
13624
|
+
() => buildMetricsScopeKey(lineId, isFactoryView ? targetFactoryLineIds : void 0),
|
|
13625
|
+
[isFactoryView, lineId, targetFactoryLineIds]
|
|
13626
|
+
);
|
|
13611
13627
|
React143.useEffect(() => {
|
|
13612
13628
|
lineIdRef.current = lineId;
|
|
13613
|
-
setMetrics({ workspaceMetrics: [], lineMetrics: [], metadata: void 0, efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND });
|
|
13614
|
-
setMetricsLineId(null);
|
|
13615
13629
|
setIsLoading(true);
|
|
13616
13630
|
setError(null);
|
|
13617
13631
|
lastFetchKeyRef.current = null;
|
|
13618
13632
|
inFlightFetchKeyRef.current = null;
|
|
13619
|
-
}, [lineId]);
|
|
13633
|
+
}, [lineId, requestedScopeKey]);
|
|
13620
13634
|
const fetchAllMetrics = React143.useCallback(async (options = {}) => {
|
|
13621
13635
|
const { force = false } = options;
|
|
13622
13636
|
const currentLineIdToUse = lineIdRef.current;
|
|
@@ -13629,7 +13643,6 @@ var useDashboardMetrics = ({
|
|
|
13629
13643
|
companySpecificMetricsTable
|
|
13630
13644
|
});
|
|
13631
13645
|
if (!currentLineIdToUse || !supabase || !enabled || shiftLoading || isTimezoneLoading || companySpecificMetricsTable.includes("unknown_company")) {
|
|
13632
|
-
updateQueueRef.current = false;
|
|
13633
13646
|
if (!metrics2?.workspaceMetrics?.length && !metrics2?.lineMetrics?.length && !shiftLoading) setIsLoading(false);
|
|
13634
13647
|
if (companySpecificMetricsTable.includes("unknown_company") && !error) {
|
|
13635
13648
|
setError({ message: "Company ID not configured for metrics table.", code: "CONFIG_ERROR" });
|
|
@@ -13642,6 +13655,10 @@ var useDashboardMetrics = ({
|
|
|
13642
13655
|
const usesShiftGroups = isFactory && shiftGroups.length > 0;
|
|
13643
13656
|
const singleShiftDetails = usesShiftGroups ? null : shiftConfig ? getCurrentShift(defaultTimezone, shiftConfig) : shiftGroups.length === 1 ? { date: shiftGroups[0].date, shiftId: shiftGroups[0].shiftId } : getCurrentShift(defaultTimezone, staticShiftConfig);
|
|
13644
13657
|
const fetchKey = usesShiftGroups ? `factory|${companyId || "unknown"}|${shiftGroupsKey}` : isFactory ? `factory|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}|${targetLineIdsKey}` : `${currentLineIdToUse}|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}`;
|
|
13658
|
+
const responseScopeKey = buildMetricsScopeKey(
|
|
13659
|
+
currentLineIdToUse,
|
|
13660
|
+
isFactory ? targetLineIds : void 0
|
|
13661
|
+
);
|
|
13645
13662
|
logDebug("[useDashboardMetrics] Fetch key details:", {
|
|
13646
13663
|
isFactory,
|
|
13647
13664
|
usesShiftGroups,
|
|
@@ -13651,14 +13668,8 @@ var useDashboardMetrics = ({
|
|
|
13651
13668
|
singleShiftDetails,
|
|
13652
13669
|
fetchKey
|
|
13653
13670
|
});
|
|
13654
|
-
if (inFlightFetchKeyRef.current === fetchKey)
|
|
13655
|
-
|
|
13656
|
-
return;
|
|
13657
|
-
}
|
|
13658
|
-
if (!force && lastFetchKeyRef.current === fetchKey) {
|
|
13659
|
-
updateQueueRef.current = false;
|
|
13660
|
-
return;
|
|
13661
|
-
}
|
|
13671
|
+
if (inFlightFetchKeyRef.current === fetchKey) return;
|
|
13672
|
+
if (!force && lastFetchKeyRef.current === fetchKey) return;
|
|
13662
13673
|
const requestId = ++activeRequestIdRef.current;
|
|
13663
13674
|
const requestLineId = currentLineIdToUse;
|
|
13664
13675
|
isFetchingRef.current = true;
|
|
@@ -13681,6 +13692,7 @@ var useDashboardMetrics = ({
|
|
|
13681
13692
|
efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND
|
|
13682
13693
|
});
|
|
13683
13694
|
setMetricsLineId(requestLineId);
|
|
13695
|
+
setMetricsScopeKey(responseScopeKey);
|
|
13684
13696
|
lastFetchKeyRef.current = inFlightFetchKeyRef.current;
|
|
13685
13697
|
return;
|
|
13686
13698
|
}
|
|
@@ -13890,6 +13902,7 @@ var useDashboardMetrics = ({
|
|
|
13890
13902
|
hydrateFromBackend(idleTimeVlmByLine);
|
|
13891
13903
|
setMetrics(newMetricsState);
|
|
13892
13904
|
setMetricsLineId(requestLineId);
|
|
13905
|
+
setMetricsScopeKey(responseScopeKey);
|
|
13893
13906
|
lastFetchKeyRef.current = inFlightFetchKeyRef.current;
|
|
13894
13907
|
} catch (err) {
|
|
13895
13908
|
if (abortController.signal.aborted || err?.name === "AbortError") {
|
|
@@ -13912,9 +13925,24 @@ var useDashboardMetrics = ({
|
|
|
13912
13925
|
if (requestId === activeRequestIdRef.current) {
|
|
13913
13926
|
setIsLoading(false);
|
|
13914
13927
|
isFetchingRef.current = false;
|
|
13915
|
-
updateQueueRef.current = false;
|
|
13916
13928
|
activeFetchLineIdRef.current = null;
|
|
13917
13929
|
inFlightFetchKeyRef.current = null;
|
|
13930
|
+
if (pendingRealtimeRefreshRef.current) {
|
|
13931
|
+
const elapsedSinceLastRealtimeRefresh = Date.now() - lastRealtimeRefreshStartedAtRef.current;
|
|
13932
|
+
const minIntervalRemaining = Math.max(0, REALTIME_REFRESH_MIN_INTERVAL_MS - elapsedSinceLastRealtimeRefresh);
|
|
13933
|
+
const nextDelay = Math.max(REALTIME_REFRESH_DEBOUNCE_MS, minIntervalRemaining);
|
|
13934
|
+
if (realtimeRefreshTimerRef.current === null) {
|
|
13935
|
+
realtimeRefreshTimerRef.current = window.setTimeout(() => {
|
|
13936
|
+
realtimeRefreshTimerRef.current = null;
|
|
13937
|
+
if (!pendingRealtimeRefreshRef.current || isFetchingRef.current || inFlightFetchKeyRef.current) {
|
|
13938
|
+
return;
|
|
13939
|
+
}
|
|
13940
|
+
pendingRealtimeRefreshRef.current = false;
|
|
13941
|
+
lastRealtimeRefreshStartedAtRef.current = Date.now();
|
|
13942
|
+
fetchAllMetricsRef.current({ force: true, reason: "subscription" });
|
|
13943
|
+
}, nextDelay);
|
|
13944
|
+
}
|
|
13945
|
+
}
|
|
13918
13946
|
}
|
|
13919
13947
|
}
|
|
13920
13948
|
}, [
|
|
@@ -13944,20 +13972,59 @@ var useDashboardMetrics = ({
|
|
|
13944
13972
|
React143.useEffect(() => {
|
|
13945
13973
|
fetchAllMetricsRef.current = fetchAllMetrics;
|
|
13946
13974
|
}, [fetchAllMetrics]);
|
|
13947
|
-
const
|
|
13948
|
-
if (
|
|
13949
|
-
|
|
13950
|
-
|
|
13975
|
+
const clearRealtimeRefreshTimer = React143.useCallback(() => {
|
|
13976
|
+
if (realtimeRefreshTimerRef.current !== null) {
|
|
13977
|
+
window.clearTimeout(realtimeRefreshTimerRef.current);
|
|
13978
|
+
realtimeRefreshTimerRef.current = null;
|
|
13979
|
+
}
|
|
13980
|
+
}, []);
|
|
13981
|
+
const scheduleRealtimeRefresh = React143.useCallback(() => {
|
|
13982
|
+
if (!enabled || !supabase) {
|
|
13983
|
+
pendingRealtimeRefreshRef.current = false;
|
|
13984
|
+
clearRealtimeRefreshTimer();
|
|
13985
|
+
return;
|
|
13986
|
+
}
|
|
13987
|
+
if (!pendingRealtimeRefreshRef.current || realtimeRefreshTimerRef.current !== null) {
|
|
13988
|
+
return;
|
|
13989
|
+
}
|
|
13990
|
+
const elapsedSinceLastRealtimeRefresh = Date.now() - lastRealtimeRefreshStartedAtRef.current;
|
|
13991
|
+
const minIntervalRemaining = Math.max(0, REALTIME_REFRESH_MIN_INTERVAL_MS - elapsedSinceLastRealtimeRefresh);
|
|
13992
|
+
const nextDelay = Math.max(REALTIME_REFRESH_DEBOUNCE_MS, minIntervalRemaining);
|
|
13993
|
+
realtimeRefreshTimerRef.current = window.setTimeout(() => {
|
|
13994
|
+
realtimeRefreshTimerRef.current = null;
|
|
13995
|
+
if (!pendingRealtimeRefreshRef.current) {
|
|
13996
|
+
return;
|
|
13951
13997
|
}
|
|
13998
|
+
if (isFetchingRef.current || inFlightFetchKeyRef.current) {
|
|
13999
|
+
scheduleRealtimeRefresh();
|
|
14000
|
+
return;
|
|
14001
|
+
}
|
|
14002
|
+
pendingRealtimeRefreshRef.current = false;
|
|
14003
|
+
lastRealtimeRefreshStartedAtRef.current = Date.now();
|
|
14004
|
+
fetchAllMetricsRef.current({ force: true, reason: "subscription" });
|
|
14005
|
+
}, nextDelay);
|
|
14006
|
+
}, [clearRealtimeRefreshTimer, enabled, supabase]);
|
|
14007
|
+
React143.useEffect(() => {
|
|
14008
|
+
return () => {
|
|
14009
|
+
clearRealtimeRefreshTimer();
|
|
14010
|
+
pendingRealtimeRefreshRef.current = false;
|
|
14011
|
+
};
|
|
14012
|
+
}, [clearRealtimeRefreshTimer]);
|
|
14013
|
+
const queueUpdate = React143.useCallback(() => {
|
|
14014
|
+
if (!enabled) {
|
|
14015
|
+
logDebug("[useDashboardMetrics] queueUpdate skipped: metrics disabled");
|
|
14016
|
+
return;
|
|
14017
|
+
}
|
|
14018
|
+
if (!supabase) {
|
|
13952
14019
|
if (!supabase) {
|
|
13953
14020
|
logDebug("[useDashboardMetrics] queueUpdate skipped: supabase not ready");
|
|
13954
14021
|
}
|
|
13955
14022
|
return;
|
|
13956
14023
|
}
|
|
13957
|
-
|
|
13958
|
-
|
|
13959
|
-
|
|
13960
|
-
}, [
|
|
14024
|
+
pendingRealtimeRefreshRef.current = true;
|
|
14025
|
+
logDebug("[useDashboardMetrics] queueUpdate queued realtime refresh");
|
|
14026
|
+
scheduleRealtimeRefresh();
|
|
14027
|
+
}, [enabled, scheduleRealtimeRefresh, supabase]);
|
|
13961
14028
|
React143.useEffect(() => {
|
|
13962
14029
|
if (enabled && lineId && supabase && !shiftLoading && !isTimezoneLoading) {
|
|
13963
14030
|
fetchAllMetrics({ reason: "line-change" });
|
|
@@ -14077,7 +14144,7 @@ var useDashboardMetrics = ({
|
|
|
14077
14144
|
{ event: "*", schema, table: companySpecificMetricsTable, filter: filter2 },
|
|
14078
14145
|
(payload) => {
|
|
14079
14146
|
const payloadData = payload.new || payload.old;
|
|
14080
|
-
|
|
14147
|
+
logDebug("[useDashboardMetrics] \u{1F4E1} WS_METRICS payload received:", {
|
|
14081
14148
|
eventType: payload.eventType,
|
|
14082
14149
|
lineId: payloadData?.line_id,
|
|
14083
14150
|
workspaceId: payloadData?.workspace_id,
|
|
@@ -14099,14 +14166,14 @@ var useDashboardMetrics = ({
|
|
|
14099
14166
|
shiftId: payloadData?.shift_id
|
|
14100
14167
|
});
|
|
14101
14168
|
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
14102
|
-
|
|
14169
|
+
logDebug("[useDashboardMetrics] \u2705 WS Date/shift match - triggering update");
|
|
14103
14170
|
queueUpdate();
|
|
14104
14171
|
} else {
|
|
14105
|
-
|
|
14172
|
+
logDebug("[useDashboardMetrics] \u274C WS Date/shift mismatch - update SKIPPED");
|
|
14106
14173
|
}
|
|
14107
14174
|
}
|
|
14108
14175
|
).subscribe((status) => {
|
|
14109
|
-
|
|
14176
|
+
logDebug("[useDashboardMetrics] \u{1F4F6} WS metrics subscription:", {
|
|
14110
14177
|
channel: wsChannelName,
|
|
14111
14178
|
status,
|
|
14112
14179
|
table: companySpecificMetricsTable,
|
|
@@ -14124,7 +14191,7 @@ var useDashboardMetrics = ({
|
|
|
14124
14191
|
{ event: "*", schema, table: configuredLineMetricsTable, filter: filter2 },
|
|
14125
14192
|
(payload) => {
|
|
14126
14193
|
const payloadData = payload.new || payload.old;
|
|
14127
|
-
|
|
14194
|
+
logDebug("[useDashboardMetrics] \u{1F4E1} LINE_METRICS payload received:", {
|
|
14128
14195
|
eventType: payload.eventType,
|
|
14129
14196
|
lineId: payloadData?.line_id,
|
|
14130
14197
|
date: payloadData?.date,
|
|
@@ -14144,15 +14211,15 @@ var useDashboardMetrics = ({
|
|
|
14144
14211
|
shiftId: payloadData?.shift_id
|
|
14145
14212
|
});
|
|
14146
14213
|
if (payloadData?.date === group.date && payloadData?.shift_id === group.shiftId) {
|
|
14147
|
-
|
|
14214
|
+
logDebug("[useDashboardMetrics] \u2705 Date/shift match - triggering update");
|
|
14148
14215
|
queueUpdate();
|
|
14149
14216
|
onLineMetricsUpdateRef.current?.();
|
|
14150
14217
|
} else {
|
|
14151
|
-
|
|
14218
|
+
logDebug("[useDashboardMetrics] \u274C Date/shift mismatch - update SKIPPED");
|
|
14152
14219
|
}
|
|
14153
14220
|
}
|
|
14154
14221
|
).subscribe((status) => {
|
|
14155
|
-
|
|
14222
|
+
logDebug("[useDashboardMetrics] \u{1F4F6} Line metrics subscription:", {
|
|
14156
14223
|
channel: lmChannelName,
|
|
14157
14224
|
status,
|
|
14158
14225
|
table: configuredLineMetricsTable,
|
|
@@ -14248,7 +14315,7 @@ var useDashboardMetrics = ({
|
|
|
14248
14315
|
{ event: "*", schema, table, filter: filter2 },
|
|
14249
14316
|
(payload) => {
|
|
14250
14317
|
const payloadData = payload.new || payload.old;
|
|
14251
|
-
|
|
14318
|
+
logDebug(`[useDashboardMetrics] \u{1F4E1} ${table.toUpperCase()} payload received (single-line):`, {
|
|
14252
14319
|
eventType: payload.eventType,
|
|
14253
14320
|
table: payload.table,
|
|
14254
14321
|
lineId: payloadData?.line_id,
|
|
@@ -14272,14 +14339,14 @@ var useDashboardMetrics = ({
|
|
|
14272
14339
|
shiftId: payloadData?.shift_id
|
|
14273
14340
|
});
|
|
14274
14341
|
if (payloadData?.date === operationalDateForSubscription && payloadData?.shift_id === currentShiftDetails.shiftId) {
|
|
14275
|
-
|
|
14342
|
+
logDebug(`[useDashboardMetrics] \u2705 ${table} Date/shift match - triggering update`);
|
|
14276
14343
|
callback();
|
|
14277
14344
|
} else {
|
|
14278
|
-
|
|
14345
|
+
logDebug(`[useDashboardMetrics] \u274C ${table} Date/shift mismatch - update SKIPPED`);
|
|
14279
14346
|
}
|
|
14280
14347
|
}
|
|
14281
14348
|
).subscribe((status) => {
|
|
14282
|
-
|
|
14349
|
+
logDebug(`[useDashboardMetrics] \u{1F4F6} ${table} subscription:`, {
|
|
14283
14350
|
channel: channelName,
|
|
14284
14351
|
status,
|
|
14285
14352
|
table,
|
|
@@ -14328,14 +14395,17 @@ var useDashboardMetrics = ({
|
|
|
14328
14395
|
lineId
|
|
14329
14396
|
// NOTE: userAccessibleLineIds removed - accessed via ref
|
|
14330
14397
|
]);
|
|
14331
|
-
const
|
|
14332
|
-
const
|
|
14398
|
+
const isCurrentScopeResolved = metricsScopeKey === requestedScopeKey;
|
|
14399
|
+
const hasLastGoodMetrics = metrics2.workspaceMetrics.length > 0 || metrics2.lineMetrics.length > 0;
|
|
14400
|
+
const canReuseLastGoodMetrics = hasLastGoodMetrics && !isCurrentScopeResolved && (isLoading || !!error);
|
|
14401
|
+
const safeMetrics = isCurrentScopeResolved || canReuseLastGoodMetrics ? metrics2 : { workspaceMetrics: [], lineMetrics: [], metadata: void 0, efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND };
|
|
14333
14402
|
return {
|
|
14334
14403
|
workspaceMetrics: safeMetrics?.workspaceMetrics || [],
|
|
14335
14404
|
lineMetrics: safeMetrics?.lineMetrics || [],
|
|
14336
14405
|
efficiencyLegend: safeMetrics?.efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND,
|
|
14337
14406
|
metadata: safeMetrics?.metadata,
|
|
14338
|
-
isLoading: enabled ? isLoading || !
|
|
14407
|
+
isLoading: enabled ? isLoading || !isCurrentScopeResolved && !canReuseLastGoodMetrics : false,
|
|
14408
|
+
isCurrentScopeResolved,
|
|
14339
14409
|
error,
|
|
14340
14410
|
refetch: () => {
|
|
14341
14411
|
if (!enabled) {
|
|
@@ -16783,6 +16853,7 @@ var isInitialized = false;
|
|
|
16783
16853
|
var isInitializing = false;
|
|
16784
16854
|
var initializedWithLineIds = [];
|
|
16785
16855
|
var missingLineContextWarnings = /* @__PURE__ */ new Set();
|
|
16856
|
+
var lineLoadPromises = /* @__PURE__ */ new Map();
|
|
16786
16857
|
var initializationPromise = null;
|
|
16787
16858
|
var workspaceDisplayNamesListeners = /* @__PURE__ */ new Set();
|
|
16788
16859
|
var notifyWorkspaceDisplayNamesListeners = (changedLineId) => {
|
|
@@ -16798,6 +16869,30 @@ var subscribeWorkspaceDisplayNames = (listener) => {
|
|
|
16798
16869
|
workspaceDisplayNamesListeners.add(listener);
|
|
16799
16870
|
return () => workspaceDisplayNamesListeners.delete(listener);
|
|
16800
16871
|
};
|
|
16872
|
+
var storeLineDisplayNames = (lineId, lineDisplayNamesMap) => {
|
|
16873
|
+
runtimeWorkspaceDisplayNames[lineId] = {};
|
|
16874
|
+
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16875
|
+
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16876
|
+
});
|
|
16877
|
+
};
|
|
16878
|
+
var ensureLineWorkspaceDisplayNamesLoaded = async (lineId) => {
|
|
16879
|
+
if (!lineId || runtimeWorkspaceDisplayNames[lineId]) {
|
|
16880
|
+
return;
|
|
16881
|
+
}
|
|
16882
|
+
const existingPromise = lineLoadPromises.get(lineId);
|
|
16883
|
+
if (existingPromise) {
|
|
16884
|
+
await existingPromise;
|
|
16885
|
+
return;
|
|
16886
|
+
}
|
|
16887
|
+
const loadPromise = workspaceService.getWorkspaceDisplayNames(void 0, lineId).then((lineDisplayNamesMap) => {
|
|
16888
|
+
storeLineDisplayNames(lineId, lineDisplayNamesMap);
|
|
16889
|
+
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
16890
|
+
}).finally(() => {
|
|
16891
|
+
lineLoadPromises.delete(lineId);
|
|
16892
|
+
});
|
|
16893
|
+
lineLoadPromises.set(lineId, loadPromise);
|
|
16894
|
+
await loadPromise;
|
|
16895
|
+
};
|
|
16801
16896
|
var getAllWorkspaceDisplayNamesSnapshot = (lineId) => {
|
|
16802
16897
|
if (lineId && runtimeWorkspaceDisplayNames[lineId]) {
|
|
16803
16898
|
return { ...runtimeWorkspaceDisplayNames[lineId] };
|
|
@@ -16862,6 +16957,7 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
16862
16957
|
}
|
|
16863
16958
|
console.log("\u{1F504} Target line IDs for workspace filtering:", targetLineIds);
|
|
16864
16959
|
runtimeWorkspaceDisplayNames = {};
|
|
16960
|
+
lineLoadPromises.clear();
|
|
16865
16961
|
if (targetLineIds.length > 0) {
|
|
16866
16962
|
const results = await Promise.all(
|
|
16867
16963
|
targetLineIds.map(async (lineId) => {
|
|
@@ -16871,10 +16967,7 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
16871
16967
|
})
|
|
16872
16968
|
);
|
|
16873
16969
|
results.forEach(({ lineId, lineDisplayNamesMap }) => {
|
|
16874
|
-
|
|
16875
|
-
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16876
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16877
|
-
});
|
|
16970
|
+
storeLineDisplayNames(lineId, lineDisplayNamesMap);
|
|
16878
16971
|
console.log(`\u2705 Stored ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
|
|
16879
16972
|
});
|
|
16880
16973
|
} else {
|
|
@@ -16906,13 +16999,8 @@ var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
|
16906
16999
|
if (lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16907
17000
|
console.log(`\u{1F504} Line ${lineId} not in cache, fetching...`);
|
|
16908
17001
|
try {
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16912
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16913
|
-
});
|
|
16914
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
|
|
16915
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
17002
|
+
await ensureLineWorkspaceDisplayNamesLoaded(lineId);
|
|
17003
|
+
console.log(`\u2705 Added workspaces for line ${lineId}`);
|
|
16916
17004
|
} catch (error) {
|
|
16917
17005
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16918
17006
|
}
|
|
@@ -16925,13 +17013,8 @@ var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
|
16925
17013
|
if (lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16926
17014
|
console.log(`\u{1F504} Line ${lineId} not in cache after init, fetching...`);
|
|
16927
17015
|
try {
|
|
16928
|
-
|
|
16929
|
-
|
|
16930
|
-
lineDisplayNamesMap.forEach((displayName, workspaceId) => {
|
|
16931
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId] = displayName;
|
|
16932
|
-
});
|
|
16933
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId}`);
|
|
16934
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
17016
|
+
await ensureLineWorkspaceDisplayNamesLoaded(lineId);
|
|
17017
|
+
console.log(`\u2705 Added workspaces for line ${lineId}`);
|
|
16935
17018
|
} catch (error) {
|
|
16936
17019
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16937
17020
|
}
|
|
@@ -16968,13 +17051,8 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
16968
17051
|
}
|
|
16969
17052
|
if (isInitialized && lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
16970
17053
|
console.log(`\u{1F504} Line ${lineId} not in cache, fetching its workspaces...`);
|
|
16971
|
-
|
|
16972
|
-
|
|
16973
|
-
lineDisplayNamesMap.forEach((displayName2, workspaceId2) => {
|
|
16974
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId2] = displayName2;
|
|
16975
|
-
});
|
|
16976
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId} to cache`);
|
|
16977
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
17054
|
+
ensureLineWorkspaceDisplayNamesLoaded(lineId).then(() => {
|
|
17055
|
+
console.log(`\u2705 Added workspaces for line ${lineId} to cache`);
|
|
16978
17056
|
}).catch((error) => {
|
|
16979
17057
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
16980
17058
|
});
|
|
@@ -17016,13 +17094,8 @@ var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
17016
17094
|
}
|
|
17017
17095
|
if (isInitialized && lineId && !runtimeWorkspaceDisplayNames[lineId]) {
|
|
17018
17096
|
console.log(`\u{1F504} Line ${lineId} not in cache, fetching its workspaces...`);
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
lineDisplayNamesMap.forEach((displayName2, workspaceId2) => {
|
|
17022
|
-
runtimeWorkspaceDisplayNames[lineId][workspaceId2] = displayName2;
|
|
17023
|
-
});
|
|
17024
|
-
console.log(`\u2705 Added ${lineDisplayNamesMap.size} workspaces for line ${lineId} to cache`);
|
|
17025
|
-
notifyWorkspaceDisplayNamesListeners(lineId);
|
|
17097
|
+
ensureLineWorkspaceDisplayNamesLoaded(lineId).then(() => {
|
|
17098
|
+
console.log(`\u2705 Added workspaces for line ${lineId} to cache`);
|
|
17026
17099
|
}).catch((error) => {
|
|
17027
17100
|
console.error(`\u274C Failed to fetch workspaces for line ${lineId}:`, error);
|
|
17028
17101
|
});
|
|
@@ -17102,6 +17175,7 @@ var refreshWorkspaceDisplayNames = async (companyId) => {
|
|
|
17102
17175
|
workspaceService.clearWorkspaceDisplayNamesCache();
|
|
17103
17176
|
runtimeWorkspaceDisplayNames = {};
|
|
17104
17177
|
isInitialized = false;
|
|
17178
|
+
lineLoadPromises.clear();
|
|
17105
17179
|
await initializeWorkspaceDisplayNames();
|
|
17106
17180
|
notifyWorkspaceDisplayNamesListeners();
|
|
17107
17181
|
};
|
|
@@ -17111,6 +17185,7 @@ var clearWorkspaceDisplayNamesCache = () => {
|
|
|
17111
17185
|
isInitialized = false;
|
|
17112
17186
|
isInitializing = false;
|
|
17113
17187
|
initializedWithLineIds = [];
|
|
17188
|
+
lineLoadPromises.clear();
|
|
17114
17189
|
initializationPromise = null;
|
|
17115
17190
|
notifyWorkspaceDisplayNamesListeners();
|
|
17116
17191
|
};
|
|
@@ -17240,7 +17315,16 @@ var useWorkspaceDisplayNamesMap = (workspaceIds, lineId, companyId) => {
|
|
|
17240
17315
|
refetch: fetchDisplayNames
|
|
17241
17316
|
};
|
|
17242
17317
|
};
|
|
17243
|
-
var useWorkspaceVideoStreams = (workspaces) => {
|
|
17318
|
+
var useWorkspaceVideoStreams = (workspaces, options = {}) => {
|
|
17319
|
+
const explicitLineIdsKey = React143.useMemo(() => {
|
|
17320
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17321
|
+
for (const lineId of options.lineIds || []) {
|
|
17322
|
+
if (lineId) {
|
|
17323
|
+
ids.add(lineId);
|
|
17324
|
+
}
|
|
17325
|
+
}
|
|
17326
|
+
return Array.from(ids).sort().join(",");
|
|
17327
|
+
}, [options.lineIds]);
|
|
17244
17328
|
const workspaceIdsKey = React143.useMemo(() => {
|
|
17245
17329
|
const ids = /* @__PURE__ */ new Set();
|
|
17246
17330
|
for (const workspace of workspaces) {
|
|
@@ -17250,7 +17334,7 @@ var useWorkspaceVideoStreams = (workspaces) => {
|
|
|
17250
17334
|
}
|
|
17251
17335
|
return Array.from(ids).sort().join(",");
|
|
17252
17336
|
}, [workspaces]);
|
|
17253
|
-
const
|
|
17337
|
+
const inferredLineIdsKey = React143.useMemo(() => {
|
|
17254
17338
|
const ids = /* @__PURE__ */ new Set();
|
|
17255
17339
|
for (const workspace of workspaces) {
|
|
17256
17340
|
if (workspace.line_id) {
|
|
@@ -17259,18 +17343,19 @@ var useWorkspaceVideoStreams = (workspaces) => {
|
|
|
17259
17343
|
}
|
|
17260
17344
|
return Array.from(ids).sort().join(",");
|
|
17261
17345
|
}, [workspaces]);
|
|
17346
|
+
const lineIdsKey = explicitLineIdsKey || inferredLineIdsKey;
|
|
17262
17347
|
const requestKey = React143.useMemo(() => {
|
|
17263
|
-
if (workspaceIdsKey) {
|
|
17264
|
-
return `workspaces:${workspaceIdsKey}`;
|
|
17265
|
-
}
|
|
17266
17348
|
if (lineIdsKey) {
|
|
17267
17349
|
return `lines:${lineIdsKey}`;
|
|
17268
17350
|
}
|
|
17351
|
+
if (workspaceIdsKey) {
|
|
17352
|
+
return `workspaces:${workspaceIdsKey}`;
|
|
17353
|
+
}
|
|
17269
17354
|
return "";
|
|
17270
17355
|
}, [workspaceIdsKey, lineIdsKey]);
|
|
17271
17356
|
const workspaceIds = React143.useMemo(
|
|
17272
|
-
() => workspaceIdsKey ? workspaceIdsKey.split(",") : [],
|
|
17273
|
-
[workspaceIdsKey]
|
|
17357
|
+
() => lineIdsKey ? [] : workspaceIdsKey ? workspaceIdsKey.split(",") : [],
|
|
17358
|
+
[lineIdsKey, workspaceIdsKey]
|
|
17274
17359
|
);
|
|
17275
17360
|
const lineIds = React143.useMemo(
|
|
17276
17361
|
() => lineIdsKey ? lineIdsKey.split(",") : [],
|
|
@@ -18814,6 +18899,7 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18814
18899
|
const supabase = useSupabase();
|
|
18815
18900
|
const databaseConfig = useDatabaseConfig();
|
|
18816
18901
|
const refreshInterval = options.refreshInterval ?? DEFAULT_REFRESH_INTERVAL_MS;
|
|
18902
|
+
const enabled = options.enabled ?? true;
|
|
18817
18903
|
const workspaceIdsKey = React143.useMemo(() => {
|
|
18818
18904
|
const ids = Array.from(new Set(workspaceIds.filter(Boolean)));
|
|
18819
18905
|
return ids.sort().join(",");
|
|
@@ -18824,7 +18910,7 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18824
18910
|
const isFetchingRef = React143.useRef(false);
|
|
18825
18911
|
const refreshIntervalRef = React143.useRef(null);
|
|
18826
18912
|
const fetchLastSeen = React143.useCallback(async () => {
|
|
18827
|
-
if (!supabase || !workspaceIdsKey || isFetchingRef.current) return;
|
|
18913
|
+
if (!enabled || !supabase || !workspaceIdsKey || isFetchingRef.current) return;
|
|
18828
18914
|
const healthTable = databaseConfig?.tables?.workspace_health || "workspace_health_status";
|
|
18829
18915
|
try {
|
|
18830
18916
|
isFetchingRef.current = true;
|
|
@@ -18856,12 +18942,18 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18856
18942
|
setIsLoading(false);
|
|
18857
18943
|
isFetchingRef.current = false;
|
|
18858
18944
|
}
|
|
18859
|
-
}, [
|
|
18945
|
+
}, [databaseConfig?.tables?.workspace_health, enabled, supabase, workspaceIdsKey]);
|
|
18860
18946
|
React143.useEffect(() => {
|
|
18947
|
+
if (!enabled) {
|
|
18948
|
+
setIsLoading(false);
|
|
18949
|
+
setError(null);
|
|
18950
|
+
setLastSeenByWorkspaceId({});
|
|
18951
|
+
return;
|
|
18952
|
+
}
|
|
18861
18953
|
fetchLastSeen();
|
|
18862
|
-
}, [fetchLastSeen]);
|
|
18954
|
+
}, [enabled, fetchLastSeen]);
|
|
18863
18955
|
React143.useEffect(() => {
|
|
18864
|
-
if (!refreshInterval || !workspaceIdsKey) return;
|
|
18956
|
+
if (!enabled || !refreshInterval || !workspaceIdsKey) return;
|
|
18865
18957
|
refreshIntervalRef.current = setInterval(() => {
|
|
18866
18958
|
fetchLastSeen();
|
|
18867
18959
|
}, refreshInterval);
|
|
@@ -18871,7 +18963,7 @@ var useWorkspaceHealthLastSeen = (workspaceIds, options = {}) => {
|
|
|
18871
18963
|
refreshIntervalRef.current = null;
|
|
18872
18964
|
}
|
|
18873
18965
|
};
|
|
18874
|
-
}, [fetchLastSeen, refreshInterval, workspaceIdsKey]);
|
|
18966
|
+
}, [enabled, fetchLastSeen, refreshInterval, workspaceIdsKey]);
|
|
18875
18967
|
return {
|
|
18876
18968
|
lastSeenByWorkspaceId,
|
|
18877
18969
|
isLoading,
|
|
@@ -34704,7 +34796,7 @@ var VideoCard = React143__namespace.default.memo(({
|
|
|
34704
34796
|
});
|
|
34705
34797
|
const showOffline = Boolean(isStreamStale);
|
|
34706
34798
|
const lastSeenText = lastSeenLabel || "Unknown";
|
|
34707
|
-
const workspaceDisplayName = displayName ||
|
|
34799
|
+
const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
|
|
34708
34800
|
const videoGridMetricValue = getVideoGridMetricValue(workspace);
|
|
34709
34801
|
const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
|
|
34710
34802
|
const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
|
|
@@ -34917,7 +35009,10 @@ var VideoGridView = React143__namespace.default.memo(({
|
|
|
34917
35009
|
}
|
|
34918
35010
|
return Array.from(ids);
|
|
34919
35011
|
}, [workspaces]);
|
|
34920
|
-
const
|
|
35012
|
+
const healthFetchEnabled = !videoStreamsLoading && workspaces.length > 0;
|
|
35013
|
+
const { lastSeenByWorkspaceId } = useWorkspaceHealthLastSeen(workspaceHealthIds, {
|
|
35014
|
+
enabled: healthFetchEnabled
|
|
35015
|
+
});
|
|
34921
35016
|
React143.useEffect(() => {
|
|
34922
35017
|
const sample = workspaces.slice(0, 3).map((workspace) => ({
|
|
34923
35018
|
id: workspace.workspace_uuid || workspace.workspace_name,
|
|
@@ -35016,6 +35111,9 @@ var VideoGridView = React143__namespace.default.memo(({
|
|
|
35016
35111
|
}, [sortedWorkspaces, lineOrder, lineNames]);
|
|
35017
35112
|
lineGroups.length > 1;
|
|
35018
35113
|
const streamsReady = !videoStreamsLoading;
|
|
35114
|
+
const resolveWorkspaceDisplayName = React143.useCallback((workspace) => {
|
|
35115
|
+
return workspace.displayName || displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || workspace.workspace_name;
|
|
35116
|
+
}, [displayNames]);
|
|
35019
35117
|
const calculateOptimalGrid = React143.useCallback(() => {
|
|
35020
35118
|
if (!containerRef.current) return;
|
|
35021
35119
|
const containerPadding = 16;
|
|
@@ -35146,11 +35244,11 @@ var VideoGridView = React143__namespace.default.memo(({
|
|
|
35146
35244
|
efficiency: workspace.efficiency,
|
|
35147
35245
|
action_count: workspace.action_count
|
|
35148
35246
|
});
|
|
35149
|
-
const displayName =
|
|
35247
|
+
const displayName = resolveWorkspaceDisplayName(workspace);
|
|
35150
35248
|
const currentPath = (router$1.asPath || "/").split("#")[0];
|
|
35151
35249
|
const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
|
|
35152
35250
|
router$1.push(`/workspace/${workspaceId}${navParams}`);
|
|
35153
|
-
}, [router$1, prewarmClipsInit]);
|
|
35251
|
+
}, [resolveWorkspaceDisplayName, router$1, prewarmClipsInit]);
|
|
35154
35252
|
const handleStreamError = React143.useCallback((workspaceId, options) => {
|
|
35155
35253
|
const isR2Stream = options?.isR2Stream ?? false;
|
|
35156
35254
|
const hasFallback = Boolean(options?.fallbackUrl);
|
|
@@ -35259,7 +35357,7 @@ var VideoGridView = React143__namespace.default.memo(({
|
|
|
35259
35357
|
legend: effectiveLegend,
|
|
35260
35358
|
cropping: card.workspaceCropping,
|
|
35261
35359
|
canvasFps: effectiveCanvasFps,
|
|
35262
|
-
displayName:
|
|
35360
|
+
displayName: resolveWorkspaceDisplayName(card.workspace),
|
|
35263
35361
|
lastSeenLabel: card.lastSeenLabel,
|
|
35264
35362
|
useRAF: effectiveUseRAF,
|
|
35265
35363
|
displayMinuteBucket,
|
|
@@ -35271,16 +35369,15 @@ var VideoGridView = React143__namespace.default.memo(({
|
|
|
35271
35369
|
},
|
|
35272
35370
|
card.workspaceKey
|
|
35273
35371
|
), [
|
|
35274
|
-
displayNames,
|
|
35275
35372
|
displayMinuteBucket,
|
|
35276
35373
|
effectiveCanvasFps,
|
|
35277
35374
|
effectiveLegend,
|
|
35278
35375
|
effectiveUseRAF,
|
|
35279
|
-
getWorkspaceDisplayName,
|
|
35280
35376
|
handleStreamError,
|
|
35281
35377
|
handleWorkspaceClick,
|
|
35282
35378
|
onWorkspaceHover,
|
|
35283
35379
|
onWorkspaceHoverEnd,
|
|
35380
|
+
resolveWorkspaceDisplayName,
|
|
35284
35381
|
selectedLine
|
|
35285
35382
|
]);
|
|
35286
35383
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative overflow-hidden h-full w-full bg-slate-50/30 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -35366,6 +35463,9 @@ var MapGridView = React143__namespace.default.memo(({
|
|
|
35366
35463
|
prewarmInFlightRef.current.delete(workspaceId);
|
|
35367
35464
|
});
|
|
35368
35465
|
}, [dashboardConfig, timezone, supabase]);
|
|
35466
|
+
const resolveWorkspaceDisplayName = React143.useCallback((workspace) => {
|
|
35467
|
+
return workspace.displayName || displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || workspace.workspace_name;
|
|
35468
|
+
}, [displayNames]);
|
|
35369
35469
|
const handleWorkspaceClick = React143.useCallback((workspace) => {
|
|
35370
35470
|
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
35371
35471
|
prewarmClipsInit(workspace);
|
|
@@ -35377,12 +35477,11 @@ var MapGridView = React143__namespace.default.memo(({
|
|
|
35377
35477
|
efficiency: workspace.efficiency,
|
|
35378
35478
|
action_count: workspace.action_count
|
|
35379
35479
|
});
|
|
35380
|
-
const displayName =
|
|
35381
|
-
getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
35480
|
+
const displayName = resolveWorkspaceDisplayName(workspace);
|
|
35382
35481
|
const currentPath = (router$1.asPath || "/").split("#")[0];
|
|
35383
35482
|
const navParams = getWorkspaceNavigationParams(workspaceId, displayName, workspace.line_id, currentPath);
|
|
35384
35483
|
router$1.push(`/workspace/${workspaceId}${navParams}`);
|
|
35385
|
-
}, [router$1,
|
|
35484
|
+
}, [resolveWorkspaceDisplayName, router$1, prewarmClipsInit]);
|
|
35386
35485
|
const activePositions = React143.useMemo(() => {
|
|
35387
35486
|
return workspacePositions.filter((pos) => {
|
|
35388
35487
|
const wsKey = pos.id.toUpperCase();
|
|
@@ -35412,7 +35511,18 @@ var MapGridView = React143__namespace.default.memo(({
|
|
|
35412
35511
|
workspace_uuid: position.id,
|
|
35413
35512
|
// Use config ID as temporary UUID
|
|
35414
35513
|
line_id: "",
|
|
35514
|
+
// Empty line ID
|
|
35515
|
+
company_id: "",
|
|
35516
|
+
shift_id: 0,
|
|
35517
|
+
date: "",
|
|
35415
35518
|
efficiency: 0,
|
|
35519
|
+
performance_score: 0,
|
|
35520
|
+
action_count: 0,
|
|
35521
|
+
pph: 0,
|
|
35522
|
+
avg_cycle_time: 0,
|
|
35523
|
+
trend: 0,
|
|
35524
|
+
predicted_output: 0,
|
|
35525
|
+
action_threshold: 0,
|
|
35416
35526
|
show_exclamation: false
|
|
35417
35527
|
};
|
|
35418
35528
|
const workspaceId = effectiveWorkspace.workspace_uuid || effectiveWorkspace.workspace_name;
|
|
@@ -35421,7 +35531,7 @@ var MapGridView = React143__namespace.default.memo(({
|
|
|
35421
35531
|
const performanceColor = isInactivePlaceholder || isConveyorRow ? "bg-slate-200 border-slate-300 text-slate-500" : getPerformanceColor(effectiveWorkspace.efficiency);
|
|
35422
35532
|
!isInactivePlaceholder && !isConveyorRow && (effectiveWorkspace.show_exclamation ?? (effectiveWorkspace.efficiency < 50 && effectiveWorkspace.efficiency >= 10));
|
|
35423
35533
|
const configLabel = position.label;
|
|
35424
|
-
const workspaceDisplayName = configLabel || (isInactivePlaceholder ? "INACTIVE" :
|
|
35534
|
+
const workspaceDisplayName = configLabel || (isInactivePlaceholder ? "INACTIVE" : resolveWorkspaceDisplayName(effectiveWorkspace) || position.id);
|
|
35425
35535
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
35426
35536
|
motion.div,
|
|
35427
35537
|
{
|
|
@@ -39388,9 +39498,12 @@ SelectSeparator.displayName = SelectPrimitive__namespace.Separator.displayName;
|
|
|
39388
39498
|
var LoadingOverlay = ({
|
|
39389
39499
|
isVisible,
|
|
39390
39500
|
message = "Loading...",
|
|
39391
|
-
className
|
|
39501
|
+
className,
|
|
39502
|
+
contentClassName,
|
|
39503
|
+
contentVariant = "card"
|
|
39392
39504
|
}) => {
|
|
39393
39505
|
if (!isVisible) return null;
|
|
39506
|
+
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";
|
|
39394
39507
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39395
39508
|
motion.div,
|
|
39396
39509
|
{
|
|
@@ -39401,7 +39514,7 @@ var LoadingOverlay = ({
|
|
|
39401
39514
|
className: `fixed inset-0 z-[100] flex items-center justify-center bg-black/30 backdrop-blur-sm ${className || ""}`,
|
|
39402
39515
|
"aria-modal": "true",
|
|
39403
39516
|
role: "dialog",
|
|
39404
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
39517
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${contentClasses} ${contentClassName || ""}`, children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message }) })
|
|
39405
39518
|
}
|
|
39406
39519
|
);
|
|
39407
39520
|
};
|
|
@@ -60731,6 +60844,353 @@ var HelpView = ({
|
|
|
60731
60844
|
};
|
|
60732
60845
|
var AuthenticatedHelpView = withAuth(HelpView);
|
|
60733
60846
|
var HelpView_default = HelpView;
|
|
60847
|
+
var sortWorkspaceMetrics = (left, right) => {
|
|
60848
|
+
if (left.line_id !== right.line_id) {
|
|
60849
|
+
return left.line_id.localeCompare(right.line_id);
|
|
60850
|
+
}
|
|
60851
|
+
return left.workspace_name.localeCompare(right.workspace_name, void 0, { numeric: true });
|
|
60852
|
+
};
|
|
60853
|
+
var transformWorkspaceMetrics = (rows) => (rows || []).map((item) => {
|
|
60854
|
+
const actionFamily = normalizeActionFamily({
|
|
60855
|
+
actionFamily: item.action_family,
|
|
60856
|
+
actionType: item.action_type,
|
|
60857
|
+
actionName: item.action_name
|
|
60858
|
+
});
|
|
60859
|
+
const actionType = actionFamily === "assembly" || actionFamily === "output" ? actionFamily : null;
|
|
60860
|
+
const metric = {
|
|
60861
|
+
company_id: item.company_id || "",
|
|
60862
|
+
line_id: item.line_id,
|
|
60863
|
+
shift_id: item.shift_id,
|
|
60864
|
+
date: item.date,
|
|
60865
|
+
workspace_uuid: item.workspace_id,
|
|
60866
|
+
workspace_name: item.workspace_name,
|
|
60867
|
+
displayName: item.workspace_display_name || item.display_name || void 0,
|
|
60868
|
+
action_count: item.total_output || 0,
|
|
60869
|
+
pph: item.avg_pph || 0,
|
|
60870
|
+
performance_score: item.performance_score || 0,
|
|
60871
|
+
avg_cycle_time: item.avg_cycle_time || 0,
|
|
60872
|
+
ideal_cycle_time: item.ideal_cycle_time || void 0,
|
|
60873
|
+
trend: item.trend_score === 1 ? 2 : 0,
|
|
60874
|
+
predicted_output: item.ideal_output || 0,
|
|
60875
|
+
efficiency: item.efficiency || 0,
|
|
60876
|
+
action_threshold: item.total_day_output || 0,
|
|
60877
|
+
monitoring_mode: item.monitoring_mode ?? void 0,
|
|
60878
|
+
idle_time: typeof item.idle_time === "number" ? item.idle_time : Number(item.idle_time),
|
|
60879
|
+
idle_time_hourly: item.idle_time_hourly ?? null,
|
|
60880
|
+
shift_start: item.shift_start ?? void 0,
|
|
60881
|
+
shift_end: item.shift_end ?? void 0,
|
|
60882
|
+
assembly_enabled: item.assembly_enabled ?? false,
|
|
60883
|
+
video_grid_metric_mode: normalizeVideoGridMetricMode(
|
|
60884
|
+
item.video_grid_metric_mode,
|
|
60885
|
+
item.assembly_enabled ?? false
|
|
60886
|
+
),
|
|
60887
|
+
action_type: actionType,
|
|
60888
|
+
action_family: actionFamily,
|
|
60889
|
+
action_display_name: getActionDisplayName({
|
|
60890
|
+
displayName: item.action_display_name,
|
|
60891
|
+
actionFamily: item.action_family,
|
|
60892
|
+
actionType: item.action_type,
|
|
60893
|
+
actionName: item.action_name
|
|
60894
|
+
}),
|
|
60895
|
+
recent_flow_percent: item.recent_flow_percent ?? null,
|
|
60896
|
+
recent_flow_window_minutes: item.recent_flow_window_minutes ?? null,
|
|
60897
|
+
recent_flow_effective_end_at: item.recent_flow_effective_end_at ?? null,
|
|
60898
|
+
recent_flow_computed_at: item.recent_flow_computed_at ?? null,
|
|
60899
|
+
scheduled_break_active: item.scheduled_break_active ?? false,
|
|
60900
|
+
incoming_wip_current: item.incoming_wip_current ?? null,
|
|
60901
|
+
incoming_wip_effective_at: item.incoming_wip_effective_at ?? null,
|
|
60902
|
+
incoming_wip_buffer_name: item.incoming_wip_buffer_name ?? null,
|
|
60903
|
+
show_exclamation: item.show_exclamation ?? void 0
|
|
60904
|
+
};
|
|
60905
|
+
workspaceMetricsStore.setOverview(metric);
|
|
60906
|
+
return metric;
|
|
60907
|
+
}).sort(sortWorkspaceMetrics);
|
|
60908
|
+
var transformActiveBreaks = (activeBreaksByLine) => {
|
|
60909
|
+
if (!activeBreaksByLine) return [];
|
|
60910
|
+
return Object.values(activeBreaksByLine).flat().map((item) => ({
|
|
60911
|
+
lineId: item.line_id,
|
|
60912
|
+
shiftName: item.shift_name || "",
|
|
60913
|
+
startTime: item.start_time,
|
|
60914
|
+
endTime: item.end_time,
|
|
60915
|
+
duration: item.duration || 0,
|
|
60916
|
+
remarks: item.remarks || "",
|
|
60917
|
+
elapsedMinutes: item.elapsed_minutes || 0,
|
|
60918
|
+
remainingMinutes: item.remaining_minutes || 0
|
|
60919
|
+
})).sort((left, right) => {
|
|
60920
|
+
if (left.lineId !== right.lineId) return left.lineId.localeCompare(right.lineId);
|
|
60921
|
+
if (left.shiftName !== right.shiftName) return left.shiftName.localeCompare(right.shiftName);
|
|
60922
|
+
return left.startTime.localeCompare(right.startTime);
|
|
60923
|
+
});
|
|
60924
|
+
};
|
|
60925
|
+
var createEmptyState = () => ({
|
|
60926
|
+
requestKey: null,
|
|
60927
|
+
resolvedScope: [],
|
|
60928
|
+
scopeKey: null,
|
|
60929
|
+
lines: [],
|
|
60930
|
+
workspaceMetrics: [],
|
|
60931
|
+
lineMetrics: [],
|
|
60932
|
+
kpiTrend: null,
|
|
60933
|
+
activeBreaks: [],
|
|
60934
|
+
videoStreamsByWorkspaceId: {},
|
|
60935
|
+
efficiencyLegend: null,
|
|
60936
|
+
metadata: {}
|
|
60937
|
+
});
|
|
60938
|
+
var normalizeMetadata = (metadata) => ({
|
|
60939
|
+
hasFlowBuffers: Boolean(metadata?.has_flow_buffers),
|
|
60940
|
+
idleTimeVlmByLine: metadata?.idle_time_vlm_by_line ?? {},
|
|
60941
|
+
generatedAt: metadata?.generated_at,
|
|
60942
|
+
cacheStatus: metadata?.cache_status,
|
|
60943
|
+
warnings: metadata?.warnings ?? []
|
|
60944
|
+
});
|
|
60945
|
+
var useLiveMonitorBootstrap = ({
|
|
60946
|
+
lineIds,
|
|
60947
|
+
companyId,
|
|
60948
|
+
enabled = true
|
|
60949
|
+
}) => {
|
|
60950
|
+
const supabase = useSupabase();
|
|
60951
|
+
const entityConfig = useEntityConfig();
|
|
60952
|
+
const { hydrateFromBackend } = useIdleTimeVlmConfig();
|
|
60953
|
+
const resolvedCompanyId = companyId || entityConfig?.companyId;
|
|
60954
|
+
const rawLineIdsKey = (lineIds || []).filter(Boolean).join(",");
|
|
60955
|
+
const normalizedLineIds = React143.useMemo(
|
|
60956
|
+
() => Array.from(new Set(rawLineIdsKey ? rawLineIdsKey.split(",") : [])),
|
|
60957
|
+
[rawLineIdsKey]
|
|
60958
|
+
);
|
|
60959
|
+
const requestKey = React143.useMemo(
|
|
60960
|
+
() => normalizedLineIds.slice().sort().join(","),
|
|
60961
|
+
[normalizedLineIds]
|
|
60962
|
+
);
|
|
60963
|
+
const [state, setState] = React143.useState(() => createEmptyState());
|
|
60964
|
+
const [isLoading, setIsLoading] = React143.useState(false);
|
|
60965
|
+
const [error, setError] = React143.useState(null);
|
|
60966
|
+
const activeRequestIdRef = React143.useRef(0);
|
|
60967
|
+
const fetchBootstrap = React143.useCallback(async (force = false) => {
|
|
60968
|
+
if (!enabled || !supabase || !resolvedCompanyId || normalizedLineIds.length === 0) {
|
|
60969
|
+
return;
|
|
60970
|
+
}
|
|
60971
|
+
const requestId = ++activeRequestIdRef.current;
|
|
60972
|
+
setIsLoading(true);
|
|
60973
|
+
setError(null);
|
|
60974
|
+
try {
|
|
60975
|
+
const searchParams = new URLSearchParams();
|
|
60976
|
+
searchParams.set("company_id", resolvedCompanyId);
|
|
60977
|
+
searchParams.set("line_ids", normalizedLineIds.join(","));
|
|
60978
|
+
if (force) {
|
|
60979
|
+
searchParams.set("force_refresh", "true");
|
|
60980
|
+
}
|
|
60981
|
+
const response = await fetchBackendJson(
|
|
60982
|
+
supabase,
|
|
60983
|
+
`/api/dashboard/monitor-bootstrap?${searchParams.toString()}`,
|
|
60984
|
+
{
|
|
60985
|
+
method: "GET",
|
|
60986
|
+
timeoutMs: 2e4,
|
|
60987
|
+
retries: 0,
|
|
60988
|
+
dedupeKey: `monitor-bootstrap::${requestKey}::${force ? "force" : "cached"}`
|
|
60989
|
+
}
|
|
60990
|
+
);
|
|
60991
|
+
if (requestId !== activeRequestIdRef.current) {
|
|
60992
|
+
return;
|
|
60993
|
+
}
|
|
60994
|
+
const workspaceMetrics = transformWorkspaceMetrics(response.workspace_metrics || []);
|
|
60995
|
+
const activeBreaks = transformActiveBreaks(response.active_breaks_by_line);
|
|
60996
|
+
const metadata = normalizeMetadata(response.metadata);
|
|
60997
|
+
if (metadata.idleTimeVlmByLine) {
|
|
60998
|
+
hydrateFromBackend(metadata.idleTimeVlmByLine);
|
|
60999
|
+
}
|
|
61000
|
+
setState({
|
|
61001
|
+
requestKey,
|
|
61002
|
+
resolvedScope: response.resolved_scope || [],
|
|
61003
|
+
scopeKey: response.scope_key || null,
|
|
61004
|
+
lines: response.lines || [],
|
|
61005
|
+
workspaceMetrics,
|
|
61006
|
+
lineMetrics: response.line_metrics || [],
|
|
61007
|
+
kpiTrend: response.kpi_trend || null,
|
|
61008
|
+
activeBreaks,
|
|
61009
|
+
videoStreamsByWorkspaceId: response.video_streams_by_workspace_id || {},
|
|
61010
|
+
efficiencyLegend: response.efficiency_legend || null,
|
|
61011
|
+
metadata
|
|
61012
|
+
});
|
|
61013
|
+
} catch (fetchError) {
|
|
61014
|
+
if (requestId !== activeRequestIdRef.current) {
|
|
61015
|
+
return;
|
|
61016
|
+
}
|
|
61017
|
+
setError(fetchError instanceof Error ? fetchError : new Error("Failed to load live monitor bootstrap"));
|
|
61018
|
+
} finally {
|
|
61019
|
+
if (requestId === activeRequestIdRef.current) {
|
|
61020
|
+
setIsLoading(false);
|
|
61021
|
+
}
|
|
61022
|
+
}
|
|
61023
|
+
}, [enabled, supabase, resolvedCompanyId, normalizedLineIds, requestKey, hydrateFromBackend]);
|
|
61024
|
+
React143.useEffect(() => {
|
|
61025
|
+
if (!enabled) {
|
|
61026
|
+
setIsLoading(false);
|
|
61027
|
+
return;
|
|
61028
|
+
}
|
|
61029
|
+
if (!resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
61030
|
+
setState(createEmptyState());
|
|
61031
|
+
setIsLoading(false);
|
|
61032
|
+
setError(null);
|
|
61033
|
+
return;
|
|
61034
|
+
}
|
|
61035
|
+
void fetchBootstrap(false);
|
|
61036
|
+
}, [enabled, resolvedCompanyId, normalizedLineIds, supabase, fetchBootstrap]);
|
|
61037
|
+
React143.useEffect(() => {
|
|
61038
|
+
if (!enabled || !resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
61039
|
+
return void 0;
|
|
61040
|
+
}
|
|
61041
|
+
let intervalId = null;
|
|
61042
|
+
let timeoutId = null;
|
|
61043
|
+
const runMinuteTick = () => {
|
|
61044
|
+
void fetchBootstrap(true);
|
|
61045
|
+
};
|
|
61046
|
+
const startInterval = () => {
|
|
61047
|
+
runMinuteTick();
|
|
61048
|
+
intervalId = window.setInterval(runMinuteTick, 6e4);
|
|
61049
|
+
};
|
|
61050
|
+
const msUntilNextMinute = (() => {
|
|
61051
|
+
const remainder = Date.now() % 6e4;
|
|
61052
|
+
return remainder === 0 ? 6e4 : 6e4 - remainder;
|
|
61053
|
+
})();
|
|
61054
|
+
timeoutId = window.setTimeout(startInterval, msUntilNextMinute);
|
|
61055
|
+
return () => {
|
|
61056
|
+
if (timeoutId !== null) {
|
|
61057
|
+
window.clearTimeout(timeoutId);
|
|
61058
|
+
}
|
|
61059
|
+
if (intervalId !== null) {
|
|
61060
|
+
window.clearInterval(intervalId);
|
|
61061
|
+
}
|
|
61062
|
+
};
|
|
61063
|
+
}, [enabled, resolvedCompanyId, normalizedLineIds, supabase, fetchBootstrap]);
|
|
61064
|
+
const isCurrentScopeResolved = state.requestKey === requestKey;
|
|
61065
|
+
return {
|
|
61066
|
+
resolvedScope: state.resolvedScope,
|
|
61067
|
+
scopeKey: state.scopeKey,
|
|
61068
|
+
lines: state.lines,
|
|
61069
|
+
workspaceMetrics: state.workspaceMetrics,
|
|
61070
|
+
lineMetrics: state.lineMetrics,
|
|
61071
|
+
kpiTrend: state.kpiTrend,
|
|
61072
|
+
activeBreaks: state.activeBreaks,
|
|
61073
|
+
videoStreamsByWorkspaceId: state.videoStreamsByWorkspaceId,
|
|
61074
|
+
efficiencyLegend: state.efficiencyLegend,
|
|
61075
|
+
metadata: state.metadata,
|
|
61076
|
+
isLoading: enabled ? isLoading || !isCurrentScopeResolved : false,
|
|
61077
|
+
isCurrentScopeResolved,
|
|
61078
|
+
error,
|
|
61079
|
+
refetch: () => fetchBootstrap(true)
|
|
61080
|
+
};
|
|
61081
|
+
};
|
|
61082
|
+
|
|
61083
|
+
// src/lib/utils/liveMonitorBootstrap.ts
|
|
61084
|
+
var toNumber3 = (value) => {
|
|
61085
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
61086
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
61087
|
+
const parsed = Number(value);
|
|
61088
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
61089
|
+
}
|
|
61090
|
+
return 0;
|
|
61091
|
+
};
|
|
61092
|
+
var normalizeNullableNumber = (value) => {
|
|
61093
|
+
if (value === null || value === void 0 || value === "") return null;
|
|
61094
|
+
return toNumber3(value);
|
|
61095
|
+
};
|
|
61096
|
+
var getLiveMonitorBootstrapMode = () => {
|
|
61097
|
+
const rawMode = (process.env.NEXT_PUBLIC_MONITOR_BOOTSTRAP_MODE || "").trim().toLowerCase();
|
|
61098
|
+
if (rawMode === "legacy" || rawMode === "shadow" || rawMode === "bootstrap") {
|
|
61099
|
+
return rawMode;
|
|
61100
|
+
}
|
|
61101
|
+
return "bootstrap";
|
|
61102
|
+
};
|
|
61103
|
+
var normalizeMonitorShadowSnapshot = (input) => {
|
|
61104
|
+
const sortedSelectedLineIds = Array.from(new Set((input.selectedLineIds || []).filter(Boolean))).sort();
|
|
61105
|
+
const resolvedScope = (input.resolvedScope || []).filter((entry) => entry?.line_id && entry?.date && entry?.shift_id !== void 0 && entry?.shift_id !== null).map((entry) => ({
|
|
61106
|
+
line_id: entry.line_id,
|
|
61107
|
+
date: entry.date,
|
|
61108
|
+
shift_id: entry.shift_id
|
|
61109
|
+
})).sort((left, right) => {
|
|
61110
|
+
if (left.line_id !== right.line_id) return left.line_id.localeCompare(right.line_id);
|
|
61111
|
+
if (left.date !== right.date) return left.date.localeCompare(right.date);
|
|
61112
|
+
return left.shift_id - right.shift_id;
|
|
61113
|
+
});
|
|
61114
|
+
const lines = (input.lines || []).filter((entry) => entry?.line_id).map((entry) => ({
|
|
61115
|
+
line_id: entry.line_id,
|
|
61116
|
+
line_name: entry.line_name || "Unknown Line"
|
|
61117
|
+
})).sort((left, right) => left.line_id.localeCompare(right.line_id));
|
|
61118
|
+
const workspaces = (input.workspaces || []).map((workspace) => {
|
|
61119
|
+
const workspaceId = workspace.workspace_uuid || null;
|
|
61120
|
+
const stream = workspaceId ? input.videoStreamsByWorkspaceId?.[workspaceId] || null : null;
|
|
61121
|
+
return {
|
|
61122
|
+
workspace_id: workspaceId,
|
|
61123
|
+
line_id: workspace.line_id,
|
|
61124
|
+
workspace_name: workspace.workspace_name,
|
|
61125
|
+
display_name: workspace.displayName || null,
|
|
61126
|
+
efficiency: toNumber3(workspace.efficiency),
|
|
61127
|
+
trend: toNumber3(workspace.trend),
|
|
61128
|
+
show_exclamation: Boolean(workspace.show_exclamation),
|
|
61129
|
+
scheduled_break_active: Boolean(workspace.scheduled_break_active),
|
|
61130
|
+
action_count: toNumber3(workspace.action_count),
|
|
61131
|
+
action_threshold: toNumber3(workspace.action_threshold),
|
|
61132
|
+
predicted_output: toNumber3(workspace.predicted_output),
|
|
61133
|
+
avg_cycle_time: toNumber3(workspace.avg_cycle_time),
|
|
61134
|
+
pph: toNumber3(workspace.pph),
|
|
61135
|
+
recent_flow_percent: normalizeNullableNumber(workspace.recent_flow_percent),
|
|
61136
|
+
incoming_wip_current: normalizeNullableNumber(workspace.incoming_wip_current),
|
|
61137
|
+
video_stream: stream ? {
|
|
61138
|
+
workspace_id: stream.workspace_id,
|
|
61139
|
+
camera_uuid: stream.camera_uuid,
|
|
61140
|
+
stream_camera_uuid: stream.stream_camera_uuid,
|
|
61141
|
+
hls_url: stream.hls_url,
|
|
61142
|
+
crop: stream.crop
|
|
61143
|
+
} : null
|
|
61144
|
+
};
|
|
61145
|
+
}).sort((left, right) => {
|
|
61146
|
+
if (left.line_id !== right.line_id) return left.line_id.localeCompare(right.line_id);
|
|
61147
|
+
return left.workspace_name.localeCompare(right.workspace_name, void 0, { numeric: true });
|
|
61148
|
+
});
|
|
61149
|
+
const activeBreaks = (input.activeBreaks || []).map((activeBreak) => ({
|
|
61150
|
+
lineId: activeBreak.lineId,
|
|
61151
|
+
shiftName: activeBreak.shiftName,
|
|
61152
|
+
startTime: activeBreak.startTime,
|
|
61153
|
+
endTime: activeBreak.endTime,
|
|
61154
|
+
remainingMinutes: toNumber3(activeBreak.remainingMinutes)
|
|
61155
|
+
})).sort((left, right) => {
|
|
61156
|
+
if (left.lineId !== right.lineId) return left.lineId.localeCompare(right.lineId);
|
|
61157
|
+
if (left.shiftName !== right.shiftName) return left.shiftName.localeCompare(right.shiftName);
|
|
61158
|
+
return left.startTime.localeCompare(right.startTime);
|
|
61159
|
+
});
|
|
61160
|
+
return {
|
|
61161
|
+
selectedLineIds: sortedSelectedLineIds,
|
|
61162
|
+
resolvedScope,
|
|
61163
|
+
lines,
|
|
61164
|
+
workspaces,
|
|
61165
|
+
activeBreaks,
|
|
61166
|
+
kpis: input.kpis || null,
|
|
61167
|
+
kpiTrend: input.kpiTrend || null,
|
|
61168
|
+
efficiencyLegend: input.efficiencyLegend || null
|
|
61169
|
+
};
|
|
61170
|
+
};
|
|
61171
|
+
var diffMonitorShadowSnapshots = (legacySnapshot, bootstrapSnapshot) => {
|
|
61172
|
+
const mismatches = [];
|
|
61173
|
+
const compareSection = (section) => {
|
|
61174
|
+
const legacyValue = legacySnapshot[section];
|
|
61175
|
+
const bootstrapValue = bootstrapSnapshot[section];
|
|
61176
|
+
if (JSON.stringify(legacyValue) !== JSON.stringify(bootstrapValue)) {
|
|
61177
|
+
mismatches.push({
|
|
61178
|
+
section,
|
|
61179
|
+
legacy: legacyValue,
|
|
61180
|
+
bootstrap: bootstrapValue
|
|
61181
|
+
});
|
|
61182
|
+
}
|
|
61183
|
+
};
|
|
61184
|
+
compareSection("selectedLineIds");
|
|
61185
|
+
compareSection("resolvedScope");
|
|
61186
|
+
compareSection("lines");
|
|
61187
|
+
compareSection("workspaces");
|
|
61188
|
+
compareSection("activeBreaks");
|
|
61189
|
+
compareSection("kpis");
|
|
61190
|
+
compareSection("kpiTrend");
|
|
61191
|
+
compareSection("efficiencyLegend");
|
|
61192
|
+
return mismatches;
|
|
61193
|
+
};
|
|
60734
61194
|
|
|
60735
61195
|
// src/lib/services/notificationService.ts
|
|
60736
61196
|
var API_BASE_URL = process.env.NEXT_PUBLIC_BACKEND_URL;
|
|
@@ -60872,7 +61332,10 @@ var logDebug3 = (...args) => {
|
|
|
60872
61332
|
if (!DEBUG_DASHBOARD_LOGS3) return;
|
|
60873
61333
|
console.log(...args);
|
|
60874
61334
|
};
|
|
61335
|
+
var EMPTY_LINE_IDS = [];
|
|
61336
|
+
var EMPTY_WORKSPACES = [];
|
|
60875
61337
|
var LoadingPageCmp = LoadingPage_default;
|
|
61338
|
+
var LoadingOverlayCmp = LoadingOverlay_default;
|
|
60876
61339
|
function HomeView({
|
|
60877
61340
|
defaultLineId,
|
|
60878
61341
|
factoryViewId,
|
|
@@ -61020,6 +61483,7 @@ function HomeView({
|
|
|
61020
61483
|
return createNotificationService(supabaseClient);
|
|
61021
61484
|
}, [supabaseClient]);
|
|
61022
61485
|
const [bottleneckNotification, setBottleneckNotification] = React143.useState(null);
|
|
61486
|
+
const showBottleneckNotificationRef = React143.useRef(null);
|
|
61023
61487
|
const [bottleneckModalOpen, setBottleneckModalOpen] = React143.useState(false);
|
|
61024
61488
|
const [bottleneckModalData, setBottleneckModalData] = React143.useState(null);
|
|
61025
61489
|
const [diagnosisModalOpen, setDiagnosisModalOpen] = React143.useState(false);
|
|
@@ -61030,6 +61494,11 @@ function HomeView({
|
|
|
61030
61494
|
dashboardConfig?.shiftConfig
|
|
61031
61495
|
);
|
|
61032
61496
|
const shouldEnableMetricsFetch = authStatus === "ready";
|
|
61497
|
+
const liveMonitorMode = React143.useMemo(() => getLiveMonitorBootstrapMode(), []);
|
|
61498
|
+
const isLegacyMonitorMode = liveMonitorMode === "legacy";
|
|
61499
|
+
const isShadowMonitorMode = liveMonitorMode === "shadow";
|
|
61500
|
+
const isBootstrapMonitorMode = liveMonitorMode === "bootstrap";
|
|
61501
|
+
const lastShadowMismatchSignatureRef = React143.useRef(null);
|
|
61033
61502
|
const handleLineMetricsUpdate = React143.useCallback(() => {
|
|
61034
61503
|
if (trendRefreshTimerRef.current) {
|
|
61035
61504
|
window.clearTimeout(trendRefreshTimerRef.current);
|
|
@@ -61045,45 +61514,24 @@ function HomeView({
|
|
|
61045
61514
|
}
|
|
61046
61515
|
}, []);
|
|
61047
61516
|
const {
|
|
61048
|
-
workspaceMetrics,
|
|
61049
|
-
lineMetrics,
|
|
61050
|
-
efficiencyLegend,
|
|
61051
|
-
metadata:
|
|
61052
|
-
isLoading:
|
|
61053
|
-
|
|
61054
|
-
|
|
61517
|
+
workspaceMetrics: legacyWorkspaceMetrics,
|
|
61518
|
+
lineMetrics: legacyLineMetrics,
|
|
61519
|
+
efficiencyLegend: legacyEfficiencyLegend,
|
|
61520
|
+
metadata: legacyMetricsMetadata,
|
|
61521
|
+
isLoading: legacyMetricsLoading,
|
|
61522
|
+
isCurrentScopeResolved: legacyIsCurrentScopeResolved,
|
|
61523
|
+
error: legacyMetricsError,
|
|
61524
|
+
refetch: refetchLegacyMetrics
|
|
61055
61525
|
} = useDashboardMetrics({
|
|
61056
61526
|
lineId: metricsScopeLineId,
|
|
61057
61527
|
lineIds: selectedLineIds,
|
|
61058
61528
|
onLineMetricsUpdate: handleLineMetricsUpdate,
|
|
61059
61529
|
userAccessibleLineIds: visibleLineIds,
|
|
61060
|
-
|
|
61061
|
-
enabled: shouldEnableMetricsFetch
|
|
61530
|
+
enabled: shouldEnableMetricsFetch && !isBootstrapMonitorMode
|
|
61062
61531
|
});
|
|
61063
|
-
const
|
|
61064
|
-
|
|
61065
|
-
|
|
61066
|
-
if (!workspace.displayName) {
|
|
61067
|
-
return;
|
|
61068
|
-
}
|
|
61069
|
-
nextDisplayNames[`${workspace.line_id}_${workspace.workspace_name}`] = workspace.displayName;
|
|
61070
|
-
});
|
|
61071
|
-
return nextDisplayNames;
|
|
61072
|
-
}, [workspaceMetrics]);
|
|
61073
|
-
React143.useEffect(() => {
|
|
61074
|
-
workspaceMetrics.forEach((workspace) => {
|
|
61075
|
-
if (!workspace.displayName) {
|
|
61076
|
-
return;
|
|
61077
|
-
}
|
|
61078
|
-
upsertWorkspaceDisplayNameInCache({
|
|
61079
|
-
lineId: workspace.line_id,
|
|
61080
|
-
workspaceId: workspace.workspace_name,
|
|
61081
|
-
displayName: workspace.displayName
|
|
61082
|
-
});
|
|
61083
|
-
});
|
|
61084
|
-
}, [workspaceMetrics]);
|
|
61085
|
-
const trendGroups = React143.useMemo(() => {
|
|
61086
|
-
const lineMetricsRows = lineMetrics || [];
|
|
61532
|
+
const legacyTrendGroups = React143.useMemo(() => {
|
|
61533
|
+
if (isBootstrapMonitorMode) return null;
|
|
61534
|
+
const lineMetricsRows = legacyLineMetrics || [];
|
|
61087
61535
|
if (!lineMetricsRows.length) return null;
|
|
61088
61536
|
if (selectedLineIds.length > 1) {
|
|
61089
61537
|
const rowsForLines = lineMetricsRows.filter((row2) => selectedLineIdSet.has(row2?.line_id));
|
|
@@ -61109,7 +61557,7 @@ function HomeView({
|
|
|
61109
61557
|
shiftId: group.shiftId
|
|
61110
61558
|
}));
|
|
61111
61559
|
}
|
|
61112
|
-
const row = lineMetricsRows.find((
|
|
61560
|
+
const row = lineMetricsRows.find((candidate) => candidate?.line_id === primarySelectedLineId);
|
|
61113
61561
|
if (!row?.date || row?.shift_id === void 0 || row?.shift_id === null) {
|
|
61114
61562
|
return null;
|
|
61115
61563
|
}
|
|
@@ -61118,69 +61566,115 @@ function HomeView({
|
|
|
61118
61566
|
date: row.date,
|
|
61119
61567
|
shiftId: row.shift_id
|
|
61120
61568
|
}];
|
|
61121
|
-
}, [
|
|
61122
|
-
const
|
|
61123
|
-
if (!
|
|
61569
|
+
}, [isBootstrapMonitorMode, legacyLineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
61570
|
+
const legacyTrendOptions = React143.useMemo(() => {
|
|
61571
|
+
if (isBootstrapMonitorMode || !legacyTrendGroups || !userCompanyId) return null;
|
|
61124
61572
|
return {
|
|
61125
|
-
groups:
|
|
61573
|
+
groups: legacyTrendGroups,
|
|
61126
61574
|
companyId: userCompanyId,
|
|
61127
61575
|
refreshKey: trendRefreshKey,
|
|
61128
61576
|
forceRefresh: trendRefreshKey > 0
|
|
61129
61577
|
};
|
|
61130
|
-
}, [
|
|
61131
|
-
const { trend:
|
|
61132
|
-
const
|
|
61578
|
+
}, [isBootstrapMonitorMode, legacyTrendGroups, userCompanyId, trendRefreshKey]);
|
|
61579
|
+
const { trend: legacyKpiTrend } = useKpiTrends(legacyTrendOptions);
|
|
61580
|
+
const bootstrapMonitor = useLiveMonitorBootstrap({
|
|
61581
|
+
lineIds: selectedLineIds,
|
|
61582
|
+
companyId: userCompanyId,
|
|
61583
|
+
enabled: shouldEnableMetricsFetch && !isLegacyMonitorMode
|
|
61584
|
+
});
|
|
61585
|
+
const currentWorkspaceMetrics = isBootstrapMonitorMode ? bootstrapMonitor.workspaceMetrics : legacyWorkspaceMetrics;
|
|
61586
|
+
const currentLineMetrics = isBootstrapMonitorMode ? bootstrapMonitor.lineMetrics : legacyLineMetrics;
|
|
61587
|
+
const currentEfficiencyLegend = isBootstrapMonitorMode ? bootstrapMonitor.efficiencyLegend : legacyEfficiencyLegend;
|
|
61588
|
+
const currentMetricsMetadata = isBootstrapMonitorMode ? bootstrapMonitor.metadata : legacyMetricsMetadata;
|
|
61589
|
+
const currentMetricsLoading = isBootstrapMonitorMode ? bootstrapMonitor.isLoading : legacyMetricsLoading;
|
|
61590
|
+
const currentIsCurrentScopeResolved = isBootstrapMonitorMode ? bootstrapMonitor.isCurrentScopeResolved : legacyIsCurrentScopeResolved;
|
|
61591
|
+
const currentMetricsError = isBootstrapMonitorMode ? bootstrapMonitor.error : legacyMetricsError;
|
|
61592
|
+
const currentRefetchMetrics = isBootstrapMonitorMode ? bootstrapMonitor.refetch : refetchLegacyMetrics;
|
|
61593
|
+
const metricsDisplayNames = React143.useMemo(() => {
|
|
61594
|
+
const nextDisplayNames = {};
|
|
61595
|
+
currentWorkspaceMetrics.forEach((workspace) => {
|
|
61596
|
+
if (!workspace.displayName) {
|
|
61597
|
+
return;
|
|
61598
|
+
}
|
|
61599
|
+
nextDisplayNames[`${workspace.line_id}_${workspace.workspace_name}`] = workspace.displayName;
|
|
61600
|
+
});
|
|
61601
|
+
return nextDisplayNames;
|
|
61602
|
+
}, [currentWorkspaceMetrics]);
|
|
61603
|
+
React143.useEffect(() => {
|
|
61604
|
+
currentWorkspaceMetrics.forEach((workspace) => {
|
|
61605
|
+
if (!workspace.displayName) {
|
|
61606
|
+
return;
|
|
61607
|
+
}
|
|
61608
|
+
upsertWorkspaceDisplayNameInCache({
|
|
61609
|
+
lineId: workspace.line_id,
|
|
61610
|
+
workspaceId: workspace.workspace_name,
|
|
61611
|
+
displayName: workspace.displayName
|
|
61612
|
+
});
|
|
61613
|
+
});
|
|
61614
|
+
}, [currentWorkspaceMetrics]);
|
|
61615
|
+
const hasFlowBuffers = Boolean(currentMetricsMetadata?.hasFlowBuffers);
|
|
61133
61616
|
React143.useEffect(() => {
|
|
61134
|
-
const sample =
|
|
61617
|
+
const sample = currentWorkspaceMetrics.slice(0, 3).map((workspace) => ({
|
|
61135
61618
|
id: workspace.workspace_uuid || workspace.workspace_name,
|
|
61136
61619
|
efficiency: workspace.efficiency,
|
|
61137
61620
|
trend: workspace.trend,
|
|
61138
61621
|
lineId: workspace.line_id
|
|
61139
61622
|
}));
|
|
61140
61623
|
logDebug3("[HomeView] workspaceMetrics update:", {
|
|
61141
|
-
count:
|
|
61142
|
-
isLoading:
|
|
61143
|
-
error:
|
|
61624
|
+
count: currentWorkspaceMetrics.length,
|
|
61625
|
+
isLoading: currentMetricsLoading,
|
|
61626
|
+
error: currentMetricsError?.message,
|
|
61144
61627
|
sample
|
|
61145
61628
|
});
|
|
61146
|
-
}, [
|
|
61147
|
-
const
|
|
61148
|
-
const lineMetricsRows =
|
|
61629
|
+
}, [currentWorkspaceMetrics, currentMetricsLoading, currentMetricsError]);
|
|
61630
|
+
const buildDisplayKpis = React143.useCallback((sourceLineMetrics, sourceIsLoading, sourceKpiTrend) => {
|
|
61631
|
+
const lineMetricsRows = sourceLineMetrics || [];
|
|
61632
|
+
let baseKpis = null;
|
|
61149
61633
|
if (selectedLineIds.length > 1) {
|
|
61150
|
-
const rowsForSelectedLines = lineMetricsRows.filter((
|
|
61151
|
-
if (
|
|
61152
|
-
|
|
61153
|
-
}
|
|
61154
|
-
|
|
61155
|
-
|
|
61156
|
-
|
|
61157
|
-
|
|
61158
|
-
|
|
61159
|
-
|
|
61160
|
-
|
|
61161
|
-
|
|
61162
|
-
if (!
|
|
61163
|
-
|
|
61634
|
+
const rowsForSelectedLines = lineMetricsRows.filter((row) => selectedLineIdSet.has(row?.line_id));
|
|
61635
|
+
if (sourceIsLoading && rowsForSelectedLines.length === 0) return null;
|
|
61636
|
+
baseKpis = aggregateKPIsFromLineMetricsRows(rowsForSelectedLines);
|
|
61637
|
+
} else {
|
|
61638
|
+
const row = lineMetricsRows.find((candidate) => candidate?.line_id === primarySelectedLineId);
|
|
61639
|
+
if (!row) {
|
|
61640
|
+
if (sourceIsLoading) return null;
|
|
61641
|
+
baseKpis = buildKPIsFromLineMetricsRow(null);
|
|
61642
|
+
} else {
|
|
61643
|
+
baseKpis = buildKPIsFromLineMetricsRow(row);
|
|
61644
|
+
}
|
|
61645
|
+
}
|
|
61646
|
+
if (!baseKpis || !sourceKpiTrend) {
|
|
61647
|
+
return baseKpis;
|
|
61648
|
+
}
|
|
61164
61649
|
return {
|
|
61165
|
-
...
|
|
61650
|
+
...baseKpis,
|
|
61166
61651
|
efficiency: {
|
|
61167
|
-
...
|
|
61168
|
-
change:
|
|
61652
|
+
...baseKpis.efficiency,
|
|
61653
|
+
change: sourceKpiTrend.efficiency?.delta_pp ?? baseKpis.efficiency.change
|
|
61169
61654
|
},
|
|
61170
61655
|
outputProgress: {
|
|
61171
|
-
...
|
|
61172
|
-
change:
|
|
61656
|
+
...baseKpis.outputProgress,
|
|
61657
|
+
change: sourceKpiTrend.outputProgress?.delta_pp ?? baseKpis.outputProgress.change
|
|
61173
61658
|
},
|
|
61174
61659
|
underperformingWorkers: {
|
|
61175
|
-
...
|
|
61176
|
-
change:
|
|
61660
|
+
...baseKpis.underperformingWorkers,
|
|
61661
|
+
change: sourceKpiTrend.underperformingWorkers?.delta_count ?? baseKpis.underperformingWorkers.change
|
|
61177
61662
|
},
|
|
61178
61663
|
avgCycleTime: {
|
|
61179
|
-
...
|
|
61180
|
-
change:
|
|
61664
|
+
...baseKpis.avgCycleTime,
|
|
61665
|
+
change: sourceKpiTrend.avgCycleTime?.delta_seconds ?? baseKpis.avgCycleTime.change
|
|
61181
61666
|
}
|
|
61182
61667
|
};
|
|
61183
|
-
}, [
|
|
61668
|
+
}, [primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
61669
|
+
const legacyKpisWithTrend = React143.useMemo(
|
|
61670
|
+
() => buildDisplayKpis(legacyLineMetrics, legacyMetricsLoading, legacyKpiTrend),
|
|
61671
|
+
[buildDisplayKpis, legacyLineMetrics, legacyMetricsLoading, legacyKpiTrend]
|
|
61672
|
+
);
|
|
61673
|
+
const bootstrapKpisWithTrend = React143.useMemo(
|
|
61674
|
+
() => buildDisplayKpis(bootstrapMonitor.lineMetrics, bootstrapMonitor.isLoading, bootstrapMonitor.kpiTrend),
|
|
61675
|
+
[buildDisplayKpis, bootstrapMonitor.lineMetrics, bootstrapMonitor.isLoading, bootstrapMonitor.kpiTrend]
|
|
61676
|
+
);
|
|
61677
|
+
const currentKpisWithTrend = isBootstrapMonitorMode ? bootstrapKpisWithTrend : legacyKpisWithTrend;
|
|
61184
61678
|
const selectedLineMeta = React143.useMemo(
|
|
61185
61679
|
() => selectedLineIds.length === 1 ? dbLines.find((line) => line.id === primarySelectedLineId) : void 0,
|
|
61186
61680
|
[dbLines, primarySelectedLineId, selectedLineIds.length]
|
|
@@ -61189,40 +61683,121 @@ function HomeView({
|
|
|
61189
61683
|
const isUptimeMode = selectedMonitoringMode === "uptime";
|
|
61190
61684
|
const averageIdleTimeSeconds = React143.useMemo(() => {
|
|
61191
61685
|
if (!isUptimeMode) return null;
|
|
61192
|
-
const targetWorkspaces =
|
|
61686
|
+
const targetWorkspaces = currentWorkspaceMetrics.filter((ws) => ws.line_id === primarySelectedLineId);
|
|
61193
61687
|
const idleValues = targetWorkspaces.map((ws) => ws.idle_time).filter((value) => Number.isFinite(value));
|
|
61194
61688
|
if (idleValues.length === 0) return 0;
|
|
61195
61689
|
const totalIdle = idleValues.reduce((sum, value) => sum + value, 0);
|
|
61196
61690
|
return totalIdle / idleValues.length;
|
|
61197
|
-
}, [isUptimeMode, primarySelectedLineId,
|
|
61691
|
+
}, [isUptimeMode, primarySelectedLineId, currentWorkspaceMetrics]);
|
|
61198
61692
|
const {
|
|
61199
|
-
activeBreaks:
|
|
61200
|
-
isLoading:
|
|
61201
|
-
error:
|
|
61202
|
-
} = useActiveBreaks(visibleLineIds);
|
|
61203
|
-
const
|
|
61693
|
+
activeBreaks: legacyAllActiveBreaks,
|
|
61694
|
+
isLoading: legacyBreaksLoading,
|
|
61695
|
+
error: legacyBreaksError
|
|
61696
|
+
} = useActiveBreaks(isBootstrapMonitorMode ? EMPTY_LINE_IDS : visibleLineIds);
|
|
61697
|
+
const legacyActiveBreaks = React143.useMemo(() => {
|
|
61204
61698
|
if (isAllLinesSelection(selectedLineIds)) {
|
|
61205
|
-
return
|
|
61699
|
+
return legacyAllActiveBreaks;
|
|
61206
61700
|
}
|
|
61207
|
-
return
|
|
61208
|
-
}, [
|
|
61701
|
+
return legacyAllActiveBreaks.filter((breakItem) => selectedLineIdSet.has(breakItem.lineId));
|
|
61702
|
+
}, [legacyAllActiveBreaks, selectedLineIdSet, selectedLineIds]);
|
|
61703
|
+
const currentActiveBreaks = isBootstrapMonitorMode ? bootstrapMonitor.activeBreaks : legacyActiveBreaks;
|
|
61704
|
+
const currentBreaksLoading = isBootstrapMonitorMode ? bootstrapMonitor.isLoading : legacyBreaksLoading;
|
|
61705
|
+
const currentBreaksError = isBootstrapMonitorMode ? bootstrapMonitor.error?.message || null : legacyBreaksError;
|
|
61209
61706
|
const activeBreakLineIds = React143.useMemo(
|
|
61210
|
-
() => new Set(
|
|
61211
|
-
[
|
|
61707
|
+
() => new Set(currentActiveBreaks.map((breakItem) => breakItem.lineId)),
|
|
61708
|
+
[currentActiveBreaks]
|
|
61212
61709
|
);
|
|
61213
61710
|
const workspaceMetricsWithBreakState = React143.useMemo(
|
|
61214
|
-
() =>
|
|
61711
|
+
() => currentWorkspaceMetrics.map((workspace) => ({
|
|
61215
61712
|
...workspace,
|
|
61216
61713
|
scheduled_break_active: activeBreakLineIds.has(workspace.line_id)
|
|
61217
61714
|
})),
|
|
61218
|
-
[
|
|
61715
|
+
[currentWorkspaceMetrics, activeBreakLineIds]
|
|
61219
61716
|
);
|
|
61220
61717
|
const [breakNotificationsDismissed, setBreakNotificationsDismissed] = React143.useState(false);
|
|
61221
61718
|
React143.useEffect(() => {
|
|
61222
|
-
if (
|
|
61719
|
+
if (currentActiveBreaks.length > 0) {
|
|
61223
61720
|
setBreakNotificationsDismissed(false);
|
|
61224
61721
|
}
|
|
61225
|
-
}, [
|
|
61722
|
+
}, [currentActiveBreaks.length]);
|
|
61723
|
+
const {
|
|
61724
|
+
streamsByWorkspaceId: legacyVideoStreamsByWorkspaceId,
|
|
61725
|
+
isLoading: legacyVideoStreamsLoading
|
|
61726
|
+
} = useWorkspaceVideoStreams(isBootstrapMonitorMode ? EMPTY_WORKSPACES : legacyWorkspaceMetrics, {
|
|
61727
|
+
lineIds: isBootstrapMonitorMode ? EMPTY_LINE_IDS : selectedLineIds
|
|
61728
|
+
});
|
|
61729
|
+
const currentVideoStreamsByWorkspaceId = isBootstrapMonitorMode ? bootstrapMonitor.videoStreamsByWorkspaceId : legacyVideoStreamsByWorkspaceId;
|
|
61730
|
+
const currentVideoStreamsLoading = isBootstrapMonitorMode ? bootstrapMonitor.isLoading : legacyVideoStreamsLoading;
|
|
61731
|
+
React143.useEffect(() => {
|
|
61732
|
+
if (!isShadowMonitorMode) {
|
|
61733
|
+
lastShadowMismatchSignatureRef.current = null;
|
|
61734
|
+
return;
|
|
61735
|
+
}
|
|
61736
|
+
if (!shouldEnableMetricsFetch || legacyMetricsLoading || !legacyIsCurrentScopeResolved || bootstrapMonitor.isLoading || !bootstrapMonitor.isCurrentScopeResolved) {
|
|
61737
|
+
return;
|
|
61738
|
+
}
|
|
61739
|
+
const legacySnapshot = normalizeMonitorShadowSnapshot({
|
|
61740
|
+
selectedLineIds,
|
|
61741
|
+
workspaces: workspaceMetricsWithBreakState,
|
|
61742
|
+
kpis: legacyKpisWithTrend,
|
|
61743
|
+
kpiTrend: legacyKpiTrend,
|
|
61744
|
+
activeBreaks: legacyActiveBreaks,
|
|
61745
|
+
videoStreamsByWorkspaceId: legacyVideoStreamsByWorkspaceId,
|
|
61746
|
+
efficiencyLegend: legacyEfficiencyLegend
|
|
61747
|
+
});
|
|
61748
|
+
const bootstrapSnapshot = normalizeMonitorShadowSnapshot({
|
|
61749
|
+
selectedLineIds,
|
|
61750
|
+
resolvedScope: bootstrapMonitor.resolvedScope,
|
|
61751
|
+
lines: bootstrapMonitor.lines,
|
|
61752
|
+
workspaces: bootstrapMonitor.workspaceMetrics.map((workspace) => ({
|
|
61753
|
+
...workspace,
|
|
61754
|
+
scheduled_break_active: bootstrapMonitor.activeBreaks.some((activeBreak) => activeBreak.lineId === workspace.line_id)
|
|
61755
|
+
})),
|
|
61756
|
+
kpis: bootstrapKpisWithTrend,
|
|
61757
|
+
kpiTrend: bootstrapMonitor.kpiTrend,
|
|
61758
|
+
activeBreaks: bootstrapMonitor.activeBreaks,
|
|
61759
|
+
videoStreamsByWorkspaceId: bootstrapMonitor.videoStreamsByWorkspaceId,
|
|
61760
|
+
efficiencyLegend: bootstrapMonitor.efficiencyLegend
|
|
61761
|
+
});
|
|
61762
|
+
const mismatches = diffMonitorShadowSnapshots(legacySnapshot, bootstrapSnapshot);
|
|
61763
|
+
const signature = JSON.stringify(mismatches);
|
|
61764
|
+
if (mismatches.length === 0) {
|
|
61765
|
+
lastShadowMismatchSignatureRef.current = null;
|
|
61766
|
+
return;
|
|
61767
|
+
}
|
|
61768
|
+
if (lastShadowMismatchSignatureRef.current === signature) {
|
|
61769
|
+
return;
|
|
61770
|
+
}
|
|
61771
|
+
lastShadowMismatchSignatureRef.current = signature;
|
|
61772
|
+
console.error("[HomeView][monitor-shadow-mismatch]", {
|
|
61773
|
+
selectedLineIds,
|
|
61774
|
+
mismatches,
|
|
61775
|
+
legacySnapshot,
|
|
61776
|
+
bootstrapSnapshot
|
|
61777
|
+
});
|
|
61778
|
+
}, [
|
|
61779
|
+
bootstrapKpisWithTrend,
|
|
61780
|
+
bootstrapMonitor.activeBreaks,
|
|
61781
|
+
bootstrapMonitor.efficiencyLegend,
|
|
61782
|
+
bootstrapMonitor.isCurrentScopeResolved,
|
|
61783
|
+
bootstrapMonitor.isLoading,
|
|
61784
|
+
bootstrapMonitor.kpiTrend,
|
|
61785
|
+
bootstrapMonitor.lines,
|
|
61786
|
+
bootstrapMonitor.resolvedScope,
|
|
61787
|
+
bootstrapMonitor.videoStreamsByWorkspaceId,
|
|
61788
|
+
bootstrapMonitor.workspaceMetrics,
|
|
61789
|
+
isShadowMonitorMode,
|
|
61790
|
+
legacyActiveBreaks,
|
|
61791
|
+
legacyEfficiencyLegend,
|
|
61792
|
+
legacyIsCurrentScopeResolved,
|
|
61793
|
+
legacyKpiTrend,
|
|
61794
|
+
legacyKpisWithTrend,
|
|
61795
|
+
legacyMetricsLoading,
|
|
61796
|
+
legacyVideoStreamsByWorkspaceId,
|
|
61797
|
+
selectedLineIds,
|
|
61798
|
+
shouldEnableMetricsFetch,
|
|
61799
|
+
workspaceMetricsWithBreakState
|
|
61800
|
+
]);
|
|
61226
61801
|
const showBottleneckNotification = React143.useCallback(async (bottleneck) => {
|
|
61227
61802
|
try {
|
|
61228
61803
|
logDebug3("\u{1F514} [Notification] Raw bottleneck data:", bottleneck);
|
|
@@ -61400,6 +61975,9 @@ function HomeView({
|
|
|
61400
61975
|
setBottleneckNotification(errorNotification);
|
|
61401
61976
|
}
|
|
61402
61977
|
}, [notificationService, timezone, dashboardConfig, lineShiftConfigs]);
|
|
61978
|
+
React143.useEffect(() => {
|
|
61979
|
+
showBottleneckNotificationRef.current = showBottleneckNotification;
|
|
61980
|
+
}, [showBottleneckNotification]);
|
|
61403
61981
|
React143.useEffect(() => {
|
|
61404
61982
|
const ticketsEnabled = dashboardConfig?.ticketsConfig?.enabled ?? true;
|
|
61405
61983
|
if (!ticketsEnabled) {
|
|
@@ -61469,7 +62047,7 @@ function HomeView({
|
|
|
61469
62047
|
});
|
|
61470
62048
|
if (latestTicket.event_type === "bottleneck") {
|
|
61471
62049
|
logDebug3("\u{1F514} [Polling] Showing bottleneck notification for:", latestTicket.log_number);
|
|
61472
|
-
|
|
62050
|
+
await showBottleneckNotificationRef.current?.(latestTicket);
|
|
61473
62051
|
} else {
|
|
61474
62052
|
logDebug3("\u26A0\uFE0F [Polling] Non-bottleneck ticket found but no handler configured:", latestTicket.event_type);
|
|
61475
62053
|
}
|
|
@@ -61489,29 +62067,30 @@ function HomeView({
|
|
|
61489
62067
|
clearInterval(pollInterval);
|
|
61490
62068
|
clearTimeout(initialPollTimer);
|
|
61491
62069
|
};
|
|
61492
|
-
}, [
|
|
62070
|
+
}, [
|
|
62071
|
+
dashboardConfig?.ticketsConfig?.enabled,
|
|
62072
|
+
notificationService,
|
|
62073
|
+
user?.email,
|
|
62074
|
+
user?.role_level,
|
|
62075
|
+
userCompanyId
|
|
62076
|
+
]);
|
|
61493
62077
|
const handleWorkspaceHover = React143.useCallback((workspaceId) => {
|
|
61494
62078
|
}, []);
|
|
61495
62079
|
const handleWorkspaceHoverEnd = React143.useCallback((workspaceId) => {
|
|
61496
62080
|
}, []);
|
|
61497
|
-
const
|
|
61498
|
-
streamsByWorkspaceId: videoStreamsByWorkspaceId,
|
|
61499
|
-
isLoading: videoStreamsLoading
|
|
61500
|
-
} = useWorkspaceVideoStreams(workspaceMetrics);
|
|
61501
|
-
const memoizedKPIs = React143.useMemo(() => kpisWithTrend, [
|
|
62081
|
+
const memoizedKPIs = React143.useMemo(() => currentKpisWithTrend, [
|
|
61502
62082
|
// Only update reference when values change by at least 1%
|
|
61503
|
-
|
|
61504
|
-
|
|
61505
|
-
|
|
61506
|
-
|
|
61507
|
-
|
|
61508
|
-
|
|
61509
|
-
|
|
61510
|
-
|
|
61511
|
-
|
|
61512
|
-
|
|
61513
|
-
|
|
61514
|
-
kpisWithTrend?.qualityCompliance?.value ? Math.round(kpisWithTrend.qualityCompliance.value) : null,
|
|
62083
|
+
currentKpisWithTrend?.efficiency?.value ? Math.round(currentKpisWithTrend.efficiency.value) : null,
|
|
62084
|
+
currentKpisWithTrend?.efficiency?.change,
|
|
62085
|
+
currentKpisWithTrend?.underperformingWorkers?.current,
|
|
62086
|
+
currentKpisWithTrend?.underperformingWorkers?.total,
|
|
62087
|
+
currentKpisWithTrend?.underperformingWorkers?.change,
|
|
62088
|
+
currentKpisWithTrend?.outputProgress?.current,
|
|
62089
|
+
currentKpisWithTrend?.outputProgress?.target,
|
|
62090
|
+
currentKpisWithTrend?.outputProgress?.change,
|
|
62091
|
+
currentKpisWithTrend?.avgCycleTime?.value ? Math.round(currentKpisWithTrend.avgCycleTime.value * 10) / 10 : null,
|
|
62092
|
+
currentKpisWithTrend?.avgCycleTime?.change,
|
|
62093
|
+
currentKpisWithTrend?.qualityCompliance?.value ? Math.round(currentKpisWithTrend.qualityCompliance.value) : null,
|
|
61515
62094
|
selectedLineIdsKey
|
|
61516
62095
|
]);
|
|
61517
62096
|
React143.useEffect(() => {
|
|
@@ -61522,13 +62101,13 @@ function HomeView({
|
|
|
61522
62101
|
dashboard_surface: "monitor"
|
|
61523
62102
|
});
|
|
61524
62103
|
}, []);
|
|
61525
|
-
const metricsErrorMessage =
|
|
62104
|
+
const metricsErrorMessage = currentMetricsError?.message || null;
|
|
61526
62105
|
const handleRetryDashboardData = React143.useCallback(async () => {
|
|
61527
62106
|
if (isRecoveringSession) {
|
|
61528
62107
|
await retrySessionHydration();
|
|
61529
62108
|
}
|
|
61530
|
-
|
|
61531
|
-
}, [
|
|
62109
|
+
await currentRefetchMetrics();
|
|
62110
|
+
}, [currentRefetchMetrics, isRecoveringSession, retrySessionHydration]);
|
|
61532
62111
|
const getTrackedLineScope = React143.useCallback((lineIdsForScope) => {
|
|
61533
62112
|
if (isAllLinesSelection(lineIdsForScope)) {
|
|
61534
62113
|
return factoryViewId;
|
|
@@ -61581,12 +62160,15 @@ function HomeView({
|
|
|
61581
62160
|
updateSelectedLineIds(Array.from(currentSelection));
|
|
61582
62161
|
}, [selectedLineIds, updateSelectedLineIds]);
|
|
61583
62162
|
React143.useEffect(() => {
|
|
61584
|
-
if (!
|
|
62163
|
+
if (!isChangingFilter) {
|
|
62164
|
+
return;
|
|
62165
|
+
}
|
|
62166
|
+
if (!currentMetricsLoading && currentIsCurrentScopeResolved || currentMetricsError) {
|
|
61585
62167
|
setIsChangingFilter(false);
|
|
61586
62168
|
}
|
|
61587
|
-
}, [
|
|
62169
|
+
}, [currentIsCurrentScopeResolved, currentMetricsError, currentMetricsLoading, isChangingFilter]);
|
|
61588
62170
|
React143.useEffect(() => {
|
|
61589
|
-
if (shouldEnableMetricsFetch && !
|
|
62171
|
+
if (shouldEnableMetricsFetch && !currentMetricsLoading && !currentMetricsError && !hasInitialDataLoaded) {
|
|
61590
62172
|
setHasInitialDataLoaded(true);
|
|
61591
62173
|
trackCoreEvent("monitor page loaded", {
|
|
61592
62174
|
default_line_id: defaultLineId,
|
|
@@ -61595,7 +62177,7 @@ function HomeView({
|
|
|
61595
62177
|
dashboard_surface: "monitor"
|
|
61596
62178
|
});
|
|
61597
62179
|
}
|
|
61598
|
-
}, [shouldEnableMetricsFetch,
|
|
62180
|
+
}, [shouldEnableMetricsFetch, currentMetricsLoading, currentMetricsError, hasInitialDataLoaded, defaultLineId, factoryViewId, isSupervisor]);
|
|
61599
62181
|
const lineTitle = React143.useMemo(() => {
|
|
61600
62182
|
return factoryName;
|
|
61601
62183
|
}, [factoryName]);
|
|
@@ -61746,15 +62328,15 @@ function HomeView({
|
|
|
61746
62328
|
return showLoading;
|
|
61747
62329
|
};
|
|
61748
62330
|
const isAuthBootstrapping = authStatus === "loading";
|
|
61749
|
-
const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (isAuthBootstrapping || shouldEnableMetricsFetch &&
|
|
61750
|
-
const isDataLoading =
|
|
62331
|
+
const isInitialLoading = !isHydrated || !hasInitialDataLoaded && (isAuthBootstrapping || shouldEnableMetricsFetch && currentMetricsLoading);
|
|
62332
|
+
const isDataLoading = currentMetricsLoading;
|
|
61751
62333
|
const hasKpiDataReady = React143.useMemo(() => {
|
|
61752
|
-
const lineMetricsRows =
|
|
62334
|
+
const lineMetricsRows = currentLineMetrics || [];
|
|
61753
62335
|
if (selectedLineIds.length > 1) {
|
|
61754
62336
|
return lineMetricsRows.some((row) => selectedLineIdSet.has(row?.line_id));
|
|
61755
62337
|
}
|
|
61756
62338
|
return lineMetricsRows.some((row) => row?.line_id === primarySelectedLineId);
|
|
61757
|
-
}, [
|
|
62339
|
+
}, [currentLineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
61758
62340
|
const isKpiLoading = !hasKpiDataReady;
|
|
61759
62341
|
const shouldShowReconnectScreen = !hasInitialDataLoaded && (isRecoveringSession || !shouldEnableMetricsFetch && authStatus !== "failed" || !!metricsErrorMessage && authStatus !== "failed");
|
|
61760
62342
|
const shouldShowFatalLoadFailure = !hasInitialDataLoaded && !!metricsErrorMessage && authStatus === "failed";
|
|
@@ -61782,6 +62364,7 @@ function HomeView({
|
|
|
61782
62364
|
return () => clearTimeout(timer);
|
|
61783
62365
|
}, [isDataLoading]);
|
|
61784
62366
|
const shouldShowDataLoading = showDataLoading || isDataLoading;
|
|
62367
|
+
const shouldShowFilterChangeLoader = isChangingFilter && !currentIsCurrentScopeResolved;
|
|
61785
62368
|
const shouldShowKpiLoading = useSmoothLoading(isKpiLoading, 400);
|
|
61786
62369
|
const displayKpis = shouldShowKpiLoading ? null : memoizedKPIs;
|
|
61787
62370
|
const kpiSectionControl = React143.useMemo(() => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -61866,7 +62449,7 @@ function HomeView({
|
|
|
61866
62449
|
}
|
|
61867
62450
|
)
|
|
61868
62451
|
] }) }) : null,
|
|
61869
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
62452
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex-1 min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
61870
62453
|
motion.div,
|
|
61871
62454
|
{
|
|
61872
62455
|
initial: { opacity: 0, scale: 0.98 },
|
|
@@ -61878,10 +62461,10 @@ function HomeView({
|
|
|
61878
62461
|
lineNames: mergedLineNames,
|
|
61879
62462
|
lineOrder: selectedLineIds,
|
|
61880
62463
|
factoryView: factoryViewId,
|
|
61881
|
-
legend:
|
|
62464
|
+
legend: currentEfficiencyLegend,
|
|
61882
62465
|
videoSources,
|
|
61883
|
-
videoStreamsByWorkspaceId,
|
|
61884
|
-
videoStreamsLoading,
|
|
62466
|
+
videoStreamsByWorkspaceId: currentVideoStreamsByWorkspaceId,
|
|
62467
|
+
videoStreamsLoading: currentVideoStreamsLoading,
|
|
61885
62468
|
displayNames: metricsDisplayNames,
|
|
61886
62469
|
hasFlowBuffers,
|
|
61887
62470
|
className: "h-full",
|
|
@@ -61889,8 +62472,7 @@ function HomeView({
|
|
|
61889
62472
|
onWorkspaceHover: handleWorkspaceHover,
|
|
61890
62473
|
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
61891
62474
|
})
|
|
61892
|
-
}
|
|
61893
|
-
selectedLineIdsKey
|
|
62475
|
+
}
|
|
61894
62476
|
) : !shouldShowDataLoading && hasInitialDataLoaded ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
61895
62477
|
motion.div,
|
|
61896
62478
|
{
|
|
@@ -61912,10 +62494,10 @@ function HomeView({
|
|
|
61912
62494
|
lineNames: mergedLineNames,
|
|
61913
62495
|
lineOrder: selectedLineIds,
|
|
61914
62496
|
factoryView: factoryViewId,
|
|
61915
|
-
legend:
|
|
62497
|
+
legend: currentEfficiencyLegend,
|
|
61916
62498
|
videoSources,
|
|
61917
|
-
videoStreamsByWorkspaceId,
|
|
61918
|
-
videoStreamsLoading,
|
|
62499
|
+
videoStreamsByWorkspaceId: currentVideoStreamsByWorkspaceId,
|
|
62500
|
+
videoStreamsLoading: currentVideoStreamsLoading,
|
|
61919
62501
|
displayNames: metricsDisplayNames,
|
|
61920
62502
|
hasFlowBuffers,
|
|
61921
62503
|
className: "h-full",
|
|
@@ -61923,16 +62505,15 @@ function HomeView({
|
|
|
61923
62505
|
onWorkspaceHover: handleWorkspaceHover,
|
|
61924
62506
|
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
61925
62507
|
})
|
|
61926
|
-
}
|
|
61927
|
-
selectedLineIdsKey
|
|
62508
|
+
}
|
|
61928
62509
|
) }) })
|
|
61929
62510
|
] }),
|
|
61930
62511
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
61931
62512
|
BreakNotificationPopup,
|
|
61932
62513
|
{
|
|
61933
|
-
activeBreaks,
|
|
62514
|
+
activeBreaks: currentActiveBreaks,
|
|
61934
62515
|
lineNames: mergedLineNames,
|
|
61935
|
-
isVisible: !
|
|
62516
|
+
isVisible: !currentBreaksLoading && !currentBreaksError && !breakNotificationsDismissed,
|
|
61936
62517
|
onDismiss: () => setBreakNotificationsDismissed(true)
|
|
61937
62518
|
}
|
|
61938
62519
|
),
|
|
@@ -61944,6 +62525,15 @@ function HomeView({
|
|
|
61944
62525
|
onDismiss: () => setBottleneckNotification(null)
|
|
61945
62526
|
}
|
|
61946
62527
|
),
|
|
62528
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
62529
|
+
LoadingOverlayCmp,
|
|
62530
|
+
{
|
|
62531
|
+
isVisible: shouldShowFilterChangeLoader,
|
|
62532
|
+
message: "Loading Dashboard...",
|
|
62533
|
+
className: "bg-slate-50/30 backdrop-blur-[3px]",
|
|
62534
|
+
contentVariant: "plain"
|
|
62535
|
+
}
|
|
62536
|
+
),
|
|
61947
62537
|
diagnosisModalOpen && bottleneckModalData?.clipId && /* @__PURE__ */ jsxRuntime.jsx(
|
|
61948
62538
|
DiagnosisVideoModal,
|
|
61949
62539
|
{
|
|
@@ -62194,7 +62784,7 @@ var buildLineInfoSnapshot = (lineDetails, metrics2) => {
|
|
|
62194
62784
|
}
|
|
62195
62785
|
};
|
|
62196
62786
|
};
|
|
62197
|
-
var
|
|
62787
|
+
var transformWorkspaceMetrics2 = (workspaceData, lineId, companyId, queryDate, queryShiftId) => (workspaceData || []).map((item) => ({
|
|
62198
62788
|
company_id: item.company_id || companyId,
|
|
62199
62789
|
line_id: item.line_id || lineId,
|
|
62200
62790
|
shift_id: item.shift_id ?? queryShiftId,
|
|
@@ -62342,7 +62932,7 @@ var useLineDetailPageData = ({
|
|
|
62342
62932
|
setDetailResponse(nextDetail);
|
|
62343
62933
|
const metrics3 = transformLineMetrics(lineId, nextDetail, queryDate, queryShiftId);
|
|
62344
62934
|
const lineDetails2 = transformLineDetails(lineId, nextDetail);
|
|
62345
|
-
const workspaces2 =
|
|
62935
|
+
const workspaces2 = transformWorkspaceMetrics2(
|
|
62346
62936
|
nextDetail.workspace_metrics || [],
|
|
62347
62937
|
lineId,
|
|
62348
62938
|
companyId,
|
|
@@ -62432,7 +63022,7 @@ var useLineDetailPageData = ({
|
|
|
62432
63022
|
[detailResponse, lineId]
|
|
62433
63023
|
);
|
|
62434
63024
|
const workspaces = React143.useMemo(
|
|
62435
|
-
() => detailResponse && companyId ?
|
|
63025
|
+
() => detailResponse && companyId ? transformWorkspaceMetrics2(detailResponse.workspace_metrics || [], lineId, companyId, queryDate, queryShiftId) : [],
|
|
62436
63026
|
[detailResponse, companyId, lineId, queryDate, queryShiftId]
|
|
62437
63027
|
);
|
|
62438
63028
|
const lineInfo = React143.useMemo(() => buildLineInfoSnapshot(lineDetails, metrics2), [lineDetails, metrics2]);
|
|
@@ -74054,7 +74644,8 @@ var TeamManagementView = ({
|
|
|
74054
74644
|
const bootstrapData = await bootstrapResponse.json();
|
|
74055
74645
|
setAvailableFactories((bootstrapData.factories || []).map((factory) => ({
|
|
74056
74646
|
id: factory.id,
|
|
74057
|
-
factory_name: factory.factory_name
|
|
74647
|
+
factory_name: factory.factory_name,
|
|
74648
|
+
company_id: factory.company_id
|
|
74058
74649
|
})));
|
|
74059
74650
|
setAvailableLines(bootstrapData.lines || []);
|
|
74060
74651
|
setUsers(bootstrapData.users || []);
|
|
@@ -79022,7 +79613,7 @@ var efficiencyLineConfig = [
|
|
|
79022
79613
|
var bumpRenderCounter = (key) => {
|
|
79023
79614
|
if (process.env.NODE_ENV === "test") ;
|
|
79024
79615
|
};
|
|
79025
|
-
var
|
|
79616
|
+
var toNumber4 = (value) => {
|
|
79026
79617
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
79027
79618
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
79028
79619
|
const parsed = Number(value);
|
|
@@ -79557,7 +80148,7 @@ var OverviewSummaryCards = React143__namespace.default.memo(({ store }) => {
|
|
|
79557
80148
|
workspaceId: item.workspace_id || "",
|
|
79558
80149
|
workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
|
|
79559
80150
|
lineName: item.line_name?.trim() || "Unknown Line",
|
|
79560
|
-
avgIdleSeconds:
|
|
80151
|
+
avgIdleSeconds: toNumber4(item.avg_idle_seconds)
|
|
79561
80152
|
})).slice(0, 5);
|
|
79562
80153
|
}, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
|
|
79563
80154
|
const showIdleContributorLineNames = React143__namespace.default.useMemo(() => {
|
|
@@ -79772,9 +80363,9 @@ var PoorestPerformersCard = React143__namespace.default.memo(({
|
|
|
79772
80363
|
return {
|
|
79773
80364
|
id: lineId,
|
|
79774
80365
|
name: line.line_name?.trim() || "Unknown Line",
|
|
79775
|
-
efficiency: roundOne(
|
|
79776
|
-
previousEfficiency:
|
|
79777
|
-
delta:
|
|
80366
|
+
efficiency: roundOne(toNumber4(line.avg_efficiency) || 0),
|
|
80367
|
+
previousEfficiency: toNumber4(line.previous_avg_efficiency),
|
|
80368
|
+
delta: toNumber4(line.delta_pp),
|
|
79778
80369
|
supervisor: supervisor?.displayName || "Unassigned",
|
|
79779
80370
|
supervisorImage: supervisor?.profilePhotoUrl ?? null
|
|
79780
80371
|
};
|
|
@@ -79883,14 +80474,14 @@ var IdleBreakdownCard = React143__namespace.default.memo(({
|
|
|
79883
80474
|
paletteToken: item.palette_token?.trim(),
|
|
79884
80475
|
iconToken: item.icon_token?.trim(),
|
|
79885
80476
|
isKnown: item.is_known ?? void 0,
|
|
79886
|
-
value:
|
|
79887
|
-
totalDurationSeconds:
|
|
79888
|
-
efficiencyLossPercentage:
|
|
80477
|
+
value: toNumber4(item.percentage) || 0,
|
|
80478
|
+
totalDurationSeconds: toNumber4(item.total_duration_seconds),
|
|
80479
|
+
efficiencyLossPercentage: toNumber4(item.efficiency_loss_percentage),
|
|
79889
80480
|
contributors: (item.contributors || []).map((contributor) => ({
|
|
79890
80481
|
workspaceId: contributor.workspace_id || "",
|
|
79891
80482
|
workspaceName: contributor.workspace_name?.trim() || "Unknown",
|
|
79892
|
-
totalDurationSeconds:
|
|
79893
|
-
percentageWithinReason:
|
|
80483
|
+
totalDurationSeconds: toNumber4(contributor.total_duration_seconds),
|
|
80484
|
+
percentageWithinReason: toNumber4(contributor.percentage_within_reason)
|
|
79894
80485
|
}))
|
|
79895
80486
|
})).filter((item) => item.value > 0);
|
|
79896
80487
|
}, [idle.data]);
|
|
@@ -79959,7 +80550,7 @@ var EfficiencyTrendCard = React143__namespace.default.memo(({
|
|
|
79959
80550
|
return `${hour12}:${minutes.toString().padStart(2, "0")} ${suffix}`;
|
|
79960
80551
|
})(),
|
|
79961
80552
|
efficiency: (() => {
|
|
79962
|
-
const value =
|
|
80553
|
+
const value = toNumber4(point.avg_efficiency);
|
|
79963
80554
|
return value === null ? void 0 : value;
|
|
79964
80555
|
})()
|
|
79965
80556
|
}));
|
|
@@ -79972,7 +80563,7 @@ var EfficiencyTrendCard = React143__namespace.default.memo(({
|
|
|
79972
80563
|
name: dateFns.format(pointDate, "MMM d"),
|
|
79973
80564
|
dayOfWeek: dateFns.format(pointDate, "EEEE"),
|
|
79974
80565
|
efficiency: (() => {
|
|
79975
|
-
const value =
|
|
80566
|
+
const value = toNumber4(point.avg_efficiency);
|
|
79976
80567
|
return value === null ? void 0 : value;
|
|
79977
80568
|
})()
|
|
79978
80569
|
}]];
|
|
@@ -79996,7 +80587,7 @@ var EfficiencyTrendCard = React143__namespace.default.memo(({
|
|
|
79996
80587
|
name: pointDate ? dateFns.format(pointDate, "MMM d") : "",
|
|
79997
80588
|
dayOfWeek: pointDate ? dateFns.format(pointDate, "EEEE") : "",
|
|
79998
80589
|
efficiency: (() => {
|
|
79999
|
-
const value =
|
|
80590
|
+
const value = toNumber4(point.avg_efficiency);
|
|
80000
80591
|
return value === null ? void 0 : value;
|
|
80001
80592
|
})()
|
|
80002
80593
|
};
|
|
@@ -80120,7 +80711,7 @@ var debugRefreshLog = (message, payload) => {
|
|
|
80120
80711
|
var isAbortError2 = (error) => {
|
|
80121
80712
|
return error instanceof DOMException && error.name === "AbortError";
|
|
80122
80713
|
};
|
|
80123
|
-
var
|
|
80714
|
+
var toNumber5 = (value) => {
|
|
80124
80715
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
80125
80716
|
if (typeof value === "string" && value.trim().length > 0) {
|
|
80126
80717
|
const parsed = Number(value);
|
|
@@ -80129,11 +80720,11 @@ var toNumber4 = (value) => {
|
|
|
80129
80720
|
return null;
|
|
80130
80721
|
};
|
|
80131
80722
|
var formatImprovementMetric = (recommendation) => {
|
|
80132
|
-
const estimatedGain =
|
|
80723
|
+
const estimatedGain = toNumber5(recommendation.estimated_gain_pieces);
|
|
80133
80724
|
if (estimatedGain !== null && estimatedGain > 0) {
|
|
80134
80725
|
return `+${Math.round(estimatedGain).toLocaleString()} pcs / day`;
|
|
80135
80726
|
}
|
|
80136
|
-
const idleMinutes =
|
|
80727
|
+
const idleMinutes = toNumber5(recommendation.metrics?.idle_minutes);
|
|
80137
80728
|
if (idleMinutes !== null) {
|
|
80138
80729
|
return `-${Math.round(idleMinutes)}m Idle`;
|
|
80139
80730
|
}
|