@optifye/dashboard-core 6.12.37 → 6.12.39
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 +3 -0
- package/dist/index.js +214 -54
- package/dist/index.mjs +215 -55
- package/package.json +1 -1
package/dist/index.css
CHANGED
package/dist/index.js
CHANGED
|
@@ -37286,7 +37286,9 @@ var HourlyOutputChartComponent = ({
|
|
|
37286
37286
|
const idleSlot = idleSlots[i];
|
|
37287
37287
|
const explicitTarget = hasHourlyTargetOutputProp ? effectiveHourlyTargetOutput?.[i] ?? null : void 0;
|
|
37288
37288
|
const currentTarget = hasHourlyTargetOutputProp ? explicitTarget : targets[i] || pphThreshold;
|
|
37289
|
+
const outputForComparison = Math.round(animatedData[i] || 0);
|
|
37289
37290
|
const comparisonTarget = currentTarget === null || currentTarget === void 0 ? targets[i] || pphThreshold : currentTarget;
|
|
37291
|
+
const targetForComparison = Math.round(comparisonTarget);
|
|
37290
37292
|
return {
|
|
37291
37293
|
hourIndex: idleSlot?.hourIndex ?? i,
|
|
37292
37294
|
hour: idleSlot?.hour || "",
|
|
@@ -37295,7 +37297,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37295
37297
|
originalOutput: data[i] || 0,
|
|
37296
37298
|
// Keep original data for labels
|
|
37297
37299
|
target: currentTarget ?? null,
|
|
37298
|
-
color:
|
|
37300
|
+
color: outputForComparison >= targetForComparison ? "#00AB45" : "#E34329",
|
|
37299
37301
|
idleMinutes: idleSlot?.idleMinutes || 0,
|
|
37300
37302
|
idleArray: idleSlot?.idleArray || [],
|
|
37301
37303
|
skuIndex: i,
|
|
@@ -59665,6 +59667,42 @@ var buildSnapshotRows = (entries, lines) => {
|
|
|
59665
59667
|
rowType: row.rowType
|
|
59666
59668
|
}));
|
|
59667
59669
|
};
|
|
59670
|
+
var isValidSnapshotRow = (row) => !!row && typeof row.efficiency === "number" && Number.isFinite(row.efficiency) && typeof row.rank === "number" && Number.isFinite(row.rank);
|
|
59671
|
+
var refreshPendingEventsFromSnapshot = (events, currentSnapshot) => {
|
|
59672
|
+
if (events.length === 0 || currentSnapshot.length === 0) return [];
|
|
59673
|
+
const snapshotByRowId = new Map(currentSnapshot.map((row) => [row.lineId, row]));
|
|
59674
|
+
return events.flatMap((event) => {
|
|
59675
|
+
const currentSubject = snapshotByRowId.get(event.crossingLineId);
|
|
59676
|
+
if (!isValidSnapshotRow(currentSubject)) return [];
|
|
59677
|
+
const movedFromOriginalRank = event.direction === "up" ? currentSubject.rank < event.previousRank : currentSubject.rank > event.previousRank;
|
|
59678
|
+
if (!movedFromOriginalRank) return [];
|
|
59679
|
+
const crossedLines = event.crossedLines.flatMap((crossedLine) => {
|
|
59680
|
+
const currentCrossedLine = snapshotByRowId.get(crossedLine.lineId);
|
|
59681
|
+
if (!isValidSnapshotRow(currentCrossedLine)) return [];
|
|
59682
|
+
const stillCrossed = event.direction === "up" ? currentSubject.rank < currentCrossedLine.rank : currentSubject.rank > currentCrossedLine.rank;
|
|
59683
|
+
if (!stillCrossed) return [];
|
|
59684
|
+
return [{
|
|
59685
|
+
...crossedLine,
|
|
59686
|
+
lineName: currentCrossedLine.lineName,
|
|
59687
|
+
currentRank: currentCrossedLine.rank,
|
|
59688
|
+
currentEfficiency: currentCrossedLine.efficiency
|
|
59689
|
+
}];
|
|
59690
|
+
});
|
|
59691
|
+
if (crossedLines.length !== event.crossedLines.length) return [];
|
|
59692
|
+
return [{
|
|
59693
|
+
...event,
|
|
59694
|
+
crossingLineName: currentSubject.lineName,
|
|
59695
|
+
currentRank: currentSubject.rank,
|
|
59696
|
+
currentEfficiency: currentSubject.efficiency,
|
|
59697
|
+
crossedLines,
|
|
59698
|
+
eventKey: buildLineOvertakeEventKey(
|
|
59699
|
+
event.crossingLineId,
|
|
59700
|
+
event.direction,
|
|
59701
|
+
crossedLines.map((line) => line.lineId)
|
|
59702
|
+
)
|
|
59703
|
+
}];
|
|
59704
|
+
});
|
|
59705
|
+
};
|
|
59668
59706
|
var formatCrossedLineNames = (event) => {
|
|
59669
59707
|
const names = event.crossedLines.map((line) => line.lineName).filter(Boolean);
|
|
59670
59708
|
if (names.length === 0) return "another line";
|
|
@@ -59722,6 +59760,7 @@ var storeEventKey = (scopeKey, eventKey) => {
|
|
|
59722
59760
|
} catch {
|
|
59723
59761
|
}
|
|
59724
59762
|
};
|
|
59763
|
+
var buildAcknowledgementKey = (scopeKey, eventKey) => `${scopeKey}:${eventKey}`;
|
|
59725
59764
|
var LineOvertakeNotificationPopup = ({
|
|
59726
59765
|
events,
|
|
59727
59766
|
onDismiss,
|
|
@@ -59871,6 +59910,7 @@ var LineOvertakeNotificationManager = ({
|
|
|
59871
59910
|
const [visibleLines, setVisibleLines] = React146.useState([]);
|
|
59872
59911
|
const [linesLoaded, setLinesLoaded] = React146.useState(false);
|
|
59873
59912
|
const [notificationEvents, setNotificationEvents] = React146.useState([]);
|
|
59913
|
+
const [returnValidationPending, setReturnValidationPending] = React146.useState(false);
|
|
59874
59914
|
const isOnActiveToastSurface = isActiveToastSurface(router$1.asPath);
|
|
59875
59915
|
const qaSimulationMode = isOnActiveToastSurface ? getLocalQaSimulationMode(router$1.asPath) : null;
|
|
59876
59916
|
const qaSimulationEnabled = Boolean(qaSimulationMode);
|
|
@@ -59897,20 +59937,33 @@ var LineOvertakeNotificationManager = ({
|
|
|
59897
59937
|
const scopeKeyRef = React146.useRef("");
|
|
59898
59938
|
const pollInFlightRef = React146.useRef(false);
|
|
59899
59939
|
const notificationEventsRef = React146.useRef([]);
|
|
59940
|
+
const acknowledgedEventKeysRef = React146.useRef(/* @__PURE__ */ new Set());
|
|
59941
|
+
const wasOnActiveToastSurfaceRef = React146.useRef(isOnActiveToastSurface);
|
|
59900
59942
|
const dedupeScopeKey = React146.useMemo(
|
|
59901
|
-
() =>
|
|
59902
|
-
|
|
59903
|
-
|
|
59904
|
-
|
|
59905
|
-
|
|
59906
|
-
|
|
59907
|
-
|
|
59908
|
-
|
|
59943
|
+
() => {
|
|
59944
|
+
if (qaSimulationEnabled) {
|
|
59945
|
+
return [
|
|
59946
|
+
user?.id || "anonymous",
|
|
59947
|
+
"qa-simulation",
|
|
59948
|
+
qaSimulationMode || "default"
|
|
59949
|
+
].join("|");
|
|
59950
|
+
}
|
|
59951
|
+
return [
|
|
59952
|
+
user?.id || "anonymous",
|
|
59953
|
+
companyId || "no-company",
|
|
59954
|
+
currentShift.date,
|
|
59955
|
+
currentShift.shiftId,
|
|
59956
|
+
roleMode || "disabled",
|
|
59957
|
+
watchedLineIds.slice().sort().join(",")
|
|
59958
|
+
].join("|");
|
|
59959
|
+
},
|
|
59909
59960
|
[
|
|
59910
59961
|
user?.id,
|
|
59911
59962
|
companyId,
|
|
59912
59963
|
currentShift.date,
|
|
59913
59964
|
currentShift.shiftId,
|
|
59965
|
+
qaSimulationEnabled,
|
|
59966
|
+
qaSimulationMode,
|
|
59914
59967
|
roleMode,
|
|
59915
59968
|
watchedLineIds
|
|
59916
59969
|
]
|
|
@@ -59947,13 +60000,45 @@ var LineOvertakeNotificationManager = ({
|
|
|
59947
60000
|
previousSnapshotRef.current = null;
|
|
59948
60001
|
notificationEventsRef.current = [];
|
|
59949
60002
|
setNotificationEvents([]);
|
|
60003
|
+
setReturnValidationPending(false);
|
|
59950
60004
|
scopeKeyRef.current = scopeKey;
|
|
59951
60005
|
}, [isOnActiveToastSurface, scopeKey]);
|
|
59952
60006
|
React146.useEffect(() => {
|
|
59953
|
-
|
|
60007
|
+
const wasOnActiveToastSurface = wasOnActiveToastSurfaceRef.current;
|
|
60008
|
+
wasOnActiveToastSurfaceRef.current = isOnActiveToastSurface;
|
|
60009
|
+
if (wasOnActiveToastSurface && !isOnActiveToastSurface && notificationEventsRef.current.length > 0) {
|
|
60010
|
+
setReturnValidationPending(true);
|
|
60011
|
+
return;
|
|
60012
|
+
}
|
|
60013
|
+
if (!wasOnActiveToastSurface && isOnActiveToastSurface && notificationEventsRef.current.length === 0) {
|
|
60014
|
+
setReturnValidationPending(false);
|
|
60015
|
+
}
|
|
60016
|
+
}, [isOnActiveToastSurface]);
|
|
60017
|
+
const acknowledgeCurrentEvents = React146.useCallback(() => {
|
|
60018
|
+
notificationEventsRef.current.forEach((event) => {
|
|
60019
|
+
acknowledgedEventKeysRef.current.add(buildAcknowledgementKey(dedupeScopeKey, event.eventKey));
|
|
60020
|
+
storeEventKey(dedupeScopeKey, event.eventKey);
|
|
60021
|
+
});
|
|
59954
60022
|
notificationEventsRef.current = [];
|
|
59955
60023
|
setNotificationEvents([]);
|
|
59956
|
-
|
|
60024
|
+
setReturnValidationPending(false);
|
|
60025
|
+
}, [dedupeScopeKey]);
|
|
60026
|
+
const clearPendingEvents = React146.useCallback(() => {
|
|
60027
|
+
notificationEventsRef.current = [];
|
|
60028
|
+
setNotificationEvents([]);
|
|
60029
|
+
setReturnValidationPending(false);
|
|
60030
|
+
}, []);
|
|
60031
|
+
const finishReturnValidation = React146.useCallback((events, currentSnapshot) => {
|
|
60032
|
+
if (events.length === 0 && notificationEventsRef.current.length > 0) {
|
|
60033
|
+
const validatedEvents = refreshPendingEventsFromSnapshot(
|
|
60034
|
+
notificationEventsRef.current,
|
|
60035
|
+
currentSnapshot
|
|
60036
|
+
);
|
|
60037
|
+
notificationEventsRef.current = validatedEvents;
|
|
60038
|
+
setNotificationEvents(validatedEvents);
|
|
60039
|
+
}
|
|
60040
|
+
setReturnValidationPending(false);
|
|
60041
|
+
}, []);
|
|
59957
60042
|
React146.useEffect(() => {
|
|
59958
60043
|
let cancelled = false;
|
|
59959
60044
|
const loadLines = async () => {
|
|
@@ -59994,10 +60079,9 @@ var LineOvertakeNotificationManager = ({
|
|
|
59994
60079
|
};
|
|
59995
60080
|
}, [companyId, isOnActiveToastSurface, qaSimulationEnabled, roleMode, supabase]);
|
|
59996
60081
|
const openLeaderboard = React146.useCallback(() => {
|
|
59997
|
-
|
|
59998
|
-
setNotificationEvents([]);
|
|
60082
|
+
acknowledgeCurrentEvents();
|
|
59999
60083
|
void router$1.push("/kpis?tab=leaderboard");
|
|
60000
|
-
}, [router$1]);
|
|
60084
|
+
}, [acknowledgeCurrentEvents, router$1]);
|
|
60001
60085
|
const updateOvertakeEvents = React146.useCallback((events) => {
|
|
60002
60086
|
if (events.length === 0) return;
|
|
60003
60087
|
const currentEventByRowId = new Map(
|
|
@@ -60005,13 +60089,9 @@ var LineOvertakeNotificationManager = ({
|
|
|
60005
60089
|
);
|
|
60006
60090
|
const nextEvents = events.filter((event) => {
|
|
60007
60091
|
if (currentEventByRowId.has(event.crossingLineId)) return true;
|
|
60008
|
-
return !hasStoredEventKey(dedupeScopeKey, event.eventKey);
|
|
60092
|
+
return !(acknowledgedEventKeysRef.current.has(buildAcknowledgementKey(dedupeScopeKey, event.eventKey)) || hasStoredEventKey(dedupeScopeKey, event.eventKey));
|
|
60009
60093
|
});
|
|
60010
60094
|
if (nextEvents.length === 0) return;
|
|
60011
|
-
nextEvents.forEach((event) => {
|
|
60012
|
-
if (currentEventByRowId.has(event.crossingLineId)) return;
|
|
60013
|
-
storeEventKey(dedupeScopeKey, event.eventKey);
|
|
60014
|
-
});
|
|
60015
60095
|
setNotificationEvents((currentEvents) => {
|
|
60016
60096
|
const eventByRowId = new Map(currentEvents.map((event) => [event.crossingLineId, event]));
|
|
60017
60097
|
nextEvents.forEach((event) => {
|
|
@@ -60054,6 +60134,7 @@ var LineOvertakeNotificationManager = ({
|
|
|
60054
60134
|
});
|
|
60055
60135
|
previousSnapshotRef.current = QA_CROSSED_ROWS;
|
|
60056
60136
|
updateOvertakeEvents(events);
|
|
60137
|
+
finishReturnValidation(events, QA_CROSSED_ROWS);
|
|
60057
60138
|
} finally {
|
|
60058
60139
|
pollInFlightRef.current = false;
|
|
60059
60140
|
}
|
|
@@ -60076,11 +60157,17 @@ var LineOvertakeNotificationManager = ({
|
|
|
60076
60157
|
const currentSnapshot = buildSnapshotRows(entries, visibleLines);
|
|
60077
60158
|
if (currentSnapshot.length === 0) {
|
|
60078
60159
|
previousSnapshotRef.current = null;
|
|
60160
|
+
if (returnValidationPending) {
|
|
60161
|
+
clearPendingEvents();
|
|
60162
|
+
}
|
|
60079
60163
|
return;
|
|
60080
60164
|
}
|
|
60081
60165
|
const previousSnapshot = previousSnapshotRef.current;
|
|
60082
60166
|
previousSnapshotRef.current = currentSnapshot;
|
|
60083
|
-
if (!previousSnapshot)
|
|
60167
|
+
if (!previousSnapshot) {
|
|
60168
|
+
finishReturnValidation([], currentSnapshot);
|
|
60169
|
+
return;
|
|
60170
|
+
}
|
|
60084
60171
|
const events = detectLineOvertakeEvents({
|
|
60085
60172
|
roleMode,
|
|
60086
60173
|
watchedLineIds,
|
|
@@ -60088,6 +60175,7 @@ var LineOvertakeNotificationManager = ({
|
|
|
60088
60175
|
currentRows: currentSnapshot
|
|
60089
60176
|
});
|
|
60090
60177
|
updateOvertakeEvents(events);
|
|
60178
|
+
finishReturnValidation(events, currentSnapshot);
|
|
60091
60179
|
} catch (error) {
|
|
60092
60180
|
console.warn("[LineOvertakeNotificationManager] Failed to poll daily leaderboard:", error);
|
|
60093
60181
|
} finally {
|
|
@@ -60101,8 +60189,11 @@ var LineOvertakeNotificationManager = ({
|
|
|
60101
60189
|
linesLoaded,
|
|
60102
60190
|
qaSimulationEnabled,
|
|
60103
60191
|
qaSimulationMode,
|
|
60192
|
+
returnValidationPending,
|
|
60104
60193
|
roleMode,
|
|
60105
60194
|
supabase,
|
|
60195
|
+
clearPendingEvents,
|
|
60196
|
+
finishReturnValidation,
|
|
60106
60197
|
updateOvertakeEvents,
|
|
60107
60198
|
visibleLineIds,
|
|
60108
60199
|
watchedLineIds
|
|
@@ -60120,14 +60211,12 @@ var LineOvertakeNotificationManager = ({
|
|
|
60120
60211
|
};
|
|
60121
60212
|
}, [pollIntervalMs, pollLeaderboard]);
|
|
60122
60213
|
if (!isOnActiveToastSurface) return null;
|
|
60214
|
+
if (returnValidationPending) return null;
|
|
60123
60215
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
60124
60216
|
LineOvertakeNotificationPopup,
|
|
60125
60217
|
{
|
|
60126
60218
|
events: notificationEvents,
|
|
60127
|
-
onDismiss:
|
|
60128
|
-
notificationEventsRef.current = [];
|
|
60129
|
-
setNotificationEvents([]);
|
|
60130
|
-
},
|
|
60219
|
+
onDismiss: acknowledgeCurrentEvents,
|
|
60131
60220
|
onOpenLeaderboard: openLeaderboard
|
|
60132
60221
|
}
|
|
60133
60222
|
);
|
|
@@ -65305,6 +65394,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65305
65394
|
const activeRequestIdRef = React146.useRef(0);
|
|
65306
65395
|
const isFetchingRef = React146.useRef(false);
|
|
65307
65396
|
const pendingRealtimeRefreshRef = React146.useRef(false);
|
|
65397
|
+
const pendingForcedRefreshRef = React146.useRef(false);
|
|
65308
65398
|
const realtimeRefreshTimerRef = React146.useRef(null);
|
|
65309
65399
|
const lastRealtimeRefreshStartedAtRef = React146.useRef(0);
|
|
65310
65400
|
const fetchBootstrap = React146.useCallback(async (force = false) => {
|
|
@@ -65378,6 +65468,18 @@ var useLiveMonitorBootstrap = ({
|
|
|
65378
65468
|
React146.useEffect(() => {
|
|
65379
65469
|
fetchBootstrapRef.current = fetchBootstrap;
|
|
65380
65470
|
}, [fetchBootstrap]);
|
|
65471
|
+
const requestScheduledForcedRefresh = React146.useCallback(() => {
|
|
65472
|
+
if (!enabled || !supabase || !resolvedCompanyId || normalizedLineIds.length === 0) {
|
|
65473
|
+
pendingForcedRefreshRef.current = false;
|
|
65474
|
+
return;
|
|
65475
|
+
}
|
|
65476
|
+
if (isFetchingRef.current) {
|
|
65477
|
+
pendingForcedRefreshRef.current = true;
|
|
65478
|
+
return;
|
|
65479
|
+
}
|
|
65480
|
+
pendingForcedRefreshRef.current = false;
|
|
65481
|
+
void fetchBootstrapRef.current(true);
|
|
65482
|
+
}, [enabled, normalizedLineIds.length, resolvedCompanyId, supabase]);
|
|
65381
65483
|
const clearRealtimeRefreshTimer = React146.useCallback(() => {
|
|
65382
65484
|
if (realtimeRefreshTimerRef.current !== null) {
|
|
65383
65485
|
window.clearTimeout(realtimeRefreshTimerRef.current);
|
|
@@ -65402,9 +65504,9 @@ var useLiveMonitorBootstrap = ({
|
|
|
65402
65504
|
}
|
|
65403
65505
|
pendingRealtimeRefreshRef.current = false;
|
|
65404
65506
|
lastRealtimeRefreshStartedAtRef.current = Date.now();
|
|
65405
|
-
|
|
65507
|
+
requestScheduledForcedRefresh();
|
|
65406
65508
|
}, nextDelay);
|
|
65407
|
-
}, [enabled, supabase]);
|
|
65509
|
+
}, [enabled, requestScheduledForcedRefresh, supabase]);
|
|
65408
65510
|
const queueRealtimeRefresh = React146.useCallback(() => {
|
|
65409
65511
|
if (!enabled || !supabase) {
|
|
65410
65512
|
pendingRealtimeRefreshRef.current = false;
|
|
@@ -65417,9 +65519,15 @@ var useLiveMonitorBootstrap = ({
|
|
|
65417
65519
|
React146.useEffect(() => {
|
|
65418
65520
|
return () => {
|
|
65419
65521
|
pendingRealtimeRefreshRef.current = false;
|
|
65522
|
+
pendingForcedRefreshRef.current = false;
|
|
65420
65523
|
clearRealtimeRefreshTimer();
|
|
65421
65524
|
};
|
|
65422
65525
|
}, [clearRealtimeRefreshTimer]);
|
|
65526
|
+
React146.useEffect(() => {
|
|
65527
|
+
if (!isLoading && pendingForcedRefreshRef.current) {
|
|
65528
|
+
requestScheduledForcedRefresh();
|
|
65529
|
+
}
|
|
65530
|
+
}, [isLoading, requestScheduledForcedRefresh]);
|
|
65423
65531
|
React146.useEffect(() => {
|
|
65424
65532
|
if (!enabled || !rawState || !resolvedCompanyId) {
|
|
65425
65533
|
return;
|
|
@@ -65558,9 +65666,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65558
65666
|
if (!enabled || !resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
65559
65667
|
return void 0;
|
|
65560
65668
|
}
|
|
65561
|
-
const forceRefreshOnResume = () =>
|
|
65562
|
-
void fetchBootstrapRef.current(true);
|
|
65563
|
-
};
|
|
65669
|
+
const forceRefreshOnResume = () => requestScheduledForcedRefresh();
|
|
65564
65670
|
const handleVisibilityChange = () => {
|
|
65565
65671
|
if (document.visibilityState === "visible") {
|
|
65566
65672
|
forceRefreshOnResume();
|
|
@@ -65574,7 +65680,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65574
65680
|
window.removeEventListener("focus", forceRefreshOnResume);
|
|
65575
65681
|
window.removeEventListener("online", forceRefreshOnResume);
|
|
65576
65682
|
};
|
|
65577
|
-
}, [enabled, normalizedLineIds.length, resolvedCompanyId, supabase]);
|
|
65683
|
+
}, [enabled, normalizedLineIds.length, requestScheduledForcedRefresh, resolvedCompanyId, supabase]);
|
|
65578
65684
|
React146.useEffect(() => {
|
|
65579
65685
|
if (!enabled || !resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
65580
65686
|
return void 0;
|
|
@@ -65582,7 +65688,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65582
65688
|
let intervalId = null;
|
|
65583
65689
|
let timeoutId = null;
|
|
65584
65690
|
const runMinuteTick = () => {
|
|
65585
|
-
|
|
65691
|
+
requestScheduledForcedRefresh();
|
|
65586
65692
|
};
|
|
65587
65693
|
const startInterval = () => {
|
|
65588
65694
|
runMinuteTick();
|
|
@@ -65601,7 +65707,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65601
65707
|
window.clearInterval(intervalId);
|
|
65602
65708
|
}
|
|
65603
65709
|
};
|
|
65604
|
-
}, [enabled,
|
|
65710
|
+
}, [enabled, normalizedLineIds, requestScheduledForcedRefresh, resolvedCompanyId, supabase]);
|
|
65605
65711
|
const isCurrentScopeResolved = state.requestKey === requestKey;
|
|
65606
65712
|
return {
|
|
65607
65713
|
resolvedScope: state.resolvedScope,
|
|
@@ -71578,6 +71684,7 @@ var KPIsOverviewView = ({
|
|
|
71578
71684
|
const [viewType, setViewType] = React146.useState("operator");
|
|
71579
71685
|
const [selectedLeaderboardDate, setSelectedLeaderboardDate] = React146.useState("");
|
|
71580
71686
|
const [selectedLeaderboardShiftId, setSelectedLeaderboardShiftId] = React146.useState(0);
|
|
71687
|
+
const [leaderboardDailyScopeMode, setLeaderboardDailyScopeMode] = React146.useState("live");
|
|
71581
71688
|
const [hasHydratedLeaderboardRouteState, setHasHydratedLeaderboardRouteState] = React146.useState(false);
|
|
71582
71689
|
const [loading, setLoading] = React146.useState(true);
|
|
71583
71690
|
const [isFilterOpen, setIsFilterOpen] = React146.useState(false);
|
|
@@ -71697,14 +71804,16 @@ var KPIsOverviewView = ({
|
|
|
71697
71804
|
const currentShiftId = currentShiftDetails.shiftId;
|
|
71698
71805
|
const activeFiltersCount = React146__namespace.default.useMemo(() => {
|
|
71699
71806
|
let count = 0;
|
|
71700
|
-
if (selectedLeaderboardShiftId !== currentShiftId) {
|
|
71807
|
+
if (leaderboardDailyScopeMode === "historical" && selectedLeaderboardShiftId !== currentShiftId) {
|
|
71701
71808
|
count++;
|
|
71702
71809
|
}
|
|
71703
71810
|
return count;
|
|
71704
|
-
}, [selectedLeaderboardShiftId, currentShiftId]);
|
|
71811
|
+
}, [leaderboardDailyScopeMode, selectedLeaderboardShiftId, currentShiftId]);
|
|
71705
71812
|
const clearFilters = React146__namespace.default.useCallback(() => {
|
|
71706
71813
|
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71707
|
-
|
|
71814
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
71815
|
+
setLeaderboardDailyScopeMode("live");
|
|
71816
|
+
}, [currentShiftDate, currentShiftId]);
|
|
71708
71817
|
React146.useEffect(() => {
|
|
71709
71818
|
const handleClickOutside = (event) => {
|
|
71710
71819
|
const target = event.target;
|
|
@@ -71736,7 +71845,24 @@ var KPIsOverviewView = ({
|
|
|
71736
71845
|
}, [shiftConfig]);
|
|
71737
71846
|
const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
|
|
71738
71847
|
const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
|
|
71739
|
-
const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
|
|
71848
|
+
const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
|
|
71849
|
+
const updateLeaderboardDate = React146__namespace.default.useCallback((dateKey) => {
|
|
71850
|
+
setSelectedLeaderboardDate(dateKey);
|
|
71851
|
+
setLeaderboardDailyScopeMode(
|
|
71852
|
+
dateKey === currentShiftDate && effectiveLeaderboardShiftId === currentShiftId ? "live" : "historical"
|
|
71853
|
+
);
|
|
71854
|
+
}, [currentShiftDate, currentShiftId, effectiveLeaderboardShiftId]);
|
|
71855
|
+
const updateLeaderboardShiftId = React146__namespace.default.useCallback((shiftId) => {
|
|
71856
|
+
setSelectedLeaderboardShiftId(shiftId);
|
|
71857
|
+
setLeaderboardDailyScopeMode(
|
|
71858
|
+
effectiveLeaderboardDate === currentShiftDate && shiftId === currentShiftId ? "live" : "historical"
|
|
71859
|
+
);
|
|
71860
|
+
}, [currentShiftDate, currentShiftId, effectiveLeaderboardDate]);
|
|
71861
|
+
const returnLeaderboardToLive = React146__namespace.default.useCallback(() => {
|
|
71862
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
71863
|
+
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71864
|
+
setLeaderboardDailyScopeMode("live");
|
|
71865
|
+
}, [currentShiftDate, currentShiftId]);
|
|
71740
71866
|
const selectedFactoryIdFromUrl = getSingleQueryValue(router$1.query[KPI_FACTORY_QUERY_PARAM]);
|
|
71741
71867
|
const selectedFactoryAreaIdFromUrl = getSingleQueryValue(router$1.query[KPI_FACTORY_AREA_QUERY_PARAM]);
|
|
71742
71868
|
const kpiLineHierarchy = React146__namespace.default.useMemo(
|
|
@@ -71762,10 +71888,12 @@ var KPIsOverviewView = ({
|
|
|
71762
71888
|
if (hasHistoricalQuery) {
|
|
71763
71889
|
setSelectedLeaderboardDate(dateQuery);
|
|
71764
71890
|
setSelectedLeaderboardShiftId(parsedShiftQuery);
|
|
71891
|
+
setLeaderboardDailyScopeMode("historical");
|
|
71765
71892
|
setTimeRange("today");
|
|
71766
71893
|
} else {
|
|
71767
71894
|
setSelectedLeaderboardDate(currentShiftDate);
|
|
71768
71895
|
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71896
|
+
setLeaderboardDailyScopeMode("live");
|
|
71769
71897
|
}
|
|
71770
71898
|
setHasHydratedLeaderboardRouteState(true);
|
|
71771
71899
|
}, [
|
|
@@ -71788,7 +71916,8 @@ var KPIsOverviewView = ({
|
|
|
71788
71916
|
pendingTabRouteSyncRef.current = null;
|
|
71789
71917
|
}
|
|
71790
71918
|
const expectedTab = activeTab === "leaderboard" ? "leaderboard" : void 0;
|
|
71791
|
-
const
|
|
71919
|
+
const shouldPersistHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && isHistoricalLeaderboardDaily;
|
|
71920
|
+
const expectedDate = shouldPersistHistoricalLeaderboardDaily ? effectiveLeaderboardDate : void 0;
|
|
71792
71921
|
const expectedShift = expectedDate !== void 0 ? effectiveLeaderboardShiftId.toString() : void 0;
|
|
71793
71922
|
const expectedFactory = activeTab === "today" && selectedFactoryNode ? selectedFactoryNode.id : void 0;
|
|
71794
71923
|
const expectedFactoryArea = activeTab === "today" && selectedFactoryNode && selectedFactoryAreaNode ? selectedFactoryAreaNode.id : void 0;
|
|
@@ -71814,6 +71943,7 @@ var KPIsOverviewView = ({
|
|
|
71814
71943
|
router$1,
|
|
71815
71944
|
activeTab,
|
|
71816
71945
|
timeRange,
|
|
71946
|
+
leaderboardDailyScopeMode,
|
|
71817
71947
|
effectiveLeaderboardDate,
|
|
71818
71948
|
effectiveLeaderboardShiftId,
|
|
71819
71949
|
hasHydratedLeaderboardRouteState,
|
|
@@ -72235,7 +72365,7 @@ var KPIsOverviewView = ({
|
|
|
72235
72365
|
const currentEfficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
|
|
72236
72366
|
const currentFallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
|
|
72237
72367
|
const showLeaderboardLoader = activeTab === "leaderboard" && (leaderboardLinesLoading || isLeaderboardLoading && currentEfficiencyMap.size === 0 && (currentFallbackEfficiencyMap?.size ?? 0) === 0);
|
|
72238
|
-
const showHistoricalLeaderboardHeader = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily;
|
|
72368
|
+
const showHistoricalLeaderboardHeader = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && isHistoricalLeaderboardDaily;
|
|
72239
72369
|
const headerDateKey = activeTab === "leaderboard" && timeRange === "today" ? effectiveLeaderboardDate : monthEndDateKey;
|
|
72240
72370
|
const headerShiftId = showHistoricalLeaderboardHeader ? effectiveLeaderboardShiftId : currentShiftDetails.shiftId;
|
|
72241
72371
|
const headerShiftName = getShiftNameById(headerShiftId, configuredTimezone, shiftConfig).replace(/ Shift$/i, "");
|
|
@@ -72430,10 +72560,7 @@ var KPIsOverviewView = ({
|
|
|
72430
72560
|
"button",
|
|
72431
72561
|
{
|
|
72432
72562
|
type: "button",
|
|
72433
|
-
onClick:
|
|
72434
|
-
setSelectedLeaderboardDate(currentShiftDate);
|
|
72435
|
-
setSelectedLeaderboardShiftId(currentShiftId);
|
|
72436
|
-
},
|
|
72563
|
+
onClick: returnLeaderboardToLive,
|
|
72437
72564
|
className: "text-[10px] font-medium text-blue-600 hover:text-blue-700 hover:underline bg-blue-50 px-2 py-1 rounded-md",
|
|
72438
72565
|
children: "Return to Live"
|
|
72439
72566
|
}
|
|
@@ -72479,10 +72606,7 @@ var KPIsOverviewView = ({
|
|
|
72479
72606
|
"button",
|
|
72480
72607
|
{
|
|
72481
72608
|
type: "button",
|
|
72482
|
-
onClick:
|
|
72483
|
-
setSelectedLeaderboardDate(currentShiftDate);
|
|
72484
|
-
setSelectedLeaderboardShiftId(currentShiftId);
|
|
72485
|
-
},
|
|
72609
|
+
onClick: returnLeaderboardToLive,
|
|
72486
72610
|
className: "text-xs sm:text-sm font-medium text-blue-600 bg-blue-50 border border-blue-100 hover:bg-blue-100 hover:text-blue-700 px-3 py-1.5 rounded-lg transition-colors shadow-sm ml-4 whitespace-nowrap",
|
|
72487
72611
|
children: "Return to Live"
|
|
72488
72612
|
}
|
|
@@ -72550,7 +72674,7 @@ var KPIsOverviewView = ({
|
|
|
72550
72674
|
endKey: effectiveLeaderboardDate
|
|
72551
72675
|
},
|
|
72552
72676
|
onChange: (range) => {
|
|
72553
|
-
|
|
72677
|
+
updateLeaderboardDate(range.startKey);
|
|
72554
72678
|
},
|
|
72555
72679
|
showLabel: false,
|
|
72556
72680
|
singleDateOnly: true
|
|
@@ -72590,7 +72714,7 @@ var KPIsOverviewView = ({
|
|
|
72590
72714
|
{
|
|
72591
72715
|
"aria-label": "Leaderboard shift",
|
|
72592
72716
|
value: effectiveLeaderboardShiftId,
|
|
72593
|
-
onChange: (e) =>
|
|
72717
|
+
onChange: (e) => updateLeaderboardShiftId(Number(e.target.value)),
|
|
72594
72718
|
className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
|
|
72595
72719
|
style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
|
|
72596
72720
|
children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
|
|
@@ -72988,19 +73112,31 @@ var LeaderboardDetailView = React146.memo(({
|
|
|
72988
73112
|
if (lineId2 === line2Id) return "Line 2";
|
|
72989
73113
|
return `Line ${lineId2.substring(0, 8)}`;
|
|
72990
73114
|
}, [dbLineNames, configuredLineNames, lineNames, line1Id, line2Id]);
|
|
72991
|
-
const configuredLineIds = React146.useMemo(() => {
|
|
72992
|
-
return getConfiguredLineIds(entityConfig);
|
|
72993
|
-
}, [entityConfig]);
|
|
72994
73115
|
const accessibleLineIdSet = React146.useMemo(
|
|
72995
73116
|
() => new Set((userAccessibleLineIds || []).filter(Boolean)),
|
|
72996
73117
|
[userAccessibleLineIds]
|
|
72997
73118
|
);
|
|
73119
|
+
const configuredLineIds = React146.useMemo(() => {
|
|
73120
|
+
const allConfiguredLineIds = getConfiguredLineIds(entityConfig);
|
|
73121
|
+
if (!userAccessibleLineIds) {
|
|
73122
|
+
return allConfiguredLineIds;
|
|
73123
|
+
}
|
|
73124
|
+
if (accessibleLineIdSet.size === 0) {
|
|
73125
|
+
return [];
|
|
73126
|
+
}
|
|
73127
|
+
return allConfiguredLineIds.filter((lineId2) => accessibleLineIdSet.has(lineId2));
|
|
73128
|
+
}, [accessibleLineIdSet, entityConfig, userAccessibleLineIds]);
|
|
72998
73129
|
const canOpenWorkspace = React146.useCallback((workspaceLineId) => {
|
|
72999
73130
|
if (!workspaceLineId) return false;
|
|
73000
73131
|
if (!userAccessibleLineIds) return true;
|
|
73001
73132
|
if (accessibleLineIdSet.size === 0) return false;
|
|
73002
73133
|
return accessibleLineIdSet.has(workspaceLineId);
|
|
73003
73134
|
}, [accessibleLineIdSet, userAccessibleLineIds]);
|
|
73135
|
+
React146.useEffect(() => {
|
|
73136
|
+
if (selectedLineFilter !== "all" && !configuredLineIds.includes(selectedLineFilter)) {
|
|
73137
|
+
setSelectedLineFilter("all");
|
|
73138
|
+
}
|
|
73139
|
+
}, [configuredLineIds, selectedLineFilter]);
|
|
73004
73140
|
const { hasUptime: lineModeHasUptime, hasOutput: lineModeHasOutput } = React146.useMemo(() => {
|
|
73005
73141
|
if (!lines || lines.length === 0) {
|
|
73006
73142
|
return { hasUptime: false, hasOutput: false };
|
|
@@ -73431,6 +73567,13 @@ var LeaderboardDetailView = React146.memo(({
|
|
|
73431
73567
|
fetchMonthlyLeaderboard();
|
|
73432
73568
|
}
|
|
73433
73569
|
}, [activeTab, fetchMonthlyLeaderboard]);
|
|
73570
|
+
const retryLeaderboard = React146.useCallback(() => {
|
|
73571
|
+
if (activeTab === "monthly") {
|
|
73572
|
+
fetchMonthlyLeaderboard();
|
|
73573
|
+
return;
|
|
73574
|
+
}
|
|
73575
|
+
fetchTodayLeaderboard();
|
|
73576
|
+
}, [activeTab, fetchMonthlyLeaderboard, fetchTodayLeaderboard]);
|
|
73434
73577
|
React146.useEffect(() => {
|
|
73435
73578
|
if (!supabase || !entityConfig.companyId) return;
|
|
73436
73579
|
if (!realtimeEnabled) return;
|
|
@@ -73694,9 +73837,26 @@ var LeaderboardDetailView = React146.memo(({
|
|
|
73694
73837
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xl text-gray-600", children: "Loading workspaces..." }) });
|
|
73695
73838
|
}
|
|
73696
73839
|
if (error) {
|
|
73697
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
73698
|
-
"
|
|
73699
|
-
|
|
73840
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full max-w-md mx-4 rounded-lg border border-slate-200 bg-white p-6 text-center shadow-sm", children: [
|
|
73841
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-full bg-amber-50 text-amber-600", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-5 w-5", "aria-hidden": "true" }) }),
|
|
73842
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold text-slate-900", children: "Leaderboard could not be refreshed" }),
|
|
73843
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm leading-6 text-slate-600", children: "Your access may have changed or the dashboard data service may be temporarily unavailable." }),
|
|
73844
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
73845
|
+
"button",
|
|
73846
|
+
{
|
|
73847
|
+
type: "button",
|
|
73848
|
+
onClick: retryLeaderboard,
|
|
73849
|
+
className: "mt-5 inline-flex items-center justify-center gap-2 rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2",
|
|
73850
|
+
children: [
|
|
73851
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
73852
|
+
"Retry"
|
|
73853
|
+
]
|
|
73854
|
+
}
|
|
73855
|
+
),
|
|
73856
|
+
error.code && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-3 text-xs text-slate-400", children: [
|
|
73857
|
+
"Reference: ",
|
|
73858
|
+
error.code
|
|
73859
|
+
] })
|
|
73700
73860
|
] }) });
|
|
73701
73861
|
}
|
|
73702
73862
|
const hasCycleTimeLeaderboardRows = sortedWorkspaces.some(
|
package/dist/index.mjs
CHANGED
|
@@ -10,7 +10,7 @@ import { EventEmitter } from 'events';
|
|
|
10
10
|
import { createClient, REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js';
|
|
11
11
|
import Hls, { Events, ErrorTypes } from 'hls.js';
|
|
12
12
|
import useSWR from 'swr';
|
|
13
|
-
import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, HelpCircle, ClipboardX, Activity, Wrench, UserX, Clock, Package,
|
|
13
|
+
import { Camera, AlertTriangle, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, RefreshCw, Filter, X, Coffee, Plus, ArrowUp, ArrowDown, ArrowRight, HelpCircle, ClipboardX, Activity, Wrench, UserX, Clock, Package, CheckCircle2, ArrowLeft, Calendar, Save, AlertCircle, Loader2, Minus, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, XCircle, Palette, LockKeyhole, TrendingDown, FolderOpen, Folder, ArrowDownWideNarrow, Tag, Sliders, Layers, Search, Edit2, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Video, Copy, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, Pencil, UserCheck, LogOut, Film, MessageSquare, Menu, Send, Settings, LifeBuoy, EyeOff, Zap, Flame, Crown, Medal } from 'lucide-react';
|
|
14
14
|
import { memo, noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds } from 'motion-utils';
|
|
15
15
|
import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, Customized, Cell, PieChart, Pie, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
|
|
16
16
|
import { Slot } from '@radix-ui/react-slot';
|
|
@@ -37257,7 +37257,9 @@ var HourlyOutputChartComponent = ({
|
|
|
37257
37257
|
const idleSlot = idleSlots[i];
|
|
37258
37258
|
const explicitTarget = hasHourlyTargetOutputProp ? effectiveHourlyTargetOutput?.[i] ?? null : void 0;
|
|
37259
37259
|
const currentTarget = hasHourlyTargetOutputProp ? explicitTarget : targets[i] || pphThreshold;
|
|
37260
|
+
const outputForComparison = Math.round(animatedData[i] || 0);
|
|
37260
37261
|
const comparisonTarget = currentTarget === null || currentTarget === void 0 ? targets[i] || pphThreshold : currentTarget;
|
|
37262
|
+
const targetForComparison = Math.round(comparisonTarget);
|
|
37261
37263
|
return {
|
|
37262
37264
|
hourIndex: idleSlot?.hourIndex ?? i,
|
|
37263
37265
|
hour: idleSlot?.hour || "",
|
|
@@ -37266,7 +37268,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37266
37268
|
originalOutput: data[i] || 0,
|
|
37267
37269
|
// Keep original data for labels
|
|
37268
37270
|
target: currentTarget ?? null,
|
|
37269
|
-
color:
|
|
37271
|
+
color: outputForComparison >= targetForComparison ? "#00AB45" : "#E34329",
|
|
37270
37272
|
idleMinutes: idleSlot?.idleMinutes || 0,
|
|
37271
37273
|
idleArray: idleSlot?.idleArray || [],
|
|
37272
37274
|
skuIndex: i,
|
|
@@ -59636,6 +59638,42 @@ var buildSnapshotRows = (entries, lines) => {
|
|
|
59636
59638
|
rowType: row.rowType
|
|
59637
59639
|
}));
|
|
59638
59640
|
};
|
|
59641
|
+
var isValidSnapshotRow = (row) => !!row && typeof row.efficiency === "number" && Number.isFinite(row.efficiency) && typeof row.rank === "number" && Number.isFinite(row.rank);
|
|
59642
|
+
var refreshPendingEventsFromSnapshot = (events, currentSnapshot) => {
|
|
59643
|
+
if (events.length === 0 || currentSnapshot.length === 0) return [];
|
|
59644
|
+
const snapshotByRowId = new Map(currentSnapshot.map((row) => [row.lineId, row]));
|
|
59645
|
+
return events.flatMap((event) => {
|
|
59646
|
+
const currentSubject = snapshotByRowId.get(event.crossingLineId);
|
|
59647
|
+
if (!isValidSnapshotRow(currentSubject)) return [];
|
|
59648
|
+
const movedFromOriginalRank = event.direction === "up" ? currentSubject.rank < event.previousRank : currentSubject.rank > event.previousRank;
|
|
59649
|
+
if (!movedFromOriginalRank) return [];
|
|
59650
|
+
const crossedLines = event.crossedLines.flatMap((crossedLine) => {
|
|
59651
|
+
const currentCrossedLine = snapshotByRowId.get(crossedLine.lineId);
|
|
59652
|
+
if (!isValidSnapshotRow(currentCrossedLine)) return [];
|
|
59653
|
+
const stillCrossed = event.direction === "up" ? currentSubject.rank < currentCrossedLine.rank : currentSubject.rank > currentCrossedLine.rank;
|
|
59654
|
+
if (!stillCrossed) return [];
|
|
59655
|
+
return [{
|
|
59656
|
+
...crossedLine,
|
|
59657
|
+
lineName: currentCrossedLine.lineName,
|
|
59658
|
+
currentRank: currentCrossedLine.rank,
|
|
59659
|
+
currentEfficiency: currentCrossedLine.efficiency
|
|
59660
|
+
}];
|
|
59661
|
+
});
|
|
59662
|
+
if (crossedLines.length !== event.crossedLines.length) return [];
|
|
59663
|
+
return [{
|
|
59664
|
+
...event,
|
|
59665
|
+
crossingLineName: currentSubject.lineName,
|
|
59666
|
+
currentRank: currentSubject.rank,
|
|
59667
|
+
currentEfficiency: currentSubject.efficiency,
|
|
59668
|
+
crossedLines,
|
|
59669
|
+
eventKey: buildLineOvertakeEventKey(
|
|
59670
|
+
event.crossingLineId,
|
|
59671
|
+
event.direction,
|
|
59672
|
+
crossedLines.map((line) => line.lineId)
|
|
59673
|
+
)
|
|
59674
|
+
}];
|
|
59675
|
+
});
|
|
59676
|
+
};
|
|
59639
59677
|
var formatCrossedLineNames = (event) => {
|
|
59640
59678
|
const names = event.crossedLines.map((line) => line.lineName).filter(Boolean);
|
|
59641
59679
|
if (names.length === 0) return "another line";
|
|
@@ -59693,6 +59731,7 @@ var storeEventKey = (scopeKey, eventKey) => {
|
|
|
59693
59731
|
} catch {
|
|
59694
59732
|
}
|
|
59695
59733
|
};
|
|
59734
|
+
var buildAcknowledgementKey = (scopeKey, eventKey) => `${scopeKey}:${eventKey}`;
|
|
59696
59735
|
var LineOvertakeNotificationPopup = ({
|
|
59697
59736
|
events,
|
|
59698
59737
|
onDismiss,
|
|
@@ -59842,6 +59881,7 @@ var LineOvertakeNotificationManager = ({
|
|
|
59842
59881
|
const [visibleLines, setVisibleLines] = useState([]);
|
|
59843
59882
|
const [linesLoaded, setLinesLoaded] = useState(false);
|
|
59844
59883
|
const [notificationEvents, setNotificationEvents] = useState([]);
|
|
59884
|
+
const [returnValidationPending, setReturnValidationPending] = useState(false);
|
|
59845
59885
|
const isOnActiveToastSurface = isActiveToastSurface(router.asPath);
|
|
59846
59886
|
const qaSimulationMode = isOnActiveToastSurface ? getLocalQaSimulationMode(router.asPath) : null;
|
|
59847
59887
|
const qaSimulationEnabled = Boolean(qaSimulationMode);
|
|
@@ -59868,20 +59908,33 @@ var LineOvertakeNotificationManager = ({
|
|
|
59868
59908
|
const scopeKeyRef = useRef("");
|
|
59869
59909
|
const pollInFlightRef = useRef(false);
|
|
59870
59910
|
const notificationEventsRef = useRef([]);
|
|
59911
|
+
const acknowledgedEventKeysRef = useRef(/* @__PURE__ */ new Set());
|
|
59912
|
+
const wasOnActiveToastSurfaceRef = useRef(isOnActiveToastSurface);
|
|
59871
59913
|
const dedupeScopeKey = useMemo(
|
|
59872
|
-
() =>
|
|
59873
|
-
|
|
59874
|
-
|
|
59875
|
-
|
|
59876
|
-
|
|
59877
|
-
|
|
59878
|
-
|
|
59879
|
-
|
|
59914
|
+
() => {
|
|
59915
|
+
if (qaSimulationEnabled) {
|
|
59916
|
+
return [
|
|
59917
|
+
user?.id || "anonymous",
|
|
59918
|
+
"qa-simulation",
|
|
59919
|
+
qaSimulationMode || "default"
|
|
59920
|
+
].join("|");
|
|
59921
|
+
}
|
|
59922
|
+
return [
|
|
59923
|
+
user?.id || "anonymous",
|
|
59924
|
+
companyId || "no-company",
|
|
59925
|
+
currentShift.date,
|
|
59926
|
+
currentShift.shiftId,
|
|
59927
|
+
roleMode || "disabled",
|
|
59928
|
+
watchedLineIds.slice().sort().join(",")
|
|
59929
|
+
].join("|");
|
|
59930
|
+
},
|
|
59880
59931
|
[
|
|
59881
59932
|
user?.id,
|
|
59882
59933
|
companyId,
|
|
59883
59934
|
currentShift.date,
|
|
59884
59935
|
currentShift.shiftId,
|
|
59936
|
+
qaSimulationEnabled,
|
|
59937
|
+
qaSimulationMode,
|
|
59885
59938
|
roleMode,
|
|
59886
59939
|
watchedLineIds
|
|
59887
59940
|
]
|
|
@@ -59918,13 +59971,45 @@ var LineOvertakeNotificationManager = ({
|
|
|
59918
59971
|
previousSnapshotRef.current = null;
|
|
59919
59972
|
notificationEventsRef.current = [];
|
|
59920
59973
|
setNotificationEvents([]);
|
|
59974
|
+
setReturnValidationPending(false);
|
|
59921
59975
|
scopeKeyRef.current = scopeKey;
|
|
59922
59976
|
}, [isOnActiveToastSurface, scopeKey]);
|
|
59923
59977
|
useEffect(() => {
|
|
59924
|
-
|
|
59978
|
+
const wasOnActiveToastSurface = wasOnActiveToastSurfaceRef.current;
|
|
59979
|
+
wasOnActiveToastSurfaceRef.current = isOnActiveToastSurface;
|
|
59980
|
+
if (wasOnActiveToastSurface && !isOnActiveToastSurface && notificationEventsRef.current.length > 0) {
|
|
59981
|
+
setReturnValidationPending(true);
|
|
59982
|
+
return;
|
|
59983
|
+
}
|
|
59984
|
+
if (!wasOnActiveToastSurface && isOnActiveToastSurface && notificationEventsRef.current.length === 0) {
|
|
59985
|
+
setReturnValidationPending(false);
|
|
59986
|
+
}
|
|
59987
|
+
}, [isOnActiveToastSurface]);
|
|
59988
|
+
const acknowledgeCurrentEvents = useCallback(() => {
|
|
59989
|
+
notificationEventsRef.current.forEach((event) => {
|
|
59990
|
+
acknowledgedEventKeysRef.current.add(buildAcknowledgementKey(dedupeScopeKey, event.eventKey));
|
|
59991
|
+
storeEventKey(dedupeScopeKey, event.eventKey);
|
|
59992
|
+
});
|
|
59925
59993
|
notificationEventsRef.current = [];
|
|
59926
59994
|
setNotificationEvents([]);
|
|
59927
|
-
|
|
59995
|
+
setReturnValidationPending(false);
|
|
59996
|
+
}, [dedupeScopeKey]);
|
|
59997
|
+
const clearPendingEvents = useCallback(() => {
|
|
59998
|
+
notificationEventsRef.current = [];
|
|
59999
|
+
setNotificationEvents([]);
|
|
60000
|
+
setReturnValidationPending(false);
|
|
60001
|
+
}, []);
|
|
60002
|
+
const finishReturnValidation = useCallback((events, currentSnapshot) => {
|
|
60003
|
+
if (events.length === 0 && notificationEventsRef.current.length > 0) {
|
|
60004
|
+
const validatedEvents = refreshPendingEventsFromSnapshot(
|
|
60005
|
+
notificationEventsRef.current,
|
|
60006
|
+
currentSnapshot
|
|
60007
|
+
);
|
|
60008
|
+
notificationEventsRef.current = validatedEvents;
|
|
60009
|
+
setNotificationEvents(validatedEvents);
|
|
60010
|
+
}
|
|
60011
|
+
setReturnValidationPending(false);
|
|
60012
|
+
}, []);
|
|
59928
60013
|
useEffect(() => {
|
|
59929
60014
|
let cancelled = false;
|
|
59930
60015
|
const loadLines = async () => {
|
|
@@ -59965,10 +60050,9 @@ var LineOvertakeNotificationManager = ({
|
|
|
59965
60050
|
};
|
|
59966
60051
|
}, [companyId, isOnActiveToastSurface, qaSimulationEnabled, roleMode, supabase]);
|
|
59967
60052
|
const openLeaderboard = useCallback(() => {
|
|
59968
|
-
|
|
59969
|
-
setNotificationEvents([]);
|
|
60053
|
+
acknowledgeCurrentEvents();
|
|
59970
60054
|
void router.push("/kpis?tab=leaderboard");
|
|
59971
|
-
}, [router]);
|
|
60055
|
+
}, [acknowledgeCurrentEvents, router]);
|
|
59972
60056
|
const updateOvertakeEvents = useCallback((events) => {
|
|
59973
60057
|
if (events.length === 0) return;
|
|
59974
60058
|
const currentEventByRowId = new Map(
|
|
@@ -59976,13 +60060,9 @@ var LineOvertakeNotificationManager = ({
|
|
|
59976
60060
|
);
|
|
59977
60061
|
const nextEvents = events.filter((event) => {
|
|
59978
60062
|
if (currentEventByRowId.has(event.crossingLineId)) return true;
|
|
59979
|
-
return !hasStoredEventKey(dedupeScopeKey, event.eventKey);
|
|
60063
|
+
return !(acknowledgedEventKeysRef.current.has(buildAcknowledgementKey(dedupeScopeKey, event.eventKey)) || hasStoredEventKey(dedupeScopeKey, event.eventKey));
|
|
59980
60064
|
});
|
|
59981
60065
|
if (nextEvents.length === 0) return;
|
|
59982
|
-
nextEvents.forEach((event) => {
|
|
59983
|
-
if (currentEventByRowId.has(event.crossingLineId)) return;
|
|
59984
|
-
storeEventKey(dedupeScopeKey, event.eventKey);
|
|
59985
|
-
});
|
|
59986
60066
|
setNotificationEvents((currentEvents) => {
|
|
59987
60067
|
const eventByRowId = new Map(currentEvents.map((event) => [event.crossingLineId, event]));
|
|
59988
60068
|
nextEvents.forEach((event) => {
|
|
@@ -60025,6 +60105,7 @@ var LineOvertakeNotificationManager = ({
|
|
|
60025
60105
|
});
|
|
60026
60106
|
previousSnapshotRef.current = QA_CROSSED_ROWS;
|
|
60027
60107
|
updateOvertakeEvents(events);
|
|
60108
|
+
finishReturnValidation(events, QA_CROSSED_ROWS);
|
|
60028
60109
|
} finally {
|
|
60029
60110
|
pollInFlightRef.current = false;
|
|
60030
60111
|
}
|
|
@@ -60047,11 +60128,17 @@ var LineOvertakeNotificationManager = ({
|
|
|
60047
60128
|
const currentSnapshot = buildSnapshotRows(entries, visibleLines);
|
|
60048
60129
|
if (currentSnapshot.length === 0) {
|
|
60049
60130
|
previousSnapshotRef.current = null;
|
|
60131
|
+
if (returnValidationPending) {
|
|
60132
|
+
clearPendingEvents();
|
|
60133
|
+
}
|
|
60050
60134
|
return;
|
|
60051
60135
|
}
|
|
60052
60136
|
const previousSnapshot = previousSnapshotRef.current;
|
|
60053
60137
|
previousSnapshotRef.current = currentSnapshot;
|
|
60054
|
-
if (!previousSnapshot)
|
|
60138
|
+
if (!previousSnapshot) {
|
|
60139
|
+
finishReturnValidation([], currentSnapshot);
|
|
60140
|
+
return;
|
|
60141
|
+
}
|
|
60055
60142
|
const events = detectLineOvertakeEvents({
|
|
60056
60143
|
roleMode,
|
|
60057
60144
|
watchedLineIds,
|
|
@@ -60059,6 +60146,7 @@ var LineOvertakeNotificationManager = ({
|
|
|
60059
60146
|
currentRows: currentSnapshot
|
|
60060
60147
|
});
|
|
60061
60148
|
updateOvertakeEvents(events);
|
|
60149
|
+
finishReturnValidation(events, currentSnapshot);
|
|
60062
60150
|
} catch (error) {
|
|
60063
60151
|
console.warn("[LineOvertakeNotificationManager] Failed to poll daily leaderboard:", error);
|
|
60064
60152
|
} finally {
|
|
@@ -60072,8 +60160,11 @@ var LineOvertakeNotificationManager = ({
|
|
|
60072
60160
|
linesLoaded,
|
|
60073
60161
|
qaSimulationEnabled,
|
|
60074
60162
|
qaSimulationMode,
|
|
60163
|
+
returnValidationPending,
|
|
60075
60164
|
roleMode,
|
|
60076
60165
|
supabase,
|
|
60166
|
+
clearPendingEvents,
|
|
60167
|
+
finishReturnValidation,
|
|
60077
60168
|
updateOvertakeEvents,
|
|
60078
60169
|
visibleLineIds,
|
|
60079
60170
|
watchedLineIds
|
|
@@ -60091,14 +60182,12 @@ var LineOvertakeNotificationManager = ({
|
|
|
60091
60182
|
};
|
|
60092
60183
|
}, [pollIntervalMs, pollLeaderboard]);
|
|
60093
60184
|
if (!isOnActiveToastSurface) return null;
|
|
60185
|
+
if (returnValidationPending) return null;
|
|
60094
60186
|
return /* @__PURE__ */ jsx(
|
|
60095
60187
|
LineOvertakeNotificationPopup,
|
|
60096
60188
|
{
|
|
60097
60189
|
events: notificationEvents,
|
|
60098
|
-
onDismiss:
|
|
60099
|
-
notificationEventsRef.current = [];
|
|
60100
|
-
setNotificationEvents([]);
|
|
60101
|
-
},
|
|
60190
|
+
onDismiss: acknowledgeCurrentEvents,
|
|
60102
60191
|
onOpenLeaderboard: openLeaderboard
|
|
60103
60192
|
}
|
|
60104
60193
|
);
|
|
@@ -65276,6 +65365,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65276
65365
|
const activeRequestIdRef = useRef(0);
|
|
65277
65366
|
const isFetchingRef = useRef(false);
|
|
65278
65367
|
const pendingRealtimeRefreshRef = useRef(false);
|
|
65368
|
+
const pendingForcedRefreshRef = useRef(false);
|
|
65279
65369
|
const realtimeRefreshTimerRef = useRef(null);
|
|
65280
65370
|
const lastRealtimeRefreshStartedAtRef = useRef(0);
|
|
65281
65371
|
const fetchBootstrap = useCallback(async (force = false) => {
|
|
@@ -65349,6 +65439,18 @@ var useLiveMonitorBootstrap = ({
|
|
|
65349
65439
|
useEffect(() => {
|
|
65350
65440
|
fetchBootstrapRef.current = fetchBootstrap;
|
|
65351
65441
|
}, [fetchBootstrap]);
|
|
65442
|
+
const requestScheduledForcedRefresh = useCallback(() => {
|
|
65443
|
+
if (!enabled || !supabase || !resolvedCompanyId || normalizedLineIds.length === 0) {
|
|
65444
|
+
pendingForcedRefreshRef.current = false;
|
|
65445
|
+
return;
|
|
65446
|
+
}
|
|
65447
|
+
if (isFetchingRef.current) {
|
|
65448
|
+
pendingForcedRefreshRef.current = true;
|
|
65449
|
+
return;
|
|
65450
|
+
}
|
|
65451
|
+
pendingForcedRefreshRef.current = false;
|
|
65452
|
+
void fetchBootstrapRef.current(true);
|
|
65453
|
+
}, [enabled, normalizedLineIds.length, resolvedCompanyId, supabase]);
|
|
65352
65454
|
const clearRealtimeRefreshTimer = useCallback(() => {
|
|
65353
65455
|
if (realtimeRefreshTimerRef.current !== null) {
|
|
65354
65456
|
window.clearTimeout(realtimeRefreshTimerRef.current);
|
|
@@ -65373,9 +65475,9 @@ var useLiveMonitorBootstrap = ({
|
|
|
65373
65475
|
}
|
|
65374
65476
|
pendingRealtimeRefreshRef.current = false;
|
|
65375
65477
|
lastRealtimeRefreshStartedAtRef.current = Date.now();
|
|
65376
|
-
|
|
65478
|
+
requestScheduledForcedRefresh();
|
|
65377
65479
|
}, nextDelay);
|
|
65378
|
-
}, [enabled, supabase]);
|
|
65480
|
+
}, [enabled, requestScheduledForcedRefresh, supabase]);
|
|
65379
65481
|
const queueRealtimeRefresh = useCallback(() => {
|
|
65380
65482
|
if (!enabled || !supabase) {
|
|
65381
65483
|
pendingRealtimeRefreshRef.current = false;
|
|
@@ -65388,9 +65490,15 @@ var useLiveMonitorBootstrap = ({
|
|
|
65388
65490
|
useEffect(() => {
|
|
65389
65491
|
return () => {
|
|
65390
65492
|
pendingRealtimeRefreshRef.current = false;
|
|
65493
|
+
pendingForcedRefreshRef.current = false;
|
|
65391
65494
|
clearRealtimeRefreshTimer();
|
|
65392
65495
|
};
|
|
65393
65496
|
}, [clearRealtimeRefreshTimer]);
|
|
65497
|
+
useEffect(() => {
|
|
65498
|
+
if (!isLoading && pendingForcedRefreshRef.current) {
|
|
65499
|
+
requestScheduledForcedRefresh();
|
|
65500
|
+
}
|
|
65501
|
+
}, [isLoading, requestScheduledForcedRefresh]);
|
|
65394
65502
|
useEffect(() => {
|
|
65395
65503
|
if (!enabled || !rawState || !resolvedCompanyId) {
|
|
65396
65504
|
return;
|
|
@@ -65529,9 +65637,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65529
65637
|
if (!enabled || !resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
65530
65638
|
return void 0;
|
|
65531
65639
|
}
|
|
65532
|
-
const forceRefreshOnResume = () =>
|
|
65533
|
-
void fetchBootstrapRef.current(true);
|
|
65534
|
-
};
|
|
65640
|
+
const forceRefreshOnResume = () => requestScheduledForcedRefresh();
|
|
65535
65641
|
const handleVisibilityChange = () => {
|
|
65536
65642
|
if (document.visibilityState === "visible") {
|
|
65537
65643
|
forceRefreshOnResume();
|
|
@@ -65545,7 +65651,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65545
65651
|
window.removeEventListener("focus", forceRefreshOnResume);
|
|
65546
65652
|
window.removeEventListener("online", forceRefreshOnResume);
|
|
65547
65653
|
};
|
|
65548
|
-
}, [enabled, normalizedLineIds.length, resolvedCompanyId, supabase]);
|
|
65654
|
+
}, [enabled, normalizedLineIds.length, requestScheduledForcedRefresh, resolvedCompanyId, supabase]);
|
|
65549
65655
|
useEffect(() => {
|
|
65550
65656
|
if (!enabled || !resolvedCompanyId || normalizedLineIds.length === 0 || !supabase) {
|
|
65551
65657
|
return void 0;
|
|
@@ -65553,7 +65659,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65553
65659
|
let intervalId = null;
|
|
65554
65660
|
let timeoutId = null;
|
|
65555
65661
|
const runMinuteTick = () => {
|
|
65556
|
-
|
|
65662
|
+
requestScheduledForcedRefresh();
|
|
65557
65663
|
};
|
|
65558
65664
|
const startInterval = () => {
|
|
65559
65665
|
runMinuteTick();
|
|
@@ -65572,7 +65678,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
65572
65678
|
window.clearInterval(intervalId);
|
|
65573
65679
|
}
|
|
65574
65680
|
};
|
|
65575
|
-
}, [enabled,
|
|
65681
|
+
}, [enabled, normalizedLineIds, requestScheduledForcedRefresh, resolvedCompanyId, supabase]);
|
|
65576
65682
|
const isCurrentScopeResolved = state.requestKey === requestKey;
|
|
65577
65683
|
return {
|
|
65578
65684
|
resolvedScope: state.resolvedScope,
|
|
@@ -71549,6 +71655,7 @@ var KPIsOverviewView = ({
|
|
|
71549
71655
|
const [viewType, setViewType] = useState("operator");
|
|
71550
71656
|
const [selectedLeaderboardDate, setSelectedLeaderboardDate] = useState("");
|
|
71551
71657
|
const [selectedLeaderboardShiftId, setSelectedLeaderboardShiftId] = useState(0);
|
|
71658
|
+
const [leaderboardDailyScopeMode, setLeaderboardDailyScopeMode] = useState("live");
|
|
71552
71659
|
const [hasHydratedLeaderboardRouteState, setHasHydratedLeaderboardRouteState] = useState(false);
|
|
71553
71660
|
const [loading, setLoading] = useState(true);
|
|
71554
71661
|
const [isFilterOpen, setIsFilterOpen] = useState(false);
|
|
@@ -71668,14 +71775,16 @@ var KPIsOverviewView = ({
|
|
|
71668
71775
|
const currentShiftId = currentShiftDetails.shiftId;
|
|
71669
71776
|
const activeFiltersCount = React146__default.useMemo(() => {
|
|
71670
71777
|
let count = 0;
|
|
71671
|
-
if (selectedLeaderboardShiftId !== currentShiftId) {
|
|
71778
|
+
if (leaderboardDailyScopeMode === "historical" && selectedLeaderboardShiftId !== currentShiftId) {
|
|
71672
71779
|
count++;
|
|
71673
71780
|
}
|
|
71674
71781
|
return count;
|
|
71675
|
-
}, [selectedLeaderboardShiftId, currentShiftId]);
|
|
71782
|
+
}, [leaderboardDailyScopeMode, selectedLeaderboardShiftId, currentShiftId]);
|
|
71676
71783
|
const clearFilters = React146__default.useCallback(() => {
|
|
71677
71784
|
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71678
|
-
|
|
71785
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
71786
|
+
setLeaderboardDailyScopeMode("live");
|
|
71787
|
+
}, [currentShiftDate, currentShiftId]);
|
|
71679
71788
|
useEffect(() => {
|
|
71680
71789
|
const handleClickOutside = (event) => {
|
|
71681
71790
|
const target = event.target;
|
|
@@ -71707,7 +71816,24 @@ var KPIsOverviewView = ({
|
|
|
71707
71816
|
}, [shiftConfig]);
|
|
71708
71817
|
const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
|
|
71709
71818
|
const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
|
|
71710
|
-
const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
|
|
71819
|
+
const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
|
|
71820
|
+
const updateLeaderboardDate = React146__default.useCallback((dateKey) => {
|
|
71821
|
+
setSelectedLeaderboardDate(dateKey);
|
|
71822
|
+
setLeaderboardDailyScopeMode(
|
|
71823
|
+
dateKey === currentShiftDate && effectiveLeaderboardShiftId === currentShiftId ? "live" : "historical"
|
|
71824
|
+
);
|
|
71825
|
+
}, [currentShiftDate, currentShiftId, effectiveLeaderboardShiftId]);
|
|
71826
|
+
const updateLeaderboardShiftId = React146__default.useCallback((shiftId) => {
|
|
71827
|
+
setSelectedLeaderboardShiftId(shiftId);
|
|
71828
|
+
setLeaderboardDailyScopeMode(
|
|
71829
|
+
effectiveLeaderboardDate === currentShiftDate && shiftId === currentShiftId ? "live" : "historical"
|
|
71830
|
+
);
|
|
71831
|
+
}, [currentShiftDate, currentShiftId, effectiveLeaderboardDate]);
|
|
71832
|
+
const returnLeaderboardToLive = React146__default.useCallback(() => {
|
|
71833
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
71834
|
+
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71835
|
+
setLeaderboardDailyScopeMode("live");
|
|
71836
|
+
}, [currentShiftDate, currentShiftId]);
|
|
71711
71837
|
const selectedFactoryIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_QUERY_PARAM]);
|
|
71712
71838
|
const selectedFactoryAreaIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_AREA_QUERY_PARAM]);
|
|
71713
71839
|
const kpiLineHierarchy = React146__default.useMemo(
|
|
@@ -71733,10 +71859,12 @@ var KPIsOverviewView = ({
|
|
|
71733
71859
|
if (hasHistoricalQuery) {
|
|
71734
71860
|
setSelectedLeaderboardDate(dateQuery);
|
|
71735
71861
|
setSelectedLeaderboardShiftId(parsedShiftQuery);
|
|
71862
|
+
setLeaderboardDailyScopeMode("historical");
|
|
71736
71863
|
setTimeRange("today");
|
|
71737
71864
|
} else {
|
|
71738
71865
|
setSelectedLeaderboardDate(currentShiftDate);
|
|
71739
71866
|
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71867
|
+
setLeaderboardDailyScopeMode("live");
|
|
71740
71868
|
}
|
|
71741
71869
|
setHasHydratedLeaderboardRouteState(true);
|
|
71742
71870
|
}, [
|
|
@@ -71759,7 +71887,8 @@ var KPIsOverviewView = ({
|
|
|
71759
71887
|
pendingTabRouteSyncRef.current = null;
|
|
71760
71888
|
}
|
|
71761
71889
|
const expectedTab = activeTab === "leaderboard" ? "leaderboard" : void 0;
|
|
71762
|
-
const
|
|
71890
|
+
const shouldPersistHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && isHistoricalLeaderboardDaily;
|
|
71891
|
+
const expectedDate = shouldPersistHistoricalLeaderboardDaily ? effectiveLeaderboardDate : void 0;
|
|
71763
71892
|
const expectedShift = expectedDate !== void 0 ? effectiveLeaderboardShiftId.toString() : void 0;
|
|
71764
71893
|
const expectedFactory = activeTab === "today" && selectedFactoryNode ? selectedFactoryNode.id : void 0;
|
|
71765
71894
|
const expectedFactoryArea = activeTab === "today" && selectedFactoryNode && selectedFactoryAreaNode ? selectedFactoryAreaNode.id : void 0;
|
|
@@ -71785,6 +71914,7 @@ var KPIsOverviewView = ({
|
|
|
71785
71914
|
router,
|
|
71786
71915
|
activeTab,
|
|
71787
71916
|
timeRange,
|
|
71917
|
+
leaderboardDailyScopeMode,
|
|
71788
71918
|
effectiveLeaderboardDate,
|
|
71789
71919
|
effectiveLeaderboardShiftId,
|
|
71790
71920
|
hasHydratedLeaderboardRouteState,
|
|
@@ -72206,7 +72336,7 @@ var KPIsOverviewView = ({
|
|
|
72206
72336
|
const currentEfficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
|
|
72207
72337
|
const currentFallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
|
|
72208
72338
|
const showLeaderboardLoader = activeTab === "leaderboard" && (leaderboardLinesLoading || isLeaderboardLoading && currentEfficiencyMap.size === 0 && (currentFallbackEfficiencyMap?.size ?? 0) === 0);
|
|
72209
|
-
const showHistoricalLeaderboardHeader = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily;
|
|
72339
|
+
const showHistoricalLeaderboardHeader = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && isHistoricalLeaderboardDaily;
|
|
72210
72340
|
const headerDateKey = activeTab === "leaderboard" && timeRange === "today" ? effectiveLeaderboardDate : monthEndDateKey;
|
|
72211
72341
|
const headerShiftId = showHistoricalLeaderboardHeader ? effectiveLeaderboardShiftId : currentShiftDetails.shiftId;
|
|
72212
72342
|
const headerShiftName = getShiftNameById(headerShiftId, configuredTimezone, shiftConfig).replace(/ Shift$/i, "");
|
|
@@ -72401,10 +72531,7 @@ var KPIsOverviewView = ({
|
|
|
72401
72531
|
"button",
|
|
72402
72532
|
{
|
|
72403
72533
|
type: "button",
|
|
72404
|
-
onClick:
|
|
72405
|
-
setSelectedLeaderboardDate(currentShiftDate);
|
|
72406
|
-
setSelectedLeaderboardShiftId(currentShiftId);
|
|
72407
|
-
},
|
|
72534
|
+
onClick: returnLeaderboardToLive,
|
|
72408
72535
|
className: "text-[10px] font-medium text-blue-600 hover:text-blue-700 hover:underline bg-blue-50 px-2 py-1 rounded-md",
|
|
72409
72536
|
children: "Return to Live"
|
|
72410
72537
|
}
|
|
@@ -72450,10 +72577,7 @@ var KPIsOverviewView = ({
|
|
|
72450
72577
|
"button",
|
|
72451
72578
|
{
|
|
72452
72579
|
type: "button",
|
|
72453
|
-
onClick:
|
|
72454
|
-
setSelectedLeaderboardDate(currentShiftDate);
|
|
72455
|
-
setSelectedLeaderboardShiftId(currentShiftId);
|
|
72456
|
-
},
|
|
72580
|
+
onClick: returnLeaderboardToLive,
|
|
72457
72581
|
className: "text-xs sm:text-sm font-medium text-blue-600 bg-blue-50 border border-blue-100 hover:bg-blue-100 hover:text-blue-700 px-3 py-1.5 rounded-lg transition-colors shadow-sm ml-4 whitespace-nowrap",
|
|
72458
72582
|
children: "Return to Live"
|
|
72459
72583
|
}
|
|
@@ -72521,7 +72645,7 @@ var KPIsOverviewView = ({
|
|
|
72521
72645
|
endKey: effectiveLeaderboardDate
|
|
72522
72646
|
},
|
|
72523
72647
|
onChange: (range) => {
|
|
72524
|
-
|
|
72648
|
+
updateLeaderboardDate(range.startKey);
|
|
72525
72649
|
},
|
|
72526
72650
|
showLabel: false,
|
|
72527
72651
|
singleDateOnly: true
|
|
@@ -72561,7 +72685,7 @@ var KPIsOverviewView = ({
|
|
|
72561
72685
|
{
|
|
72562
72686
|
"aria-label": "Leaderboard shift",
|
|
72563
72687
|
value: effectiveLeaderboardShiftId,
|
|
72564
|
-
onChange: (e) =>
|
|
72688
|
+
onChange: (e) => updateLeaderboardShiftId(Number(e.target.value)),
|
|
72565
72689
|
className: "w-full appearance-none pl-3 pr-8 py-2 text-sm bg-gray-50 border border-gray-200 hover:border-gray-300 rounded-lg text-gray-900 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:bg-white transition-all cursor-pointer",
|
|
72566
72690
|
style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.75rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
|
|
72567
72691
|
children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
|
|
@@ -72959,19 +73083,31 @@ var LeaderboardDetailView = memo$1(({
|
|
|
72959
73083
|
if (lineId2 === line2Id) return "Line 2";
|
|
72960
73084
|
return `Line ${lineId2.substring(0, 8)}`;
|
|
72961
73085
|
}, [dbLineNames, configuredLineNames, lineNames, line1Id, line2Id]);
|
|
72962
|
-
const configuredLineIds = useMemo(() => {
|
|
72963
|
-
return getConfiguredLineIds(entityConfig);
|
|
72964
|
-
}, [entityConfig]);
|
|
72965
73086
|
const accessibleLineIdSet = useMemo(
|
|
72966
73087
|
() => new Set((userAccessibleLineIds || []).filter(Boolean)),
|
|
72967
73088
|
[userAccessibleLineIds]
|
|
72968
73089
|
);
|
|
73090
|
+
const configuredLineIds = useMemo(() => {
|
|
73091
|
+
const allConfiguredLineIds = getConfiguredLineIds(entityConfig);
|
|
73092
|
+
if (!userAccessibleLineIds) {
|
|
73093
|
+
return allConfiguredLineIds;
|
|
73094
|
+
}
|
|
73095
|
+
if (accessibleLineIdSet.size === 0) {
|
|
73096
|
+
return [];
|
|
73097
|
+
}
|
|
73098
|
+
return allConfiguredLineIds.filter((lineId2) => accessibleLineIdSet.has(lineId2));
|
|
73099
|
+
}, [accessibleLineIdSet, entityConfig, userAccessibleLineIds]);
|
|
72969
73100
|
const canOpenWorkspace = useCallback((workspaceLineId) => {
|
|
72970
73101
|
if (!workspaceLineId) return false;
|
|
72971
73102
|
if (!userAccessibleLineIds) return true;
|
|
72972
73103
|
if (accessibleLineIdSet.size === 0) return false;
|
|
72973
73104
|
return accessibleLineIdSet.has(workspaceLineId);
|
|
72974
73105
|
}, [accessibleLineIdSet, userAccessibleLineIds]);
|
|
73106
|
+
useEffect(() => {
|
|
73107
|
+
if (selectedLineFilter !== "all" && !configuredLineIds.includes(selectedLineFilter)) {
|
|
73108
|
+
setSelectedLineFilter("all");
|
|
73109
|
+
}
|
|
73110
|
+
}, [configuredLineIds, selectedLineFilter]);
|
|
72975
73111
|
const { hasUptime: lineModeHasUptime, hasOutput: lineModeHasOutput } = useMemo(() => {
|
|
72976
73112
|
if (!lines || lines.length === 0) {
|
|
72977
73113
|
return { hasUptime: false, hasOutput: false };
|
|
@@ -73402,6 +73538,13 @@ var LeaderboardDetailView = memo$1(({
|
|
|
73402
73538
|
fetchMonthlyLeaderboard();
|
|
73403
73539
|
}
|
|
73404
73540
|
}, [activeTab, fetchMonthlyLeaderboard]);
|
|
73541
|
+
const retryLeaderboard = useCallback(() => {
|
|
73542
|
+
if (activeTab === "monthly") {
|
|
73543
|
+
fetchMonthlyLeaderboard();
|
|
73544
|
+
return;
|
|
73545
|
+
}
|
|
73546
|
+
fetchTodayLeaderboard();
|
|
73547
|
+
}, [activeTab, fetchMonthlyLeaderboard, fetchTodayLeaderboard]);
|
|
73405
73548
|
useEffect(() => {
|
|
73406
73549
|
if (!supabase || !entityConfig.companyId) return;
|
|
73407
73550
|
if (!realtimeEnabled) return;
|
|
@@ -73665,9 +73808,26 @@ var LeaderboardDetailView = memo$1(({
|
|
|
73665
73808
|
return /* @__PURE__ */ jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsx("div", { className: "text-xl text-gray-600", children: "Loading workspaces..." }) });
|
|
73666
73809
|
}
|
|
73667
73810
|
if (error) {
|
|
73668
|
-
return /* @__PURE__ */ jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "
|
|
73669
|
-
"
|
|
73670
|
-
|
|
73811
|
+
return /* @__PURE__ */ jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsxs("div", { className: "w-full max-w-md mx-4 rounded-lg border border-slate-200 bg-white p-6 text-center shadow-sm", children: [
|
|
73812
|
+
/* @__PURE__ */ jsx("div", { className: "mx-auto mb-4 flex h-11 w-11 items-center justify-center rounded-full bg-amber-50 text-amber-600", children: /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5", "aria-hidden": "true" }) }),
|
|
73813
|
+
/* @__PURE__ */ jsx("h2", { className: "text-base font-semibold text-slate-900", children: "Leaderboard could not be refreshed" }),
|
|
73814
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm leading-6 text-slate-600", children: "Your access may have changed or the dashboard data service may be temporarily unavailable." }),
|
|
73815
|
+
/* @__PURE__ */ jsxs(
|
|
73816
|
+
"button",
|
|
73817
|
+
{
|
|
73818
|
+
type: "button",
|
|
73819
|
+
onClick: retryLeaderboard,
|
|
73820
|
+
className: "mt-5 inline-flex items-center justify-center gap-2 rounded-md bg-slate-900 px-4 py-2 text-sm font-medium text-white transition-colors hover:bg-slate-800 focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2",
|
|
73821
|
+
children: [
|
|
73822
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "h-4 w-4", "aria-hidden": "true" }),
|
|
73823
|
+
"Retry"
|
|
73824
|
+
]
|
|
73825
|
+
}
|
|
73826
|
+
),
|
|
73827
|
+
error.code && /* @__PURE__ */ jsxs("p", { className: "mt-3 text-xs text-slate-400", children: [
|
|
73828
|
+
"Reference: ",
|
|
73829
|
+
error.code
|
|
73830
|
+
] })
|
|
73671
73831
|
] }) });
|
|
73672
73832
|
}
|
|
73673
73833
|
const hasCycleTimeLeaderboardRows = sortedWorkspaces.some(
|