@optifye/dashboard-core 6.6.11 → 6.6.13
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 +37 -13
- package/dist/index.d.mts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +387 -238
- package/dist/index.mjs +388 -240
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4044,12 +4044,8 @@ var S3ClipsSupabaseService = class {
|
|
|
4044
4044
|
id: clip.clip_id,
|
|
4045
4045
|
src: clip.playlist,
|
|
4046
4046
|
// Raw playlist content
|
|
4047
|
-
timestamp:
|
|
4048
|
-
|
|
4049
|
-
hour: "2-digit",
|
|
4050
|
-
minute: "2-digit",
|
|
4051
|
-
second: "2-digit"
|
|
4052
|
-
}),
|
|
4047
|
+
timestamp: clip.timestamp,
|
|
4048
|
+
// Use pre-formatted timestamp from API (already in 12-hour format with seconds)
|
|
4053
4049
|
severity: this.getSeverityFromClipType(clip.clip_type_name),
|
|
4054
4050
|
description: this.getDescriptionFromClipType(clip.clip_type_name),
|
|
4055
4051
|
type: clip.clip_type_name,
|
|
@@ -6545,6 +6541,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6545
6541
|
const lineIdRef = React21.useRef(lineId);
|
|
6546
6542
|
const isFetchingRef = React21.useRef(false);
|
|
6547
6543
|
const updateQueueRef = React21.useRef(false);
|
|
6544
|
+
const onLineMetricsUpdateRef = React21.useRef(onLineMetricsUpdate);
|
|
6545
|
+
React21.useEffect(() => {
|
|
6546
|
+
onLineMetricsUpdateRef.current = onLineMetricsUpdate;
|
|
6547
|
+
}, [onLineMetricsUpdate]);
|
|
6548
6548
|
const companySpecificMetricsTable = React21.useMemo(
|
|
6549
6549
|
() => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
|
|
6550
6550
|
[entityConfig.companyId]
|
|
@@ -6660,13 +6660,17 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6660
6660
|
defaultTimezone,
|
|
6661
6661
|
shiftConfig
|
|
6662
6662
|
]);
|
|
6663
|
+
const fetchAllMetricsRef = React21.useRef(fetchAllMetrics);
|
|
6664
|
+
React21.useEffect(() => {
|
|
6665
|
+
fetchAllMetricsRef.current = fetchAllMetrics;
|
|
6666
|
+
}, [fetchAllMetrics]);
|
|
6663
6667
|
const queueUpdate = React21.useCallback(() => {
|
|
6664
6668
|
if (updateQueueRef.current || !supabase) {
|
|
6665
6669
|
return;
|
|
6666
6670
|
}
|
|
6667
6671
|
updateQueueRef.current = true;
|
|
6668
|
-
|
|
6669
|
-
}, [
|
|
6672
|
+
fetchAllMetricsRef.current();
|
|
6673
|
+
}, [supabase]);
|
|
6670
6674
|
React21.useEffect(() => {
|
|
6671
6675
|
if (lineId && supabase) {
|
|
6672
6676
|
fetchAllMetrics();
|
|
@@ -6681,11 +6685,11 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6681
6685
|
const operationalDateForSubscription = getOperationalDate(defaultTimezone);
|
|
6682
6686
|
const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
|
|
6683
6687
|
if (targetLineIds.length === 0) return;
|
|
6684
|
-
const wsMetricsFilter = `
|
|
6685
|
-
const lineMetricsFilter = `
|
|
6688
|
+
const wsMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
6689
|
+
const lineMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
6686
6690
|
const channels = [];
|
|
6687
6691
|
const createSubscription = (table, filter2, channelNameBase, callback) => {
|
|
6688
|
-
const channelName = `${channelNameBase}-${
|
|
6692
|
+
const channelName = `${channelNameBase}-${Date.now()}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
6689
6693
|
const channel = supabase.channel(channelName).on(
|
|
6690
6694
|
"postgres_changes",
|
|
6691
6695
|
{ event: "*", schema, table, filter: filter2 },
|
|
@@ -6695,40 +6699,29 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6695
6699
|
callback();
|
|
6696
6700
|
}
|
|
6697
6701
|
}
|
|
6698
|
-
).subscribe(
|
|
6699
|
-
if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR && err) {
|
|
6700
|
-
console.error(`[useDashboardMetrics] Subscription error for ${table} on ${currentLineIdToUse}:`, err.message);
|
|
6701
|
-
} else if (status === supabaseJs.REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
|
|
6702
|
-
console.warn(`[useDashboardMetrics] Subscription timeout for ${table} on ${currentLineIdToUse}.`);
|
|
6703
|
-
}
|
|
6704
|
-
});
|
|
6702
|
+
).subscribe();
|
|
6705
6703
|
channels.push(channel);
|
|
6706
6704
|
};
|
|
6707
6705
|
createSubscription(companySpecificMetricsTable, wsMetricsFilter, "dashboard-ws-metrics", queueUpdate);
|
|
6708
6706
|
createSubscription(configuredLineMetricsTable, lineMetricsFilter, "dashboard-line-metrics", () => {
|
|
6709
6707
|
queueUpdate();
|
|
6710
|
-
|
|
6708
|
+
onLineMetricsUpdateRef.current?.();
|
|
6711
6709
|
});
|
|
6712
6710
|
return () => {
|
|
6713
6711
|
channels.forEach((channel) => {
|
|
6714
|
-
supabase?.removeChannel(channel)
|
|
6712
|
+
supabase?.removeChannel(channel);
|
|
6715
6713
|
});
|
|
6716
6714
|
};
|
|
6717
6715
|
}, [
|
|
6718
6716
|
supabase,
|
|
6719
|
-
// fetchAllMetrics, // fetchAllMetrics is now a dependency of queueUpdate
|
|
6720
6717
|
queueUpdate,
|
|
6721
|
-
// Section 6: Add queueUpdate as dependency
|
|
6722
6718
|
companySpecificMetricsTable,
|
|
6723
6719
|
configuredLineMetricsTable,
|
|
6724
6720
|
schema,
|
|
6725
|
-
entityConfig,
|
|
6726
|
-
|
|
6721
|
+
entityConfig?.companyId,
|
|
6722
|
+
entityConfig?.factoryViewId,
|
|
6727
6723
|
defaultTimezone,
|
|
6728
|
-
shiftConfig,
|
|
6729
|
-
onLineMetricsUpdate,
|
|
6730
6724
|
lineId
|
|
6731
|
-
// Add lineId from props to re-run effect if it changes, managed by lineIdRef inside effect
|
|
6732
6725
|
]);
|
|
6733
6726
|
return {
|
|
6734
6727
|
workspaceMetrics: metrics2?.workspaceMetrics || [],
|
|
@@ -6889,6 +6882,7 @@ var useRealtimeLineMetrics = ({
|
|
|
6889
6882
|
const updateQueueRef = React21.useRef(false);
|
|
6890
6883
|
const isFetchingRef = React21.useRef(false);
|
|
6891
6884
|
const channelsRef = React21.useRef([]);
|
|
6885
|
+
const fetchTimeoutRef = React21.useRef(null);
|
|
6892
6886
|
const currentShift = React21.useMemo(() => getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig), [dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
6893
6887
|
const shiftId = React21.useMemo(
|
|
6894
6888
|
() => urlShiftId !== void 0 ? urlShiftId : currentShift.shiftId,
|
|
@@ -7098,9 +7092,17 @@ var useRealtimeLineMetrics = ({
|
|
|
7098
7092
|
}
|
|
7099
7093
|
}, [supabase, date, shiftId, urlShiftId, onMetricsUpdate, entityConfig, dateTimeConfig.defaultTimezone]);
|
|
7100
7094
|
const queueUpdate = React21.useCallback(() => {
|
|
7101
|
-
|
|
7102
|
-
|
|
7103
|
-
|
|
7095
|
+
console.log("[useRealtimeLineMetrics] Update queued, debouncing...");
|
|
7096
|
+
if (fetchTimeoutRef.current) {
|
|
7097
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
7098
|
+
}
|
|
7099
|
+
fetchTimeoutRef.current = setTimeout(() => {
|
|
7100
|
+
if (updateQueueRef.current) return;
|
|
7101
|
+
updateQueueRef.current = true;
|
|
7102
|
+
console.log("[useRealtimeLineMetrics] Debounced fetch triggered");
|
|
7103
|
+
fetchData();
|
|
7104
|
+
fetchTimeoutRef.current = null;
|
|
7105
|
+
}, 500);
|
|
7104
7106
|
}, [fetchData]);
|
|
7105
7107
|
const setupSubscriptions = React21.useCallback(() => {
|
|
7106
7108
|
if (channelsRef.current.length > 0) {
|
|
@@ -7178,6 +7180,10 @@ var useRealtimeLineMetrics = ({
|
|
|
7178
7180
|
}
|
|
7179
7181
|
setupSubscriptions();
|
|
7180
7182
|
return () => {
|
|
7183
|
+
if (fetchTimeoutRef.current) {
|
|
7184
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
7185
|
+
fetchTimeoutRef.current = null;
|
|
7186
|
+
}
|
|
7181
7187
|
if (channelsRef.current.length > 0) {
|
|
7182
7188
|
channelsRef.current.forEach((channel) => {
|
|
7183
7189
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -8124,13 +8130,10 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
8124
8130
|
}
|
|
8125
8131
|
}
|
|
8126
8132
|
if (displayName) {
|
|
8127
|
-
console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${displayName} (from Supabase)`);
|
|
8128
8133
|
return displayName;
|
|
8129
8134
|
} else {
|
|
8130
8135
|
if (isInitialized) {
|
|
8131
|
-
console.
|
|
8132
|
-
} else {
|
|
8133
|
-
console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (Supabase not initialized yet)`);
|
|
8136
|
+
console.warn(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
|
|
8134
8137
|
}
|
|
8135
8138
|
return workspaceId;
|
|
8136
8139
|
}
|
|
@@ -8167,13 +8170,10 @@ var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
8167
8170
|
}
|
|
8168
8171
|
}
|
|
8169
8172
|
if (displayName) {
|
|
8170
|
-
console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${displayName} (from Supabase)`);
|
|
8171
8173
|
return displayName;
|
|
8172
8174
|
} else {
|
|
8173
8175
|
if (isInitialized) {
|
|
8174
|
-
console.
|
|
8175
|
-
} else {
|
|
8176
|
-
console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (Supabase not initialized yet)`);
|
|
8176
|
+
console.warn(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
|
|
8177
8177
|
}
|
|
8178
8178
|
return workspaceId;
|
|
8179
8179
|
}
|
|
@@ -8479,6 +8479,8 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8479
8479
|
const [loading, setLoading] = React21.useState(true);
|
|
8480
8480
|
const [error, setError] = React21.useState(null);
|
|
8481
8481
|
const [initialized, setInitialized] = React21.useState(false);
|
|
8482
|
+
const fetchTimeoutRef = React21.useRef(null);
|
|
8483
|
+
const isFetchingRef = React21.useRef(false);
|
|
8482
8484
|
const queryShiftId = React21.useMemo(() => {
|
|
8483
8485
|
const currentShift = getCurrentShift(
|
|
8484
8486
|
dateTimeConfig.defaultTimezone || "Asia/Kolkata",
|
|
@@ -8497,16 +8499,15 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8497
8499
|
}, [entityConfig.companyId]);
|
|
8498
8500
|
const schema = databaseConfig.schema ?? "public";
|
|
8499
8501
|
const fetchWorkspaceMetrics = React21.useCallback(async () => {
|
|
8502
|
+
if (isFetchingRef.current) {
|
|
8503
|
+
return;
|
|
8504
|
+
}
|
|
8505
|
+
isFetchingRef.current = true;
|
|
8500
8506
|
if (!initialized) {
|
|
8501
8507
|
setLoading(true);
|
|
8502
8508
|
}
|
|
8503
8509
|
setError(null);
|
|
8504
8510
|
try {
|
|
8505
|
-
console.log("Fetching all workspace metrics with params:", {
|
|
8506
|
-
queryDate,
|
|
8507
|
-
queryShiftId,
|
|
8508
|
-
metricsTable
|
|
8509
|
-
});
|
|
8510
8511
|
const configuredLineIds = getConfiguredLineIds(entityConfig);
|
|
8511
8512
|
let enabledWorkspaceIds = [];
|
|
8512
8513
|
for (const lineId of configuredLineIds) {
|
|
@@ -8549,13 +8550,26 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8549
8550
|
efficiency: item.efficiency || 0,
|
|
8550
8551
|
action_threshold: item.total_day_output || 0
|
|
8551
8552
|
}));
|
|
8552
|
-
setWorkspaces(
|
|
8553
|
+
setWorkspaces((prevWorkspaces) => {
|
|
8554
|
+
if (prevWorkspaces.length !== transformedData.length) {
|
|
8555
|
+
return transformedData;
|
|
8556
|
+
}
|
|
8557
|
+
const hasChanges = transformedData.some((newWs) => {
|
|
8558
|
+
const prevWs = prevWorkspaces.find((w) => w.workspace_uuid === newWs.workspace_uuid);
|
|
8559
|
+
if (!prevWs) {
|
|
8560
|
+
return true;
|
|
8561
|
+
}
|
|
8562
|
+
return prevWs.efficiency !== newWs.efficiency || prevWs.action_count !== newWs.action_count || prevWs.action_threshold !== newWs.action_threshold || prevWs.avg_cycle_time !== newWs.avg_cycle_time || prevWs.workspace_name !== newWs.workspace_name;
|
|
8563
|
+
});
|
|
8564
|
+
return hasChanges ? transformedData : prevWorkspaces;
|
|
8565
|
+
});
|
|
8553
8566
|
setInitialized(true);
|
|
8554
8567
|
} catch (err) {
|
|
8555
|
-
console.error("Error
|
|
8568
|
+
console.error("[useAllWorkspaceMetrics] Error:", err.message);
|
|
8556
8569
|
setError({ message: err.message, code: err.code || "FETCH_ERROR" });
|
|
8557
8570
|
} finally {
|
|
8558
8571
|
setLoading(false);
|
|
8572
|
+
isFetchingRef.current = false;
|
|
8559
8573
|
}
|
|
8560
8574
|
}, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId]);
|
|
8561
8575
|
React21.useEffect(() => {
|
|
@@ -8563,25 +8577,37 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8563
8577
|
fetchWorkspaceMetrics();
|
|
8564
8578
|
}
|
|
8565
8579
|
const setupSubscription = () => {
|
|
8566
|
-
const filter2 = `date=eq.${queryDate} AND shift_id=eq.${queryShiftId}`;
|
|
8567
|
-
console.log("Setting up subscription for all workspaces with filter:", filter2);
|
|
8568
8580
|
const channel2 = supabase.channel(`all-workspace-metrics-${Date.now()}`).on(
|
|
8569
8581
|
"postgres_changes",
|
|
8570
8582
|
{
|
|
8571
8583
|
event: "*",
|
|
8572
8584
|
schema,
|
|
8573
|
-
table: metricsTable
|
|
8574
|
-
filter: filter2
|
|
8585
|
+
table: metricsTable
|
|
8575
8586
|
},
|
|
8576
8587
|
async (payload) => {
|
|
8577
|
-
|
|
8578
|
-
|
|
8588
|
+
const data = payload.new || payload.old;
|
|
8589
|
+
if (data?.date !== queryDate || data?.shift_id !== queryShiftId) {
|
|
8590
|
+
return;
|
|
8591
|
+
}
|
|
8592
|
+
if (fetchTimeoutRef.current) {
|
|
8593
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
8594
|
+
}
|
|
8595
|
+
fetchTimeoutRef.current = setTimeout(async () => {
|
|
8596
|
+
if (!isFetchingRef.current) {
|
|
8597
|
+
await fetchWorkspaceMetrics();
|
|
8598
|
+
}
|
|
8599
|
+
fetchTimeoutRef.current = null;
|
|
8600
|
+
}, 300);
|
|
8579
8601
|
}
|
|
8580
8602
|
).subscribe();
|
|
8581
8603
|
return channel2;
|
|
8582
8604
|
};
|
|
8583
8605
|
const channel = setupSubscription();
|
|
8584
8606
|
return () => {
|
|
8607
|
+
if (fetchTimeoutRef.current) {
|
|
8608
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
8609
|
+
fetchTimeoutRef.current = null;
|
|
8610
|
+
}
|
|
8585
8611
|
if (channel) {
|
|
8586
8612
|
supabase.removeChannel(channel);
|
|
8587
8613
|
}
|
|
@@ -21983,7 +22009,16 @@ var VideoCard = React21__namespace.default.memo(({
|
|
|
21983
22009
|
}
|
|
21984
22010
|
);
|
|
21985
22011
|
}, (prevProps, nextProps) => {
|
|
21986
|
-
|
|
22012
|
+
if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
|
|
22013
|
+
return false;
|
|
22014
|
+
}
|
|
22015
|
+
if (prevProps.hlsUrl !== nextProps.hlsUrl || prevProps.shouldPlay !== nextProps.shouldPlay) {
|
|
22016
|
+
return false;
|
|
22017
|
+
}
|
|
22018
|
+
if (prevProps.cropping?.x !== nextProps.cropping?.x || prevProps.cropping?.y !== nextProps.cropping?.y || prevProps.cropping?.width !== nextProps.cropping?.width || prevProps.cropping?.height !== nextProps.cropping?.height) {
|
|
22019
|
+
return false;
|
|
22020
|
+
}
|
|
22021
|
+
return true;
|
|
21987
22022
|
});
|
|
21988
22023
|
VideoCard.displayName = "VideoCard";
|
|
21989
22024
|
var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
|
|
@@ -22991,7 +23026,8 @@ var BreakNotificationPopup = ({
|
|
|
22991
23026
|
onDismiss,
|
|
22992
23027
|
isVisible = true,
|
|
22993
23028
|
className = "",
|
|
22994
|
-
lineNames = {}
|
|
23029
|
+
lineNames = {},
|
|
23030
|
+
axelImagePath = "/axel-profile.png"
|
|
22995
23031
|
}) => {
|
|
22996
23032
|
const [isDismissed, setIsDismissed] = React21.useState(false);
|
|
22997
23033
|
const [currentTime, setCurrentTime] = React21.useState(/* @__PURE__ */ new Date());
|
|
@@ -23016,6 +23052,109 @@ var BreakNotificationPopup = ({
|
|
|
23016
23052
|
if (!isVisible || isDismissed || activeBreaks.length === 0) {
|
|
23017
23053
|
return null;
|
|
23018
23054
|
}
|
|
23055
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: activeBreaks.map((breakItem, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23056
|
+
motion.div,
|
|
23057
|
+
{
|
|
23058
|
+
initial: { opacity: 0, x: 100, y: -20 },
|
|
23059
|
+
animate: { opacity: 1, x: 0, y: 0 },
|
|
23060
|
+
exit: { opacity: 0, x: 100, y: -20 },
|
|
23061
|
+
transition: { duration: 0.3, ease: "easeOut", delay: index * 0.1 },
|
|
23062
|
+
className: `fixed right-4 z-50 max-w-xs w-full ${className}`,
|
|
23063
|
+
style: { top: `${6 + index * 12}rem` },
|
|
23064
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
|
|
23065
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
|
|
23066
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23067
|
+
"img",
|
|
23068
|
+
{
|
|
23069
|
+
src: axelImagePath,
|
|
23070
|
+
alt: "Axel AI",
|
|
23071
|
+
className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
|
|
23072
|
+
onError: (e) => {
|
|
23073
|
+
const target = e.currentTarget;
|
|
23074
|
+
target.style.display = "none";
|
|
23075
|
+
const fallback = document.createElement("div");
|
|
23076
|
+
fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
|
|
23077
|
+
fallback.textContent = "A";
|
|
23078
|
+
target.parentElement?.appendChild(fallback);
|
|
23079
|
+
}
|
|
23080
|
+
}
|
|
23081
|
+
) }),
|
|
23082
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
23083
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
|
|
23084
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "font-semibold text-sm text-gray-900", children: [
|
|
23085
|
+
breakItem.remarks || "Break",
|
|
23086
|
+
(activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-500 ml-1", children: [
|
|
23087
|
+
"\u2022 ",
|
|
23088
|
+
lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}`
|
|
23089
|
+
] })
|
|
23090
|
+
] }),
|
|
23091
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Coffee, { className: "w-4 h-4 text-amber-500" })
|
|
23092
|
+
] }),
|
|
23093
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-600 leading-relaxed mb-2", children: [
|
|
23094
|
+
"Currently active from ",
|
|
23095
|
+
breakItem.startTime,
|
|
23096
|
+
" to ",
|
|
23097
|
+
breakItem.endTime,
|
|
23098
|
+
". ",
|
|
23099
|
+
formatTime3(breakItem.elapsedMinutes),
|
|
23100
|
+
" elapsed of ",
|
|
23101
|
+
formatTime3(breakItem.duration),
|
|
23102
|
+
" total."
|
|
23103
|
+
] }),
|
|
23104
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23105
|
+
"div",
|
|
23106
|
+
{
|
|
23107
|
+
className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
|
|
23108
|
+
style: {
|
|
23109
|
+
width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
|
|
23110
|
+
}
|
|
23111
|
+
}
|
|
23112
|
+
) }) })
|
|
23113
|
+
] })
|
|
23114
|
+
] }),
|
|
23115
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23116
|
+
"button",
|
|
23117
|
+
{
|
|
23118
|
+
onClick: handleDismiss,
|
|
23119
|
+
onTouchStart: () => {
|
|
23120
|
+
},
|
|
23121
|
+
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center flex-shrink-0",
|
|
23122
|
+
"aria-label": "Dismiss notification",
|
|
23123
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 sm:w-3 sm:h-3" })
|
|
23124
|
+
}
|
|
23125
|
+
)
|
|
23126
|
+
] }) }) })
|
|
23127
|
+
},
|
|
23128
|
+
`${breakItem.lineId}-${breakItem.startTime}-${index}`
|
|
23129
|
+
)) });
|
|
23130
|
+
};
|
|
23131
|
+
var AxelNotificationPopup = ({
|
|
23132
|
+
suggestion,
|
|
23133
|
+
isVisible = true,
|
|
23134
|
+
onDismiss,
|
|
23135
|
+
className = "",
|
|
23136
|
+
axelImagePath = "/axel-profile.png"
|
|
23137
|
+
}) => {
|
|
23138
|
+
const [isDismissed, setIsDismissed] = React21.useState(false);
|
|
23139
|
+
const handleDismiss = () => {
|
|
23140
|
+
setIsDismissed(true);
|
|
23141
|
+
onDismiss?.();
|
|
23142
|
+
};
|
|
23143
|
+
if (!isVisible || isDismissed || !suggestion) {
|
|
23144
|
+
return null;
|
|
23145
|
+
}
|
|
23146
|
+
const getTypeIcon = () => {
|
|
23147
|
+
switch (suggestion.type) {
|
|
23148
|
+
case "improvement":
|
|
23149
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { className: "w-4 h-4 text-blue-500" });
|
|
23150
|
+
case "alert":
|
|
23151
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "w-4 h-4 text-amber-500" });
|
|
23152
|
+
case "insight":
|
|
23153
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-4 h-4 text-purple-500" });
|
|
23154
|
+
default:
|
|
23155
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { className: "w-4 h-4 text-blue-500" });
|
|
23156
|
+
}
|
|
23157
|
+
};
|
|
23019
23158
|
return /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23020
23159
|
motion.div,
|
|
23021
23160
|
{
|
|
@@ -23023,58 +23162,54 @@ var BreakNotificationPopup = ({
|
|
|
23023
23162
|
animate: { opacity: 1, x: 0, y: 0 },
|
|
23024
23163
|
exit: { opacity: 0, x: 100, y: -20 },
|
|
23025
23164
|
transition: { duration: 0.3, ease: "easeOut" },
|
|
23026
|
-
className: `fixed top-24 right-4 z-
|
|
23027
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children:
|
|
23165
|
+
className: `fixed top-24 right-4 z-40 max-w-xs w-full ${className}`,
|
|
23166
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23028
23167
|
motion.div,
|
|
23029
23168
|
{
|
|
23030
|
-
initial: { opacity: 0, y:
|
|
23169
|
+
initial: { opacity: 0, y: 10 },
|
|
23031
23170
|
animate: { opacity: 1, y: 0 },
|
|
23032
|
-
transition: { delay:
|
|
23033
|
-
className:
|
|
23171
|
+
transition: { delay: 0.1 },
|
|
23172
|
+
className: "p-3",
|
|
23034
23173
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between", children: [
|
|
23035
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
23036
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
23174
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
|
|
23175
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23176
|
+
"img",
|
|
23177
|
+
{
|
|
23178
|
+
src: axelImagePath,
|
|
23179
|
+
alt: "Axel AI",
|
|
23180
|
+
className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
|
|
23181
|
+
onError: (e) => {
|
|
23182
|
+
const target = e.currentTarget;
|
|
23183
|
+
target.style.display = "none";
|
|
23184
|
+
const fallback = document.createElement("div");
|
|
23185
|
+
fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
|
|
23186
|
+
fallback.textContent = "A";
|
|
23187
|
+
target.parentElement?.appendChild(fallback);
|
|
23188
|
+
}
|
|
23189
|
+
}
|
|
23190
|
+
) }),
|
|
23037
23191
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
23038
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-1", children: [
|
|
23039
|
-
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-
|
|
23040
|
-
|
|
23192
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
|
|
23193
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-sm text-gray-900", children: suggestion.title }),
|
|
23194
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: getTypeIcon() })
|
|
23041
23195
|
] }),
|
|
23042
|
-
/* @__PURE__ */ jsxRuntime.jsx("
|
|
23043
|
-
breakItem.startTime,
|
|
23044
|
-
" - ",
|
|
23045
|
-
breakItem.endTime
|
|
23046
|
-
] }) }),
|
|
23047
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm sm:text-xs text-gray-500", children: [
|
|
23048
|
-
formatTime3(breakItem.elapsedMinutes),
|
|
23049
|
-
" / ",
|
|
23050
|
-
formatTime3(breakItem.duration)
|
|
23051
|
-
] }) }),
|
|
23052
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
23053
|
-
"div",
|
|
23054
|
-
{
|
|
23055
|
-
className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
|
|
23056
|
-
style: {
|
|
23057
|
-
width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
|
|
23058
|
-
}
|
|
23059
|
-
}
|
|
23060
|
-
) }) })
|
|
23196
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-600 leading-relaxed", children: suggestion.message })
|
|
23061
23197
|
] })
|
|
23062
23198
|
] }),
|
|
23063
|
-
|
|
23199
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23064
23200
|
"button",
|
|
23065
23201
|
{
|
|
23066
23202
|
onClick: handleDismiss,
|
|
23067
23203
|
onTouchStart: () => {
|
|
23068
23204
|
},
|
|
23069
|
-
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center",
|
|
23205
|
+
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center flex-shrink-0",
|
|
23070
23206
|
"aria-label": "Dismiss notification",
|
|
23071
23207
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "w-4 h-4 sm:w-3 sm:h-3" })
|
|
23072
23208
|
}
|
|
23073
23209
|
)
|
|
23074
23210
|
] })
|
|
23075
|
-
}
|
|
23076
|
-
|
|
23077
|
-
)) })
|
|
23211
|
+
}
|
|
23212
|
+
) })
|
|
23078
23213
|
}
|
|
23079
23214
|
) });
|
|
23080
23215
|
};
|
|
@@ -25905,12 +26040,6 @@ var WorkspaceHistoryCalendar = ({
|
|
|
25905
26040
|
] })
|
|
25906
26041
|
] });
|
|
25907
26042
|
};
|
|
25908
|
-
|
|
25909
|
-
// src/lib/constants/design-tokens.ts
|
|
25910
|
-
var designTokens = {
|
|
25911
|
-
// Typography scale with clear hierarchy
|
|
25912
|
-
typography: {
|
|
25913
|
-
body: "text-sm text-gray-600"}};
|
|
25914
26043
|
var WEEKDAYS3 = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
25915
26044
|
var getOrdinal = (n) => {
|
|
25916
26045
|
const suffix = ["th", "st", "nd", "rd"];
|
|
@@ -26094,10 +26223,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26094
26223
|
}
|
|
26095
26224
|
}, [workspaceId, onShiftChange]);
|
|
26096
26225
|
if (monthlyDataLoading) {
|
|
26097
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */ jsxRuntime.
|
|
26098
|
-
|
|
26099
|
-
|
|
26100
|
-
|
|
26226
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
26227
|
+
OptifyeLogoLoader_default,
|
|
26228
|
+
{
|
|
26229
|
+
size: "lg",
|
|
26230
|
+
message: "Loading monthly performance data..."
|
|
26231
|
+
}
|
|
26232
|
+
) });
|
|
26101
26233
|
}
|
|
26102
26234
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col gap-2 min-h-0 overflow-y-auto pb-6 ${className}`, children: [
|
|
26103
26235
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: [
|
|
@@ -26534,7 +26666,7 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
|
|
|
26534
26666
|
doc.roundedRect(22, y - 7, 165, 12, 2, 2, "S");
|
|
26535
26667
|
};
|
|
26536
26668
|
doc.setFillColor(245, 245, 245);
|
|
26537
|
-
doc.roundedRect(15, 95, 180,
|
|
26669
|
+
doc.roundedRect(15, 95, 180, 60, 3, 3, "F");
|
|
26538
26670
|
doc.setFontSize(18);
|
|
26539
26671
|
doc.setFont("helvetica", "bold");
|
|
26540
26672
|
doc.setTextColor(40, 40, 40);
|
|
@@ -26563,34 +26695,29 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
|
|
|
26563
26695
|
doc.text("PPH (Pieces Per Hour):", 25, kpiStartY + kpiSpacing * 3);
|
|
26564
26696
|
doc.setFont("helvetica", "bold");
|
|
26565
26697
|
doc.text(`${workspace.avg_pph.toFixed(1)} (Standard: ${workspace.pph_threshold.toFixed(1)})`, 120, kpiStartY + kpiSpacing * 3);
|
|
26566
|
-
createKPIBox(kpiStartY + kpiSpacing * 4);
|
|
26567
|
-
doc.setFont("helvetica", "normal");
|
|
26568
|
-
doc.text("Rank:", 25, kpiStartY + kpiSpacing * 4);
|
|
26569
|
-
doc.setFont("helvetica", "bold");
|
|
26570
|
-
doc.text(`${workspace.workspace_rank} of ${workspace.total_workspaces}`, 120, kpiStartY + kpiSpacing * 4);
|
|
26571
26698
|
doc.setDrawColor(180, 180, 180);
|
|
26572
26699
|
doc.setLineWidth(0.8);
|
|
26573
|
-
doc.line(20,
|
|
26700
|
+
doc.line(20, 170, 190, 170);
|
|
26574
26701
|
doc.setFillColor(245, 245, 245);
|
|
26575
|
-
doc.roundedRect(15,
|
|
26702
|
+
doc.roundedRect(15, 175, 180, 85, 3, 3, "F");
|
|
26576
26703
|
doc.setFontSize(18);
|
|
26577
26704
|
doc.setFont("helvetica", "bold");
|
|
26578
26705
|
doc.setTextColor(40, 40, 40);
|
|
26579
|
-
doc.text("Hourly Performance", 20,
|
|
26706
|
+
doc.text("Hourly Performance", 20, 185);
|
|
26580
26707
|
doc.setTextColor(0, 0, 0);
|
|
26581
26708
|
doc.setFontSize(11);
|
|
26582
26709
|
doc.setFont("helvetica", "bold");
|
|
26583
26710
|
doc.setFillColor(245, 245, 245);
|
|
26584
|
-
doc.roundedRect(20,
|
|
26585
|
-
doc.text("Time Range", 25,
|
|
26586
|
-
doc.text("Output", 95,
|
|
26587
|
-
doc.text("Target", 135,
|
|
26588
|
-
doc.text("Status", 170,
|
|
26711
|
+
doc.roundedRect(20, 177, 170, 8, 1, 1, "F");
|
|
26712
|
+
doc.text("Time Range", 25, 182);
|
|
26713
|
+
doc.text("Output", 95, 182);
|
|
26714
|
+
doc.text("Target", 135, 182);
|
|
26715
|
+
doc.text("Status", 170, 182);
|
|
26589
26716
|
doc.setLineWidth(0.2);
|
|
26590
26717
|
doc.setDrawColor(220, 220, 220);
|
|
26591
|
-
doc.line(20,
|
|
26718
|
+
doc.line(20, 185, 190, 185);
|
|
26592
26719
|
doc.setFont("helvetica", "normal");
|
|
26593
|
-
let yPos =
|
|
26720
|
+
let yPos = 191;
|
|
26594
26721
|
const hourlyData = workspace.hourly_action_counts || [];
|
|
26595
26722
|
const hourlyTarget = workspace.pph_threshold;
|
|
26596
26723
|
hourlyData.forEach((output, index) => {
|
|
@@ -28384,7 +28511,10 @@ var FilterDialogTrigger = ({
|
|
|
28384
28511
|
}
|
|
28385
28512
|
);
|
|
28386
28513
|
};
|
|
28387
|
-
var getSeverityIcon = (severity) => {
|
|
28514
|
+
var getSeverityIcon = (severity, categoryId) => {
|
|
28515
|
+
if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
|
|
28516
|
+
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3 w-3 text-red-500" });
|
|
28517
|
+
}
|
|
28388
28518
|
switch (severity) {
|
|
28389
28519
|
case "high":
|
|
28390
28520
|
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3 w-3 text-red-500" });
|
|
@@ -28611,17 +28741,17 @@ var FileManagerFilters = ({
|
|
|
28611
28741
|
const colorClasses = getColorClasses(category.color);
|
|
28612
28742
|
const clipNodes = filteredClips.map((clip, index) => {
|
|
28613
28743
|
const timeString = new Date(clip.clip_timestamp).toLocaleTimeString("en-US", {
|
|
28614
|
-
hour12:
|
|
28615
|
-
hour: "
|
|
28744
|
+
hour12: true,
|
|
28745
|
+
hour: "numeric",
|
|
28616
28746
|
minute: "2-digit",
|
|
28617
28747
|
timeZone: timezone
|
|
28618
28748
|
// Use database timezone for display
|
|
28619
28749
|
});
|
|
28620
28750
|
return {
|
|
28621
28751
|
id: clip.id,
|
|
28622
|
-
label: `${timeString}
|
|
28752
|
+
label: `${timeString}${clip.duration && category.id !== "idle_time" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`,
|
|
28623
28753
|
type: "video",
|
|
28624
|
-
icon: getSeverityIcon(clip.severity),
|
|
28754
|
+
icon: getSeverityIcon(clip.severity, category.id),
|
|
28625
28755
|
timestamp: clip.clip_timestamp,
|
|
28626
28756
|
severity: clip.severity,
|
|
28627
28757
|
clipId: clip.clipId,
|
|
@@ -28661,9 +28791,9 @@ var FileManagerFilters = ({
|
|
|
28661
28791
|
children: (percentileClips["fast-cycles"] || []).map((clip, index) => ({
|
|
28662
28792
|
id: clip.id,
|
|
28663
28793
|
// Remove prefix to match currentVideoId
|
|
28664
|
-
label: `${clip.timestamp}
|
|
28794
|
+
label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
28665
28795
|
type: "video",
|
|
28666
|
-
icon: getSeverityIcon(clip.severity),
|
|
28796
|
+
icon: getSeverityIcon(clip.severity, "fast-cycles"),
|
|
28667
28797
|
timestamp: clip.creation_timestamp,
|
|
28668
28798
|
severity: clip.severity,
|
|
28669
28799
|
clipId: clip.id,
|
|
@@ -28684,9 +28814,9 @@ var FileManagerFilters = ({
|
|
|
28684
28814
|
children: (percentileClips["slow-cycles"] || []).map((clip, index) => ({
|
|
28685
28815
|
id: clip.id,
|
|
28686
28816
|
// Remove prefix to match currentVideoId
|
|
28687
|
-
label: `${clip.timestamp}
|
|
28817
|
+
label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
28688
28818
|
type: "video",
|
|
28689
|
-
icon: getSeverityIcon(clip.severity),
|
|
28819
|
+
icon: getSeverityIcon(clip.severity, "slow-cycles"),
|
|
28690
28820
|
timestamp: clip.creation_timestamp,
|
|
28691
28821
|
severity: clip.severity,
|
|
28692
28822
|
clipId: clip.id,
|
|
@@ -28707,9 +28837,9 @@ var FileManagerFilters = ({
|
|
|
28707
28837
|
isPercentile: true,
|
|
28708
28838
|
children: (percentileClips['idle-times'] || []).map((clip, index) => ({
|
|
28709
28839
|
id: clip.id, // Remove prefix to match currentVideoId
|
|
28710
|
-
label: `${clip.timestamp}
|
|
28840
|
+
label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ''}`,
|
|
28711
28841
|
type: 'video' as const,
|
|
28712
|
-
icon: getSeverityIcon(clip.severity),
|
|
28842
|
+
icon: getSeverityIcon(clip.severity, 'longest-idles'),
|
|
28713
28843
|
timestamp: clip.creation_timestamp,
|
|
28714
28844
|
severity: clip.severity,
|
|
28715
28845
|
clipId: clip.id,
|
|
@@ -28764,7 +28894,7 @@ var FileManagerFilters = ({
|
|
|
28764
28894
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
28765
28895
|
"div",
|
|
28766
28896
|
{
|
|
28767
|
-
className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-
|
|
28897
|
+
className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-blue-50 to-blue-50/60 border border-blue-200/50 shadow-md shadow-blue-100/20" : ""}`} ${node.type === "video" ? "ml-6" : ""}`,
|
|
28768
28898
|
onClick: () => handleNodeClick(node),
|
|
28769
28899
|
children: [
|
|
28770
28900
|
hasChildren && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -28781,13 +28911,10 @@ var FileManagerFilters = ({
|
|
|
28781
28911
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 mr-3 ${node.type === "category" || node.type === "percentile-category" ? "p-2 rounded-lg shadow-sm group-hover:scale-110 transition-transform duration-200" : "p-0.5"} ${colorClasses && (node.type === "category" || node.type === "percentile-category") ? `${colorClasses.bg} border border-white/60` : ""}`, children: node.icon }),
|
|
28782
28912
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
|
|
28783
28913
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
28784
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-
|
|
28914
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-blue-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
|
|
28785
28915
|
node.type === "category" && categories.find((c) => c.id === node.id)?.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: categories.find((c) => c.id === node.id)?.description }),
|
|
28786
28916
|
node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
|
|
28787
|
-
node.type === "video" && node.severity && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */ jsxRuntime.
|
|
28788
|
-
node.severity,
|
|
28789
|
-
" priority"
|
|
28790
|
-
] }) })
|
|
28917
|
+
node.type === "video" && node.severity && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${node.categoryId === "idle_time" || node.categoryId === "low_value" ? "bg-red-100 text-red-700" : node.severity === "high" ? "bg-red-100 text-red-700" : node.severity === "medium" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"}`, children: node.categoryId === "idle_time" || node.categoryId === "low_value" ? "Idle" : node.severity === "low" ? "Fast" : node.severity === "medium" ? "Average" : "Slow" }) })
|
|
28791
28918
|
] }),
|
|
28792
28919
|
node.count !== void 0 && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children: node.count }) })
|
|
28793
28920
|
] })
|
|
@@ -37028,6 +37155,8 @@ function HomeView({
|
|
|
37028
37155
|
const [errorMessage, setErrorMessage] = React21.useState(null);
|
|
37029
37156
|
const [displayNamesInitialized, setDisplayNamesInitialized] = React21.useState(false);
|
|
37030
37157
|
const [hasInitialDataLoaded, setHasInitialDataLoaded] = React21.useState(false);
|
|
37158
|
+
const [axelSuggestion, setAxelSuggestion] = React21.useState(null);
|
|
37159
|
+
const [showAxelNotification, setShowAxelNotification] = React21.useState(false);
|
|
37031
37160
|
const dashboardConfig = useDashboardConfig();
|
|
37032
37161
|
const timezone = useAppTimezone();
|
|
37033
37162
|
React21.useEffect(() => {
|
|
@@ -37102,12 +37231,7 @@ function HomeView({
|
|
|
37102
37231
|
}, []);
|
|
37103
37232
|
const handleWorkspaceHoverEnd = React21.useCallback((workspaceId) => {
|
|
37104
37233
|
}, []);
|
|
37105
|
-
const memoizedWorkspaceMetrics =
|
|
37106
|
-
// Only update reference if meaningful properties change
|
|
37107
|
-
workspaceMetrics.length,
|
|
37108
|
-
// Use stable string representation instead of spreading array
|
|
37109
|
-
JSON.stringify(workspaceMetrics.map((w) => `${w.workspace_uuid}-${Math.round(w.efficiency)}-${w.trend}`))
|
|
37110
|
-
]);
|
|
37234
|
+
const memoizedWorkspaceMetrics = workspaceMetrics;
|
|
37111
37235
|
const memoizedKPIs = React21.useMemo(() => kpis, [
|
|
37112
37236
|
// Only update reference when values change by at least 1%
|
|
37113
37237
|
kpis?.efficiency?.value ? Math.round(kpis.efficiency.value) : null,
|
|
@@ -37135,6 +37259,9 @@ function HomeView({
|
|
|
37135
37259
|
setIsChangingFilter(true);
|
|
37136
37260
|
setSelectedLineId(value);
|
|
37137
37261
|
}, []);
|
|
37262
|
+
const handleDismissAxelNotification = React21.useCallback(() => {
|
|
37263
|
+
setShowAxelNotification(false);
|
|
37264
|
+
}, []);
|
|
37138
37265
|
React21.useEffect(() => {
|
|
37139
37266
|
if (!metricsLoading && !kpisLoading && isChangingFilter) {
|
|
37140
37267
|
if (workspaceMetrics.length > 0 || selectedLineId === factoryViewId) {
|
|
@@ -37246,6 +37373,14 @@ function HomeView({
|
|
|
37246
37373
|
lineNames,
|
|
37247
37374
|
isVisible: !breaksLoading && !breaksError
|
|
37248
37375
|
}
|
|
37376
|
+
),
|
|
37377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
37378
|
+
AxelNotificationPopup,
|
|
37379
|
+
{
|
|
37380
|
+
suggestion: axelSuggestion,
|
|
37381
|
+
isVisible: showAxelNotification,
|
|
37382
|
+
onDismiss: handleDismissAxelNotification
|
|
37383
|
+
}
|
|
37249
37384
|
)
|
|
37250
37385
|
] })
|
|
37251
37386
|
}
|
|
@@ -38679,7 +38814,7 @@ var KPIsOverviewView = ({
|
|
|
38679
38814
|
var KPIsOverviewView_default = KPIsOverviewView;
|
|
38680
38815
|
var IsolatedTimer = React21.memo(() => {
|
|
38681
38816
|
return /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {});
|
|
38682
|
-
}
|
|
38817
|
+
});
|
|
38683
38818
|
IsolatedTimer.displayName = "IsolatedTimer";
|
|
38684
38819
|
var HeaderRibbon = React21.memo(({
|
|
38685
38820
|
currentDate,
|
|
@@ -38687,42 +38822,49 @@ var HeaderRibbon = React21.memo(({
|
|
|
38687
38822
|
shiftId,
|
|
38688
38823
|
getShiftIcon,
|
|
38689
38824
|
getShiftName
|
|
38690
|
-
}) =>
|
|
38691
|
-
|
|
38692
|
-
|
|
38693
|
-
|
|
38694
|
-
|
|
38695
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children:
|
|
38825
|
+
}) => {
|
|
38826
|
+
const shiftIcon = React21.useMemo(() => getShiftIcon(shiftId), [getShiftIcon, shiftId]);
|
|
38827
|
+
const shiftName = React21.useMemo(() => getShiftName(shiftId), [getShiftName, shiftId]);
|
|
38828
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
38829
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
|
|
38830
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: currentMobileDate }) }),
|
|
38831
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
|
|
38832
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: shiftIcon }),
|
|
38833
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: shiftName })
|
|
38834
|
+
] }),
|
|
38835
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsxRuntime.jsx(IsolatedTimer, {}) }) })
|
|
38696
38836
|
] }),
|
|
38697
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
38698
|
-
|
|
38699
|
-
|
|
38700
|
-
|
|
38701
|
-
|
|
38702
|
-
|
|
38703
|
-
|
|
38704
|
-
|
|
38705
|
-
|
|
38706
|
-
|
|
38707
|
-
|
|
38708
|
-
" Shift"
|
|
38837
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
|
|
38838
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsxRuntime.jsx(IsolatedTimer, {}) }),
|
|
38839
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
|
|
38840
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: currentDate }),
|
|
38841
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-300" }),
|
|
38842
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38843
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-blue-600", children: shiftIcon }),
|
|
38844
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
|
|
38845
|
+
shiftName,
|
|
38846
|
+
" Shift"
|
|
38847
|
+
] })
|
|
38709
38848
|
] })
|
|
38710
|
-
] })
|
|
38711
|
-
] })
|
|
38712
|
-
|
|
38849
|
+
] }) })
|
|
38850
|
+
] });
|
|
38851
|
+
});
|
|
38713
38852
|
HeaderRibbon.displayName = "HeaderRibbon";
|
|
38714
38853
|
var MobileWorkspaceCard = React21.memo(({
|
|
38715
38854
|
workspace,
|
|
38716
38855
|
rank,
|
|
38717
38856
|
cardClass,
|
|
38718
38857
|
onWorkspaceClick,
|
|
38719
|
-
getMedalIcon
|
|
38720
|
-
getLineName
|
|
38858
|
+
getMedalIcon
|
|
38721
38859
|
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38722
38860
|
"div",
|
|
38723
38861
|
{
|
|
38724
38862
|
onClick: () => onWorkspaceClick(workspace, rank),
|
|
38725
|
-
className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] transition-all cursor-pointer`,
|
|
38863
|
+
className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] transition-all duration-300 cursor-pointer`,
|
|
38864
|
+
style: {
|
|
38865
|
+
willChange: "opacity, transform",
|
|
38866
|
+
animation: "fadeIn 0.3s ease-in-out"
|
|
38867
|
+
},
|
|
38726
38868
|
children: [
|
|
38727
38869
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
38728
38870
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
@@ -38734,8 +38876,8 @@ var MobileWorkspaceCard = React21.memo(({
|
|
|
38734
38876
|
getMedalIcon(rank)
|
|
38735
38877
|
] }),
|
|
38736
38878
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
38737
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-gray-900", children:
|
|
38738
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children:
|
|
38879
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-gray-900", children: workspace.displayName }),
|
|
38880
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: workspace.lineName })
|
|
38739
38881
|
] })
|
|
38740
38882
|
] }),
|
|
38741
38883
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-right", children: [
|
|
@@ -38765,27 +38907,32 @@ var MobileWorkspaceCard = React21.memo(({
|
|
|
38765
38907
|
] })
|
|
38766
38908
|
]
|
|
38767
38909
|
}
|
|
38768
|
-
))
|
|
38910
|
+
), (prevProps, nextProps) => {
|
|
38911
|
+
return prevProps.rank === nextProps.rank && prevProps.cardClass === nextProps.cardClass && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick && prevProps.getMedalIcon === nextProps.getMedalIcon;
|
|
38912
|
+
});
|
|
38769
38913
|
MobileWorkspaceCard.displayName = "MobileWorkspaceCard";
|
|
38770
38914
|
var DesktopWorkspaceRow = React21.memo(({
|
|
38771
38915
|
workspace,
|
|
38772
38916
|
index,
|
|
38773
38917
|
rowClass,
|
|
38774
38918
|
onWorkspaceClick,
|
|
38775
|
-
getMedalIcon
|
|
38776
|
-
getLineName
|
|
38919
|
+
getMedalIcon
|
|
38777
38920
|
}) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
38778
38921
|
"tr",
|
|
38779
38922
|
{
|
|
38780
38923
|
onClick: () => onWorkspaceClick(workspace, index + 1),
|
|
38781
|
-
className: `${rowClass} hover:bg-gray-50/90 transition-
|
|
38924
|
+
className: `${rowClass} hover:bg-gray-50/90 transition-all duration-300 cursor-pointer group`,
|
|
38925
|
+
style: {
|
|
38926
|
+
willChange: "opacity, background-color",
|
|
38927
|
+
animation: "fadeIn 0.3s ease-in-out"
|
|
38928
|
+
},
|
|
38782
38929
|
children: [
|
|
38783
38930
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap group-hover:font-medium", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38784
38931
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: index + 1 }),
|
|
38785
38932
|
getMedalIcon(index + 1)
|
|
38786
38933
|
] }) }),
|
|
38787
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children:
|
|
38788
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children:
|
|
38934
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.displayName }) }),
|
|
38935
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium", children: workspace.lineName }) }),
|
|
38789
38936
|
/* @__PURE__ */ jsxRuntime.jsxs("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium whitespace-nowrap", children: [
|
|
38790
38937
|
(workspace.efficiency || 0).toFixed(1),
|
|
38791
38938
|
"%"
|
|
@@ -38803,7 +38950,9 @@ var DesktopWorkspaceRow = React21.memo(({
|
|
|
38803
38950
|
] })
|
|
38804
38951
|
]
|
|
38805
38952
|
}
|
|
38806
|
-
))
|
|
38953
|
+
), (prevProps, nextProps) => {
|
|
38954
|
+
return prevProps.index === nextProps.index && prevProps.rowClass === nextProps.rowClass && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick && prevProps.getMedalIcon === nextProps.getMedalIcon;
|
|
38955
|
+
});
|
|
38807
38956
|
DesktopWorkspaceRow.displayName = "DesktopWorkspaceRow";
|
|
38808
38957
|
var LeaderboardDetailView = React21.memo(({
|
|
38809
38958
|
lineId,
|
|
@@ -38819,6 +38968,13 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
38819
38968
|
const navigation = useNavigation();
|
|
38820
38969
|
const entityConfig = useEntityConfig();
|
|
38821
38970
|
const [sortAscending, setSortAscending] = React21.useState(false);
|
|
38971
|
+
const [isMobile, setIsMobile] = React21.useState(false);
|
|
38972
|
+
React21__namespace.default.useEffect(() => {
|
|
38973
|
+
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
38974
|
+
checkMobile();
|
|
38975
|
+
window.addEventListener("resize", checkMobile);
|
|
38976
|
+
return () => window.removeEventListener("resize", checkMobile);
|
|
38977
|
+
}, []);
|
|
38822
38978
|
const configuredLineNames = React21.useMemo(() => {
|
|
38823
38979
|
return getAllLineDisplayNames(entityConfig);
|
|
38824
38980
|
}, [entityConfig]);
|
|
@@ -38836,18 +38992,10 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
38836
38992
|
const handleSortToggle = React21.useCallback(() => {
|
|
38837
38993
|
setSortAscending(!sortAscending);
|
|
38838
38994
|
}, [sortAscending]);
|
|
38839
|
-
const
|
|
38840
|
-
|
|
38841
|
-
|
|
38842
|
-
|
|
38843
|
-
}), [lineId, date, shift]);
|
|
38844
|
-
const {
|
|
38845
|
-
metrics: metrics2,
|
|
38846
|
-
lineDetails,
|
|
38847
|
-
loading: metricsLoading,
|
|
38848
|
-
error: metricsError,
|
|
38849
|
-
refreshMetrics
|
|
38850
|
-
} = useRealtimeLineMetrics(realtimeMetricsParams);
|
|
38995
|
+
const shiftId = React21.useMemo(
|
|
38996
|
+
() => typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
|
|
38997
|
+
[shift]
|
|
38998
|
+
);
|
|
38851
38999
|
const {
|
|
38852
39000
|
workspaces,
|
|
38853
39001
|
loading: workspacesLoading,
|
|
@@ -38857,12 +39005,12 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
38857
39005
|
initialDate: date,
|
|
38858
39006
|
initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0
|
|
38859
39007
|
});
|
|
38860
|
-
const getShiftName = React21.useCallback((
|
|
38861
|
-
if (
|
|
38862
|
-
return
|
|
39008
|
+
const getShiftName = React21.useCallback((shiftId2) => {
|
|
39009
|
+
if (shiftId2 === void 0) return "Day";
|
|
39010
|
+
return shiftId2 === 0 ? "Day" : "Night";
|
|
38863
39011
|
}, []);
|
|
38864
|
-
const getShiftIcon = React21.useCallback((
|
|
38865
|
-
const shift2 = getShiftName(
|
|
39012
|
+
const getShiftIcon = React21.useCallback((shiftId2) => {
|
|
39013
|
+
const shift2 = getShiftName(shiftId2);
|
|
38866
39014
|
if (shift2 === "Day") {
|
|
38867
39015
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" }) });
|
|
38868
39016
|
} else {
|
|
@@ -38904,17 +39052,18 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
38904
39052
|
return null;
|
|
38905
39053
|
}
|
|
38906
39054
|
}, [sortAscending]);
|
|
39055
|
+
const workspacesLength = React21.useMemo(() => workspaces?.length || 0, [workspaces?.length]);
|
|
38907
39056
|
const handleWorkspaceClick = React21.useCallback((workspace, rank) => {
|
|
38908
39057
|
trackCoreEvent("Workspace from Leaderboard Clicked", {
|
|
38909
39058
|
workspace_name: workspace.workspace_name,
|
|
38910
39059
|
workspace_id: workspace.workspace_uuid,
|
|
38911
39060
|
rank,
|
|
38912
|
-
total_workspaces:
|
|
39061
|
+
total_workspaces: workspacesLength,
|
|
38913
39062
|
efficiency: workspace.efficiency,
|
|
38914
39063
|
action_count: workspace.action_count,
|
|
38915
39064
|
action_threshold: workspace.action_threshold
|
|
38916
39065
|
});
|
|
38917
|
-
const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
39066
|
+
const displayName = workspace.displayName || getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
38918
39067
|
const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName, workspace.line_id) : "";
|
|
38919
39068
|
const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
|
|
38920
39069
|
if (onWorkspaceClick) {
|
|
@@ -38922,20 +39071,33 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
38922
39071
|
} else {
|
|
38923
39072
|
navigation.navigate(`/workspace/${workspace.workspace_uuid}${navParams}${returnToParam}`);
|
|
38924
39073
|
}
|
|
38925
|
-
}, [onWorkspaceClick, navigation, lineId,
|
|
38926
|
-
const
|
|
39074
|
+
}, [onWorkspaceClick, navigation, lineId, workspacesLength]);
|
|
39075
|
+
const workspaceDisplayData = React21.useMemo(() => {
|
|
38927
39076
|
if (!workspaces) return [];
|
|
38928
|
-
return
|
|
39077
|
+
return workspaces.map((ws) => ({
|
|
39078
|
+
...ws,
|
|
39079
|
+
displayName: getWorkspaceDisplayName(ws.workspace_name, ws.line_id),
|
|
39080
|
+
lineName: getLineName(ws.line_id)
|
|
39081
|
+
}));
|
|
39082
|
+
}, [workspaces, getLineName]);
|
|
39083
|
+
const sortedWorkspaces = React21.useMemo(() => {
|
|
39084
|
+
return [...workspaceDisplayData].sort((a, b) => {
|
|
38929
39085
|
const effA = a.efficiency || 0;
|
|
38930
39086
|
const effB = b.efficiency || 0;
|
|
38931
39087
|
return sortAscending ? effA - effB : effB - effA;
|
|
38932
39088
|
});
|
|
38933
|
-
}, [
|
|
38934
|
-
const loading =
|
|
38935
|
-
const error =
|
|
38936
|
-
const currentDateFormatted = React21.useMemo(() =>
|
|
38937
|
-
|
|
38938
|
-
|
|
39089
|
+
}, [workspaceDisplayData, sortAscending]);
|
|
39090
|
+
const loading = workspacesLoading;
|
|
39091
|
+
const error = workspacesError;
|
|
39092
|
+
const currentDateFormatted = React21.useMemo(() => {
|
|
39093
|
+
const dateStr = (/* @__PURE__ */ new Date()).toDateString();
|
|
39094
|
+
return formatDate(new Date(dateStr));
|
|
39095
|
+
}, [formatDate, date]);
|
|
39096
|
+
const currentMobileDateFormatted = React21.useMemo(() => {
|
|
39097
|
+
const dateStr = (/* @__PURE__ */ new Date()).toDateString();
|
|
39098
|
+
return formatMobileDate(new Date(dateStr));
|
|
39099
|
+
}, [formatMobileDate, date]);
|
|
39100
|
+
if (loading && (!workspaces || workspaces.length === 0)) {
|
|
38939
39101
|
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..." }) });
|
|
38940
39102
|
}
|
|
38941
39103
|
if (error) {
|
|
@@ -38944,7 +39106,7 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
38944
39106
|
error.message
|
|
38945
39107
|
] }) });
|
|
38946
39108
|
}
|
|
38947
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, children: [
|
|
39109
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, style: { willChange: "contents" }, children: [
|
|
38948
39110
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-20 bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 sm:px-6 md:px-8 py-2 sm:py-2.5", children: [
|
|
38949
39111
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
38950
39112
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -39036,31 +39198,30 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
39036
39198
|
{
|
|
39037
39199
|
currentDate: currentDateFormatted,
|
|
39038
39200
|
currentMobileDate: currentMobileDateFormatted,
|
|
39039
|
-
shiftId
|
|
39201
|
+
shiftId,
|
|
39040
39202
|
getShiftIcon,
|
|
39041
39203
|
getShiftName
|
|
39042
39204
|
}
|
|
39043
39205
|
)
|
|
39044
39206
|
] }) }),
|
|
39045
|
-
/* @__PURE__ */ jsxRuntime.
|
|
39046
|
-
|
|
39047
|
-
|
|
39048
|
-
|
|
39049
|
-
|
|
39050
|
-
|
|
39051
|
-
|
|
39052
|
-
|
|
39053
|
-
|
|
39054
|
-
|
|
39055
|
-
|
|
39056
|
-
|
|
39057
|
-
|
|
39058
|
-
|
|
39059
|
-
|
|
39060
|
-
|
|
39061
|
-
|
|
39062
|
-
|
|
39063
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block bg-white rounded-lg shadow-md overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse table-auto", children: [
|
|
39207
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full mx-auto p-3 sm:p-4 md:p-6", children: isMobile ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3", children: sortedWorkspaces.map((ws, index) => {
|
|
39208
|
+
const rank = index + 1;
|
|
39209
|
+
const isTopThree = index < 3;
|
|
39210
|
+
const cardClass = sortAscending ? isTopThree ? "bg-red-50/90 border-red-200" : "bg-white" : isTopThree ? "bg-green-50/90 border-green-200" : "bg-white";
|
|
39211
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
39212
|
+
MobileWorkspaceCard,
|
|
39213
|
+
{
|
|
39214
|
+
workspace: ws,
|
|
39215
|
+
rank,
|
|
39216
|
+
cardClass,
|
|
39217
|
+
onWorkspaceClick: handleWorkspaceClick,
|
|
39218
|
+
getMedalIcon
|
|
39219
|
+
},
|
|
39220
|
+
ws.workspace_uuid
|
|
39221
|
+
);
|
|
39222
|
+
}) }) : (
|
|
39223
|
+
/* Desktop table view - only render on desktop */
|
|
39224
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-white rounded-lg shadow-md overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxRuntime.jsxs("table", { className: "w-full border-collapse table-auto", children: [
|
|
39064
39225
|
/* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("tr", { children: [
|
|
39065
39226
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2.5 sm:p-4 text-left text-xs sm:text-sm font-semibold text-gray-600 whitespace-nowrap", children: "Rank" }),
|
|
39066
39227
|
/* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2.5 sm:p-4 text-left text-xs sm:text-sm font-semibold text-gray-600 whitespace-nowrap", children: "Workspace" }),
|
|
@@ -39079,17 +39240,16 @@ var LeaderboardDetailView = React21.memo(({
|
|
|
39079
39240
|
index,
|
|
39080
39241
|
rowClass,
|
|
39081
39242
|
onWorkspaceClick: handleWorkspaceClick,
|
|
39082
|
-
getMedalIcon
|
|
39083
|
-
getLineName
|
|
39243
|
+
getMedalIcon
|
|
39084
39244
|
},
|
|
39085
39245
|
ws.workspace_uuid
|
|
39086
39246
|
);
|
|
39087
39247
|
}) })
|
|
39088
39248
|
] }) }) })
|
|
39089
|
-
|
|
39249
|
+
) })
|
|
39090
39250
|
] });
|
|
39091
39251
|
}, (prevProps, nextProps) => {
|
|
39092
|
-
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className
|
|
39252
|
+
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className;
|
|
39093
39253
|
});
|
|
39094
39254
|
LeaderboardDetailView.displayName = "LeaderboardDetailView";
|
|
39095
39255
|
var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
|
|
@@ -40198,24 +40358,12 @@ var ACTION_NAMES = {
|
|
|
40198
40358
|
// src/views/TargetsView.utils.ts
|
|
40199
40359
|
var calculatePPH = (cycleTime, breaks = [], shiftHours = 0) => {
|
|
40200
40360
|
if (cycleTime === "" || cycleTime === 0) return "";
|
|
40201
|
-
const
|
|
40202
|
-
|
|
40203
|
-
return Number(basicPPH.toFixed(1));
|
|
40204
|
-
}
|
|
40205
|
-
const safeBreaks = Array.isArray(breaks) ? breaks : [];
|
|
40206
|
-
const totalBreakMinutes = safeBreaks.reduce((total, breakItem) => total + breakItem.duration, 0);
|
|
40207
|
-
const totalBreakHours = totalBreakMinutes / 60;
|
|
40208
|
-
const realWorkHours = shiftHours - totalBreakHours;
|
|
40209
|
-
const effectivePPH = basicPPH * (realWorkHours / shiftHours);
|
|
40210
|
-
return Number(effectivePPH.toFixed(1));
|
|
40361
|
+
const pph = 3600 / cycleTime;
|
|
40362
|
+
return Number(pph.toFixed(1));
|
|
40211
40363
|
};
|
|
40212
40364
|
var calculateDayOutput = (pph, shiftHours, breaks = []) => {
|
|
40213
40365
|
if (pph === "") return "";
|
|
40214
|
-
|
|
40215
|
-
const totalBreakMinutes = safeBreaks.reduce((total, breakItem) => total + breakItem.duration, 0);
|
|
40216
|
-
const totalBreakHours = totalBreakMinutes / 60;
|
|
40217
|
-
const realWorkHours = shiftHours - totalBreakHours;
|
|
40218
|
-
return Math.round(pph * realWorkHours);
|
|
40366
|
+
return Math.round(pph * shiftHours);
|
|
40219
40367
|
};
|
|
40220
40368
|
var formatWorkspaceName = (name, lineId) => {
|
|
40221
40369
|
return getWorkspaceDisplayName(name, lineId);
|
|
@@ -44263,6 +44411,7 @@ exports.AuthenticatedHomeView = AuthenticatedHomeView;
|
|
|
44263
44411
|
exports.AuthenticatedShiftsView = AuthenticatedShiftsView;
|
|
44264
44412
|
exports.AuthenticatedTargetsView = AuthenticatedTargetsView;
|
|
44265
44413
|
exports.AuthenticatedWorkspaceHealthView = AuthenticatedWorkspaceHealthView;
|
|
44414
|
+
exports.AxelNotificationPopup = AxelNotificationPopup;
|
|
44266
44415
|
exports.BackButton = BackButton;
|
|
44267
44416
|
exports.BackButtonMinimal = BackButtonMinimal;
|
|
44268
44417
|
exports.BarChart = BarChart;
|