@optifye/dashboard-core 4.2.3 → 4.2.5
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.d.mts +12 -1
- package/dist/index.d.ts +12 -1
- package/dist/index.js +1511 -1266
- package/dist/index.mjs +935 -692
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as
|
|
2
|
-
import
|
|
1
|
+
import * as React14 from 'react';
|
|
2
|
+
import React14__default, { createContext, useRef, useCallback, useState, useMemo, useEffect, memo, useContext, useLayoutEffect, useId, Children, isValidElement, useInsertionEffect, forwardRef, Fragment as Fragment$1, createElement, Component } from 'react';
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { useRouter } from 'next/router';
|
|
5
5
|
import { subDays, format, parseISO, isValid, isFuture, isToday } from 'date-fns';
|
|
@@ -12,7 +12,7 @@ import { noop, warning, invariant, progress, secondsToMilliseconds, milliseconds
|
|
|
12
12
|
import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
|
|
13
13
|
import { ResponsiveContainer, BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, ReferenceLine, Bar, Cell, LabelList, PieChart, Pie, Legend, LineChart as LineChart$1, Line } from 'recharts';
|
|
14
14
|
import { Slot } from '@radix-ui/react-slot';
|
|
15
|
-
import { ChevronDown, ChevronUp, Check,
|
|
15
|
+
import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, X, Coffee, Plus, Clock, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, RefreshCw, Menu, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Settings, LifeBuoy, Loader2, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
|
|
16
16
|
import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
|
|
17
17
|
import html2canvas from 'html2canvas';
|
|
18
18
|
import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
|
|
@@ -188,14 +188,14 @@ var _getDashboardConfigInstance = () => {
|
|
|
188
188
|
}
|
|
189
189
|
return dashboardConfigInstance;
|
|
190
190
|
};
|
|
191
|
-
var DashboardConfigContext =
|
|
191
|
+
var DashboardConfigContext = React14.createContext(void 0);
|
|
192
192
|
var DashboardProvider = ({ config: userProvidedConfig, children }) => {
|
|
193
|
-
const fullConfig =
|
|
193
|
+
const fullConfig = React14.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
|
|
194
194
|
_setDashboardConfigInstance(fullConfig);
|
|
195
|
-
|
|
195
|
+
React14.useEffect(() => {
|
|
196
196
|
_setDashboardConfigInstance(fullConfig);
|
|
197
197
|
}, [fullConfig]);
|
|
198
|
-
|
|
198
|
+
React14.useEffect(() => {
|
|
199
199
|
if (!fullConfig.theme) return;
|
|
200
200
|
const styleId = "dashboard-core-theme-vars";
|
|
201
201
|
let styleEl = document.getElementById(styleId);
|
|
@@ -221,7 +221,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
|
|
|
221
221
|
return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children });
|
|
222
222
|
};
|
|
223
223
|
var useDashboardConfig = () => {
|
|
224
|
-
const ctx =
|
|
224
|
+
const ctx = React14.useContext(DashboardConfigContext);
|
|
225
225
|
if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
|
|
226
226
|
return ctx;
|
|
227
227
|
};
|
|
@@ -849,6 +849,63 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
849
849
|
if (recentData) {
|
|
850
850
|
console.log(`[useWorkspaceDetailedMetrics] Found fallback data from date: ${recentData.date}, shift: ${recentData.shift_id}`);
|
|
851
851
|
const outputDifference2 = (recentData.total_output || 0) - (recentData.ideal_output || 0);
|
|
852
|
+
const workspaceMatch2 = recentData.workspace_name?.match(/WS(\d+)/);
|
|
853
|
+
const workspaceNumber2 = workspaceMatch2 ? parseInt(workspaceMatch2[1]) : 0;
|
|
854
|
+
const specialWsStart2 = workspaceConfig.specialWorkspaces?.startId ?? 19;
|
|
855
|
+
const specialWsEnd2 = workspaceConfig.specialWorkspaces?.endId ?? 34;
|
|
856
|
+
const isSpecialWorkspace2 = workspaceNumber2 >= specialWsStart2 && workspaceNumber2 <= specialWsEnd2;
|
|
857
|
+
const outputHourly2 = recentData.output_hourly || {};
|
|
858
|
+
const hasOutputHourlyData2 = outputHourly2 && typeof outputHourly2 === "object" && Object.keys(outputHourly2).length > 0;
|
|
859
|
+
let hourlyActionCounts2 = [];
|
|
860
|
+
if (hasOutputHourlyData2) {
|
|
861
|
+
console.log("Using new output_hourly column for workspace (fallback):", recentData.workspace_name);
|
|
862
|
+
console.log("Raw output_hourly data (fallback):", outputHourly2);
|
|
863
|
+
const isNightShift = recentData.shift_id === 1;
|
|
864
|
+
const shiftStart = recentData.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
865
|
+
const shiftEnd = recentData.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
866
|
+
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
867
|
+
let expectedHours = [];
|
|
868
|
+
if (isNightShift) {
|
|
869
|
+
for (let i = 0; i < 9; i++) {
|
|
870
|
+
expectedHours.push((startHour + i) % 24);
|
|
871
|
+
}
|
|
872
|
+
} else {
|
|
873
|
+
for (let i = 0; i < 9; i++) {
|
|
874
|
+
expectedHours.push((startHour + i) % 24);
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
console.log("Expected shift hours (fallback):", expectedHours);
|
|
878
|
+
console.log("Available data hours (fallback):", Object.keys(outputHourly2));
|
|
879
|
+
hourlyActionCounts2 = expectedHours.map((expectedHour) => {
|
|
880
|
+
let hourData = outputHourly2[expectedHour.toString()];
|
|
881
|
+
if (!hourData && isNightShift) {
|
|
882
|
+
for (const [storedHour, data2] of Object.entries(outputHourly2)) {
|
|
883
|
+
if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
|
|
884
|
+
if (storedHour === "18" && expectedHour === 1) {
|
|
885
|
+
hourData = data2;
|
|
886
|
+
console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour} (fallback)`);
|
|
887
|
+
break;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
|
|
893
|
+
});
|
|
894
|
+
console.log("Final hourly action counts (fallback):", hourlyActionCounts2);
|
|
895
|
+
} else {
|
|
896
|
+
console.log("Using output_array fallback for workspace (fallback):", recentData.workspace_name);
|
|
897
|
+
const minuteByMinuteArray = recentData.output_array || [];
|
|
898
|
+
if (isSpecialWorkspace2) {
|
|
899
|
+
const last40Readings = minuteByMinuteArray.slice(Math.max(0, minuteByMinuteArray.length - 40));
|
|
900
|
+
hourlyActionCounts2 = last40Readings;
|
|
901
|
+
} else {
|
|
902
|
+
for (let i = 0; i < minuteByMinuteArray.length; i += 60) {
|
|
903
|
+
const hourSlice = minuteByMinuteArray.slice(i, Math.min(i + 60, minuteByMinuteArray.length));
|
|
904
|
+
const hourlySum = hourSlice.reduce((sum, count) => sum + count, 0);
|
|
905
|
+
hourlyActionCounts2.push(hourlySum);
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
}
|
|
852
909
|
const transformedData2 = {
|
|
853
910
|
workspace_id: recentData.workspace_id,
|
|
854
911
|
workspace_name: recentData.workspace_name,
|
|
@@ -869,12 +926,14 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
869
926
|
ideal_cycle_time: recentData.ideal_cycle_time || 0,
|
|
870
927
|
avg_efficiency: recentData.efficiency || 0,
|
|
871
928
|
total_actions: recentData.total_output || 0,
|
|
872
|
-
hourly_action_counts:
|
|
929
|
+
hourly_action_counts: hourlyActionCounts2,
|
|
930
|
+
// Now uses the NEW logic with fallback
|
|
873
931
|
workspace_rank: recentData.workspace_rank || 0,
|
|
874
932
|
total_workspaces: recentData.total_workspaces || workspaceConfig.totalWorkspaces || 42,
|
|
875
933
|
ideal_output_until_now: recentData.ideal_output || 0,
|
|
876
934
|
output_difference: outputDifference2,
|
|
877
935
|
idle_time: recentData.idle_time || 0,
|
|
936
|
+
idle_time_hourly: recentData.idle_time_hourly || void 0,
|
|
878
937
|
...recentData.compliance_efficiency !== void 0 && { compliance_efficiency: recentData.compliance_efficiency },
|
|
879
938
|
...recentData.sop_check !== void 0 && { sop_check: recentData.sop_check }
|
|
880
939
|
};
|
|
@@ -901,17 +960,66 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
901
960
|
const specialWsStart = workspaceConfig.specialWorkspaces?.startId ?? 19;
|
|
902
961
|
const specialWsEnd = workspaceConfig.specialWorkspaces?.endId ?? 34;
|
|
903
962
|
const isSpecialWorkspace = workspaceNumber >= specialWsStart && workspaceNumber <= specialWsEnd;
|
|
904
|
-
const
|
|
963
|
+
const outputHourly = data.output_hourly || {};
|
|
964
|
+
console.log("[DEBUG] Raw data.output_hourly:", data.output_hourly);
|
|
965
|
+
console.log("[DEBUG] outputHourly after || {}:", outputHourly);
|
|
966
|
+
console.log("[DEBUG] typeof outputHourly:", typeof outputHourly);
|
|
967
|
+
console.log("[DEBUG] Object.keys(outputHourly):", Object.keys(outputHourly));
|
|
968
|
+
console.log("[DEBUG] Object.keys(outputHourly).length:", Object.keys(outputHourly).length);
|
|
969
|
+
const hasOutputHourlyData = outputHourly && typeof outputHourly === "object" && Object.keys(outputHourly).length > 0;
|
|
970
|
+
console.log("[DEBUG] hasOutputHourlyData:", hasOutputHourlyData);
|
|
905
971
|
let hourlyActionCounts = [];
|
|
906
|
-
if (
|
|
907
|
-
|
|
908
|
-
|
|
972
|
+
if (hasOutputHourlyData) {
|
|
973
|
+
console.log("\u2705 Using new output_hourly column for workspace:", data.workspace_name);
|
|
974
|
+
console.log("Raw output_hourly data:", JSON.stringify(outputHourly));
|
|
975
|
+
const isNightShift = data.shift_id === 1;
|
|
976
|
+
const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
977
|
+
const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
978
|
+
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
979
|
+
let expectedHours = [];
|
|
980
|
+
if (isNightShift) {
|
|
981
|
+
for (let i = 0; i < 9; i++) {
|
|
982
|
+
expectedHours.push((startHour + i) % 24);
|
|
983
|
+
}
|
|
984
|
+
} else {
|
|
985
|
+
for (let i = 0; i < 9; i++) {
|
|
986
|
+
expectedHours.push((startHour + i) % 24);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
console.log("Expected shift hours:", expectedHours);
|
|
990
|
+
console.log("Available data hours:", Object.keys(outputHourly));
|
|
991
|
+
hourlyActionCounts = expectedHours.map((expectedHour) => {
|
|
992
|
+
let hourData = outputHourly[expectedHour.toString()];
|
|
993
|
+
if (!hourData && isNightShift) {
|
|
994
|
+
for (const [storedHour, data2] of Object.entries(outputHourly)) {
|
|
995
|
+
if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
|
|
996
|
+
if (storedHour === "18" && expectedHour === 1) {
|
|
997
|
+
hourData = data2;
|
|
998
|
+
console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour}`);
|
|
999
|
+
break;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
|
|
1005
|
+
});
|
|
1006
|
+
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
909
1007
|
} else {
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
1008
|
+
console.log("\u274C Using output_array fallback for workspace:", data.workspace_name);
|
|
1009
|
+
console.log("[DEBUG] Fallback reason - hasOutputHourlyData is false");
|
|
1010
|
+
console.log("[DEBUG] data.output_hourly was:", data.output_hourly);
|
|
1011
|
+
const minuteByMinuteArray = data.output_array || [];
|
|
1012
|
+
if (isSpecialWorkspace) {
|
|
1013
|
+
const last40Readings = minuteByMinuteArray.slice(Math.max(0, minuteByMinuteArray.length - 40));
|
|
1014
|
+
hourlyActionCounts = last40Readings;
|
|
1015
|
+
} else {
|
|
1016
|
+
for (let i = 0; i < minuteByMinuteArray.length; i += 60) {
|
|
1017
|
+
const hourSlice = minuteByMinuteArray.slice(i, Math.min(i + 60, minuteByMinuteArray.length));
|
|
1018
|
+
const hourlySum = hourSlice.reduce((sum, count) => sum + count, 0);
|
|
1019
|
+
hourlyActionCounts.push(hourlySum);
|
|
1020
|
+
}
|
|
914
1021
|
}
|
|
1022
|
+
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
915
1023
|
}
|
|
916
1024
|
const transformedData = {
|
|
917
1025
|
workspace_id: data.workspace_id,
|
|
@@ -940,6 +1048,8 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
940
1048
|
output_difference: outputDifference,
|
|
941
1049
|
idle_time: data.idle_time || 0,
|
|
942
1050
|
// Add idle_time from performance_metrics table
|
|
1051
|
+
idle_time_hourly: data.idle_time_hourly || void 0,
|
|
1052
|
+
// Add idle_time_hourly from performance_metrics table
|
|
943
1053
|
...data.compliance_efficiency !== void 0 && { compliance_efficiency: data.compliance_efficiency },
|
|
944
1054
|
...data.sop_check !== void 0 && { sop_check: data.sop_check }
|
|
945
1055
|
};
|
|
@@ -1460,16 +1570,56 @@ var dashboardService = {
|
|
|
1460
1570
|
const specialStart = workspaceConfig.specialWorkspaces?.startId ?? 19;
|
|
1461
1571
|
const specialEnd = workspaceConfig.specialWorkspaces?.endId ?? 34;
|
|
1462
1572
|
const isSpecialWorkspace = workspaceNumber >= specialStart && workspaceNumber <= specialEnd;
|
|
1463
|
-
const
|
|
1573
|
+
const outputHourly = data.output_hourly || {};
|
|
1574
|
+
const hasOutputHourlyData = outputHourly && typeof outputHourly === "object" && Object.keys(outputHourly).length > 0;
|
|
1464
1575
|
let hourlyActionCounts = [];
|
|
1465
|
-
if (
|
|
1466
|
-
|
|
1467
|
-
|
|
1576
|
+
if (hasOutputHourlyData) {
|
|
1577
|
+
console.log("Using new output_hourly column for workspace:", data.workspace_name);
|
|
1578
|
+
console.log("Raw output_hourly data:", outputHourly);
|
|
1579
|
+
const isNightShift = data.shift_id === 1;
|
|
1580
|
+
const shiftStart = data.shift_start || (isNightShift ? "22:00" : "06:00");
|
|
1581
|
+
const shiftEnd = data.shift_end || (isNightShift ? "06:00" : "14:00");
|
|
1582
|
+
const startHour = parseInt(shiftStart.split(":")[0]);
|
|
1583
|
+
let expectedHours = [];
|
|
1584
|
+
if (isNightShift) {
|
|
1585
|
+
for (let i = 0; i < 9; i++) {
|
|
1586
|
+
expectedHours.push((startHour + i) % 24);
|
|
1587
|
+
}
|
|
1588
|
+
} else {
|
|
1589
|
+
for (let i = 0; i < 9; i++) {
|
|
1590
|
+
expectedHours.push((startHour + i) % 24);
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
console.log("Expected shift hours:", expectedHours);
|
|
1594
|
+
console.log("Available data hours:", Object.keys(outputHourly));
|
|
1595
|
+
hourlyActionCounts = expectedHours.map((expectedHour) => {
|
|
1596
|
+
let hourData = outputHourly[expectedHour.toString()];
|
|
1597
|
+
if (!hourData && isNightShift) {
|
|
1598
|
+
for (const [storedHour, data2] of Object.entries(outputHourly)) {
|
|
1599
|
+
if (Array.isArray(data2) && data2.length > 0 && data2.some((val) => val > 0)) {
|
|
1600
|
+
if (storedHour === "18" && expectedHour === 1) {
|
|
1601
|
+
hourData = data2;
|
|
1602
|
+
console.log(`Mapping stored hour ${storedHour} to expected hour ${expectedHour}`);
|
|
1603
|
+
break;
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
return Array.isArray(hourData) ? hourData.reduce((sum, count) => sum + (count || 0), 0) : 0;
|
|
1609
|
+
});
|
|
1610
|
+
console.log("Final hourly action counts:", hourlyActionCounts);
|
|
1468
1611
|
} else {
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1612
|
+
console.log("Using output_array fallback for workspace:", data.workspace_name);
|
|
1613
|
+
const minuteByMinuteArray = data.output_array || [];
|
|
1614
|
+
if (isSpecialWorkspace) {
|
|
1615
|
+
const numReadings = workspaceConfig.specialWorkspaces?.hourlyReadingsCount ?? 40;
|
|
1616
|
+
hourlyActionCounts = minuteByMinuteArray.slice(-numReadings);
|
|
1617
|
+
} else {
|
|
1618
|
+
for (let i = 0; i < minuteByMinuteArray.length; i += 60) {
|
|
1619
|
+
const hourSlice = minuteByMinuteArray.slice(i, Math.min(i + 60, minuteByMinuteArray.length));
|
|
1620
|
+
const hourlySum = hourSlice.reduce((sum, count) => sum + (count ?? 0), 0);
|
|
1621
|
+
hourlyActionCounts.push(hourlySum);
|
|
1622
|
+
}
|
|
1473
1623
|
}
|
|
1474
1624
|
}
|
|
1475
1625
|
const transformedData = {
|
|
@@ -1498,6 +1648,7 @@ var dashboardService = {
|
|
|
1498
1648
|
ideal_output_until_now: data.ideal_output || 0,
|
|
1499
1649
|
output_difference: outputDifference,
|
|
1500
1650
|
idle_time: data.idle_time || 0,
|
|
1651
|
+
idle_time_hourly: data.idle_time_hourly || void 0,
|
|
1501
1652
|
...data.compliance_efficiency !== void 0 && { compliance_efficiency: data.compliance_efficiency },
|
|
1502
1653
|
...data.sop_check !== void 0 && { sop_check: data.sop_check }
|
|
1503
1654
|
};
|
|
@@ -1650,18 +1801,20 @@ var dashboardService = {
|
|
|
1650
1801
|
date: queryDate,
|
|
1651
1802
|
shift_id: queryShiftId,
|
|
1652
1803
|
metrics: {
|
|
1653
|
-
avg_efficiency: avgEfficiencyFromLineMetrics,
|
|
1654
|
-
|
|
1804
|
+
avg_efficiency: avgEfficiencyFromPerf2 > 0 ? avgEfficiencyFromPerf2 : avgEfficiencyFromLineMetrics,
|
|
1805
|
+
// Use performance data first, fallback to line metrics
|
|
1806
|
+
avg_cycle_time: combinedMetricsData.avg_cycle_time / numLines,
|
|
1655
1807
|
current_output: combinedMetricsData.current_output,
|
|
1656
1808
|
ideal_output: combinedMetricsData.ideal_output,
|
|
1657
|
-
total_workspaces: 44,
|
|
1809
|
+
total_workspaces: combinedMetricsData.total_workspaces || 44,
|
|
1810
|
+
// Use combined or default
|
|
1658
1811
|
underperforming_workspaces: underperformingCount2,
|
|
1659
|
-
line_threshold: combinedMetricsData.
|
|
1660
|
-
threshold_pph:
|
|
1661
|
-
shift_start: "06:00",
|
|
1662
|
-
shift_end: "
|
|
1812
|
+
line_threshold: combinedMetricsData.line_threshold,
|
|
1813
|
+
threshold_pph: combinedMetricsData.threshold_pph / numLines,
|
|
1814
|
+
shift_start: metricsData?.[0]?.shift_start || shiftConfig.dayShift?.startTime || "06:00",
|
|
1815
|
+
shift_end: metricsData?.[0]?.shift_end || shiftConfig.dayShift?.endTime || "18:00",
|
|
1663
1816
|
last_updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1664
|
-
output_array: combinedMetricsData.output_array
|
|
1817
|
+
output_array: combinedMetricsData.output_array,
|
|
1665
1818
|
underperforming_workspace_names: [],
|
|
1666
1819
|
underperforming_workspace_uuids: [],
|
|
1667
1820
|
poorest_performing_workspaces: []
|
|
@@ -1693,7 +1846,8 @@ var dashboardService = {
|
|
|
1693
1846
|
date: queryDate,
|
|
1694
1847
|
shift_id: queryShiftId,
|
|
1695
1848
|
metrics: {
|
|
1696
|
-
avg_efficiency: metrics2?.avg_efficiency ??
|
|
1849
|
+
avg_efficiency: avgEfficiencyFromPerf > 0 ? avgEfficiencyFromPerf : metrics2?.avg_efficiency ?? 0,
|
|
1850
|
+
// Use performance data first, fallback to line metrics
|
|
1697
1851
|
avg_cycle_time: metrics2?.avg_cycle_time || 0,
|
|
1698
1852
|
current_output: metrics2?.current_output || 0,
|
|
1699
1853
|
ideal_output: metrics2?.ideal_output || metrics2?.line_threshold || 0,
|
|
@@ -1701,8 +1855,8 @@ var dashboardService = {
|
|
|
1701
1855
|
underperforming_workspaces: underperformingCount,
|
|
1702
1856
|
line_threshold: metrics2?.line_threshold || 0,
|
|
1703
1857
|
threshold_pph: metrics2?.threshold_pph || 0,
|
|
1704
|
-
shift_start: metrics2?.shift_start || shiftConfig.dayShift?.startTime || "
|
|
1705
|
-
shift_end: metrics2?.shift_end || shiftConfig.dayShift?.endTime || "
|
|
1858
|
+
shift_start: metrics2?.shift_start || shiftConfig.dayShift?.startTime || "06:00",
|
|
1859
|
+
shift_end: metrics2?.shift_end || shiftConfig.dayShift?.endTime || "18:00",
|
|
1706
1860
|
last_updated: metrics2?.last_updated || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1707
1861
|
output_array: metrics2?.output_array || [],
|
|
1708
1862
|
underperforming_workspace_names: metrics2?.underperforming_workspace_names || [],
|
|
@@ -4284,8 +4438,26 @@ async function initializeWorkspaceDisplayNames(explicitLineId) {
|
|
|
4284
4438
|
isInitializing = false;
|
|
4285
4439
|
}
|
|
4286
4440
|
}
|
|
4441
|
+
var preInitializeWorkspaceDisplayNames = async (lineId) => {
|
|
4442
|
+
console.log("\u{1F504} preInitializeWorkspaceDisplayNames called for lineId:", lineId);
|
|
4443
|
+
if (isInitialized || isInitializing) {
|
|
4444
|
+
console.log("\u{1F504} Already initialized or initializing, skipping pre-init");
|
|
4445
|
+
return;
|
|
4446
|
+
}
|
|
4447
|
+
await initializeWorkspaceDisplayNames(lineId);
|
|
4448
|
+
};
|
|
4449
|
+
var forceRefreshWorkspaceDisplayNames = async (lineId) => {
|
|
4450
|
+
console.log("\u{1F504} forceRefreshWorkspaceDisplayNames called for lineId:", lineId);
|
|
4451
|
+
clearWorkspaceDisplayNamesCache();
|
|
4452
|
+
await initializeWorkspaceDisplayNames(lineId);
|
|
4453
|
+
};
|
|
4287
4454
|
console.log("\u{1F504} Module loaded, will initialize lazily when first function is called");
|
|
4288
4455
|
var getWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
4456
|
+
if (!isInitialized && !isInitializing) {
|
|
4457
|
+
console.log(`\u{1F504} [DEBUG] getWorkspaceDisplayName(${workspaceId}) - Not initialized, triggering lazy init...`);
|
|
4458
|
+
} else if (isInitializing) {
|
|
4459
|
+
console.log(`\u{1F504} [DEBUG] getWorkspaceDisplayName(${workspaceId}) - Currently initializing...`);
|
|
4460
|
+
}
|
|
4289
4461
|
if (!isInitialized && !isInitializing) {
|
|
4290
4462
|
console.log("\u{1F504} Lazy initialization triggered by getWorkspaceDisplayName");
|
|
4291
4463
|
initializeWorkspaceDisplayNames(lineId).catch((error) => {
|
|
@@ -4369,6 +4541,7 @@ var clearWorkspaceDisplayNamesCache = () => {
|
|
|
4369
4541
|
workspaceService.clearWorkspaceDisplayNamesCache();
|
|
4370
4542
|
runtimeWorkspaceDisplayNames = {};
|
|
4371
4543
|
isInitialized = false;
|
|
4544
|
+
isInitializing = false;
|
|
4372
4545
|
};
|
|
4373
4546
|
|
|
4374
4547
|
// src/lib/hooks/useWorkspaceDisplayNames.ts
|
|
@@ -8037,7 +8210,7 @@ var MotionConfigContext = createContext({
|
|
|
8037
8210
|
});
|
|
8038
8211
|
|
|
8039
8212
|
// ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
|
|
8040
|
-
var PopChildMeasure = class extends
|
|
8213
|
+
var PopChildMeasure = class extends React14.Component {
|
|
8041
8214
|
getSnapshotBeforeUpdate(prevProps) {
|
|
8042
8215
|
const element = this.props.childRef.current;
|
|
8043
8216
|
if (element && prevProps.isPresent && !this.props.isPresent) {
|
|
@@ -8092,7 +8265,7 @@ function PopChild({ children, isPresent }) {
|
|
|
8092
8265
|
document.head.removeChild(style);
|
|
8093
8266
|
};
|
|
8094
8267
|
}, [isPresent]);
|
|
8095
|
-
return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children:
|
|
8268
|
+
return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React14.cloneElement(children, { ref }) });
|
|
8096
8269
|
}
|
|
8097
8270
|
|
|
8098
8271
|
// ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
|
|
@@ -8129,7 +8302,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
|
|
|
8129
8302
|
useMemo(() => {
|
|
8130
8303
|
presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
|
|
8131
8304
|
}, [isPresent]);
|
|
8132
|
-
|
|
8305
|
+
React14.useEffect(() => {
|
|
8133
8306
|
!isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
|
|
8134
8307
|
}, [isPresent]);
|
|
8135
8308
|
if (mode === "popLayout") {
|
|
@@ -15398,7 +15571,7 @@ var LoadingPage = ({
|
|
|
15398
15571
|
subMessage = "Please wait while we prepare your data",
|
|
15399
15572
|
className
|
|
15400
15573
|
}) => {
|
|
15401
|
-
|
|
15574
|
+
React14__default.useEffect(() => {
|
|
15402
15575
|
console.log("LoadingPage rendered with message:", message);
|
|
15403
15576
|
const timeout = setTimeout(() => {
|
|
15404
15577
|
console.warn("LoadingPage has been visible for more than 8 seconds. This might indicate an issue.");
|
|
@@ -15441,10 +15614,10 @@ var withAuth = (WrappedComponent2, options) => {
|
|
|
15441
15614
|
return function WithAuthComponent(props) {
|
|
15442
15615
|
const { session, loading } = useAuth();
|
|
15443
15616
|
const router = useRouter();
|
|
15444
|
-
|
|
15617
|
+
React14.useEffect(() => {
|
|
15445
15618
|
console.log("withAuth state:", { loading, hasSession: !!session, requireAuth: defaultOptions.requireAuth });
|
|
15446
15619
|
}, [session, loading]);
|
|
15447
|
-
|
|
15620
|
+
React14.useEffect(() => {
|
|
15448
15621
|
if (!loading && defaultOptions.requireAuth && !session) {
|
|
15449
15622
|
console.log("Redirecting to login from withAuth");
|
|
15450
15623
|
router.replace(defaultOptions.redirectTo);
|
|
@@ -16131,10 +16304,10 @@ var CycleTimeOverTimeChart = ({
|
|
|
16131
16304
|
};
|
|
16132
16305
|
const displayData = getDisplayData(data);
|
|
16133
16306
|
const DURATION = displayData.length;
|
|
16134
|
-
const [animatedData, setAnimatedData] =
|
|
16135
|
-
const prevDataRef =
|
|
16136
|
-
const animationFrameRef =
|
|
16137
|
-
const animateToNewData =
|
|
16307
|
+
const [animatedData, setAnimatedData] = React14__default.useState(Array(DURATION).fill(0));
|
|
16308
|
+
const prevDataRef = React14__default.useRef(Array(DURATION).fill(0));
|
|
16309
|
+
const animationFrameRef = React14__default.useRef(null);
|
|
16310
|
+
const animateToNewData = React14__default.useCallback((targetData) => {
|
|
16138
16311
|
const startData = [...prevDataRef.current];
|
|
16139
16312
|
const startTime = performance.now();
|
|
16140
16313
|
const duration = 1200;
|
|
@@ -16164,7 +16337,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
16164
16337
|
}
|
|
16165
16338
|
animationFrameRef.current = requestAnimationFrame(animate);
|
|
16166
16339
|
}, []);
|
|
16167
|
-
|
|
16340
|
+
React14__default.useEffect(() => {
|
|
16168
16341
|
if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
|
|
16169
16342
|
const processedData = getDisplayData(data);
|
|
16170
16343
|
animateToNewData(processedData);
|
|
@@ -16388,7 +16561,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
16388
16561
|
renderLegend()
|
|
16389
16562
|
] });
|
|
16390
16563
|
};
|
|
16391
|
-
var Card =
|
|
16564
|
+
var Card = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16392
16565
|
"div",
|
|
16393
16566
|
{
|
|
16394
16567
|
ref,
|
|
@@ -16400,7 +16573,7 @@ var Card = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
16400
16573
|
}
|
|
16401
16574
|
));
|
|
16402
16575
|
Card.displayName = "Card";
|
|
16403
|
-
var CardHeader =
|
|
16576
|
+
var CardHeader = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16404
16577
|
"div",
|
|
16405
16578
|
{
|
|
16406
16579
|
ref,
|
|
@@ -16409,7 +16582,7 @@ var CardHeader = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
16409
16582
|
}
|
|
16410
16583
|
));
|
|
16411
16584
|
CardHeader.displayName = "CardHeader";
|
|
16412
|
-
var CardTitle =
|
|
16585
|
+
var CardTitle = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16413
16586
|
"h3",
|
|
16414
16587
|
{
|
|
16415
16588
|
ref,
|
|
@@ -16421,7 +16594,7 @@ var CardTitle = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
16421
16594
|
}
|
|
16422
16595
|
));
|
|
16423
16596
|
CardTitle.displayName = "CardTitle";
|
|
16424
|
-
var CardDescription =
|
|
16597
|
+
var CardDescription = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16425
16598
|
"p",
|
|
16426
16599
|
{
|
|
16427
16600
|
ref,
|
|
@@ -16430,9 +16603,9 @@ var CardDescription = React33.forwardRef(({ className, ...props }, ref) => /* @_
|
|
|
16430
16603
|
}
|
|
16431
16604
|
));
|
|
16432
16605
|
CardDescription.displayName = "CardDescription";
|
|
16433
|
-
var CardContent =
|
|
16606
|
+
var CardContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
|
|
16434
16607
|
CardContent.displayName = "CardContent";
|
|
16435
|
-
var CardFooter =
|
|
16608
|
+
var CardFooter = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16436
16609
|
"div",
|
|
16437
16610
|
{
|
|
16438
16611
|
ref,
|
|
@@ -16508,7 +16681,7 @@ var buttonVariants = cva(
|
|
|
16508
16681
|
}
|
|
16509
16682
|
}
|
|
16510
16683
|
);
|
|
16511
|
-
var Button =
|
|
16684
|
+
var Button = React14.forwardRef(
|
|
16512
16685
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
16513
16686
|
const Comp = asChild ? Slot : "button";
|
|
16514
16687
|
return /* @__PURE__ */ jsx(
|
|
@@ -16539,10 +16712,30 @@ var HourlyOutputChart = ({
|
|
|
16539
16712
|
};
|
|
16540
16713
|
const shiftStartTime = getTimeFromTimeString(shiftStart);
|
|
16541
16714
|
const SHIFT_DURATION = 11;
|
|
16542
|
-
const [animatedData, setAnimatedData] =
|
|
16543
|
-
const prevDataRef =
|
|
16544
|
-
const animationFrameRef =
|
|
16545
|
-
const
|
|
16715
|
+
const [animatedData, setAnimatedData] = React14__default.useState(Array(SHIFT_DURATION).fill(0));
|
|
16716
|
+
const prevDataRef = React14__default.useRef(Array(SHIFT_DURATION).fill(0));
|
|
16717
|
+
const animationFrameRef = React14__default.useRef(null);
|
|
16718
|
+
const [shouldAnimateIdle, setShouldAnimateIdle] = React14__default.useState(false);
|
|
16719
|
+
const prevShowIdleTimeRef = React14__default.useRef(showIdleTime);
|
|
16720
|
+
const animationTimeoutRef = React14__default.useRef(null);
|
|
16721
|
+
React14__default.useEffect(() => {
|
|
16722
|
+
if (showIdleTime && !prevShowIdleTimeRef.current) {
|
|
16723
|
+
setShouldAnimateIdle(true);
|
|
16724
|
+
if (animationTimeoutRef.current) {
|
|
16725
|
+
clearTimeout(animationTimeoutRef.current);
|
|
16726
|
+
}
|
|
16727
|
+
animationTimeoutRef.current = setTimeout(() => {
|
|
16728
|
+
setShouldAnimateIdle(false);
|
|
16729
|
+
}, 1e3);
|
|
16730
|
+
}
|
|
16731
|
+
prevShowIdleTimeRef.current = showIdleTime;
|
|
16732
|
+
return () => {
|
|
16733
|
+
if (animationTimeoutRef.current) {
|
|
16734
|
+
clearTimeout(animationTimeoutRef.current);
|
|
16735
|
+
}
|
|
16736
|
+
};
|
|
16737
|
+
}, [showIdleTime]);
|
|
16738
|
+
const animateToNewData = React14__default.useCallback((targetData) => {
|
|
16546
16739
|
const startData = [...prevDataRef.current];
|
|
16547
16740
|
const startTime = performance.now();
|
|
16548
16741
|
const duration = 1200;
|
|
@@ -16572,7 +16765,7 @@ var HourlyOutputChart = ({
|
|
|
16572
16765
|
}
|
|
16573
16766
|
animationFrameRef.current = requestAnimationFrame(animate);
|
|
16574
16767
|
}, []);
|
|
16575
|
-
|
|
16768
|
+
React14__default.useEffect(() => {
|
|
16576
16769
|
if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
|
|
16577
16770
|
const shiftData = data.slice(0, SHIFT_DURATION);
|
|
16578
16771
|
animateToNewData(shiftData);
|
|
@@ -16583,7 +16776,7 @@ var HourlyOutputChart = ({
|
|
|
16583
16776
|
}
|
|
16584
16777
|
};
|
|
16585
16778
|
}, [data, animateToNewData]);
|
|
16586
|
-
const formatHour = (hourIndex) => {
|
|
16779
|
+
const formatHour = React14__default.useCallback((hourIndex) => {
|
|
16587
16780
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
16588
16781
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
16589
16782
|
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
@@ -16599,8 +16792,8 @@ var HourlyOutputChart = ({
|
|
|
16599
16792
|
return `${hour12}:${m.toString().padStart(2, "0")}${period}`;
|
|
16600
16793
|
};
|
|
16601
16794
|
return `${formatTime2(startHour, startMinute)}-${formatTime2(endHour, endMinute)}`;
|
|
16602
|
-
};
|
|
16603
|
-
const formatTimeRange = (hourIndex) => {
|
|
16795
|
+
}, [shiftStartTime.decimalHour]);
|
|
16796
|
+
const formatTimeRange = React14__default.useCallback((hourIndex) => {
|
|
16604
16797
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
16605
16798
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
16606
16799
|
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
@@ -16613,22 +16806,24 @@ var HourlyOutputChart = ({
|
|
|
16613
16806
|
return `${hour12}:${m.toString().padStart(2, "0")} ${period}`;
|
|
16614
16807
|
};
|
|
16615
16808
|
return `${formatTime2(startHour, startMinute)} - ${formatTime2(endHour, endMinute)}`;
|
|
16616
|
-
};
|
|
16617
|
-
const chartData =
|
|
16618
|
-
|
|
16619
|
-
|
|
16620
|
-
|
|
16621
|
-
|
|
16622
|
-
|
|
16623
|
-
|
|
16624
|
-
|
|
16625
|
-
|
|
16626
|
-
|
|
16627
|
-
|
|
16628
|
-
|
|
16629
|
-
|
|
16630
|
-
|
|
16631
|
-
|
|
16809
|
+
}, [shiftStartTime.decimalHour]);
|
|
16810
|
+
const chartData = React14__default.useMemo(() => {
|
|
16811
|
+
return Array.from({ length: SHIFT_DURATION }, (_, i) => {
|
|
16812
|
+
const actualHour = (shiftStartTime.hour + i) % 24;
|
|
16813
|
+
const idleArray = idleTimeHourly?.[actualHour.toString()] || [];
|
|
16814
|
+
const idleMinutes = idleArray.filter((val) => val === "1").length;
|
|
16815
|
+
return {
|
|
16816
|
+
hour: formatHour(i),
|
|
16817
|
+
timeRange: formatTimeRange(i),
|
|
16818
|
+
output: animatedData[i] || 0,
|
|
16819
|
+
originalOutput: data[i] || 0,
|
|
16820
|
+
// Keep original data for labels
|
|
16821
|
+
color: (animatedData[i] || 0) >= Math.round(pphThreshold) ? "#00AB45" : "#E34329",
|
|
16822
|
+
idleMinutes,
|
|
16823
|
+
idleArray
|
|
16824
|
+
};
|
|
16825
|
+
});
|
|
16826
|
+
}, [animatedData, data, pphThreshold, idleTimeHourly, shiftStartTime.hour, formatHour, formatTimeRange]);
|
|
16632
16827
|
const maxYValue = Math.ceil(pphThreshold * 1.5);
|
|
16633
16828
|
const generateYAxisTicks = () => {
|
|
16634
16829
|
const targetValue = Math.round(pphThreshold);
|
|
@@ -16721,10 +16916,10 @@ var HourlyOutputChart = ({
|
|
|
16721
16916
|
contentStyle: {
|
|
16722
16917
|
backgroundColor: "white",
|
|
16723
16918
|
border: "none",
|
|
16724
|
-
borderRadius: "
|
|
16725
|
-
boxShadow: "0
|
|
16726
|
-
padding: "
|
|
16727
|
-
fontSize: "
|
|
16919
|
+
borderRadius: "12px",
|
|
16920
|
+
boxShadow: "0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
|
|
16921
|
+
padding: "0",
|
|
16922
|
+
fontSize: "14px"
|
|
16728
16923
|
},
|
|
16729
16924
|
content: (props) => {
|
|
16730
16925
|
if (!props.active || !props.payload || props.payload.length === 0) return null;
|
|
@@ -16758,48 +16953,54 @@ var HourlyOutputChart = ({
|
|
|
16758
16953
|
const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
|
|
16759
16954
|
return `${hour12}:${minute.toString().padStart(2, "0")} ${period}`;
|
|
16760
16955
|
};
|
|
16761
|
-
return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-
|
|
16762
|
-
/* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-
|
|
16763
|
-
/* @__PURE__ */ jsxs("
|
|
16764
|
-
"
|
|
16765
|
-
|
|
16766
|
-
|
|
16767
|
-
|
|
16768
|
-
|
|
16769
|
-
] }),
|
|
16770
|
-
showIdleTime && data2.idleMinutes > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16771
|
-
/* @__PURE__ */ jsxs("p", { className: "text-gray-600 mb-1 border-t pt-1 mt-1", children: [
|
|
16772
|
-
"Idle Time: ",
|
|
16773
|
-
/* @__PURE__ */ jsxs("span", { className: "font-medium text-gray-700", children: [
|
|
16774
|
-
data2.idleMinutes,
|
|
16775
|
-
" minutes"
|
|
16956
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-xl border border-gray-100 p-4 min-w-[220px]", children: [
|
|
16957
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 text-sm", children: data2.timeRange }) }),
|
|
16958
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
16959
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
16960
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Output" }),
|
|
16961
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-gray-900 text-sm", children: [
|
|
16962
|
+
Math.round(data2.output),
|
|
16963
|
+
" units"
|
|
16776
16964
|
] })
|
|
16777
16965
|
] }),
|
|
16778
|
-
|
|
16779
|
-
/* @__PURE__ */ jsx("
|
|
16780
|
-
|
|
16781
|
-
|
|
16782
|
-
|
|
16783
|
-
|
|
16784
|
-
|
|
16785
|
-
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
|
|
16790
|
-
|
|
16791
|
-
|
|
16792
|
-
|
|
16793
|
-
|
|
16794
|
-
|
|
16795
|
-
|
|
16796
|
-
"
|
|
16797
|
-
|
|
16798
|
-
|
|
16799
|
-
|
|
16800
|
-
|
|
16801
|
-
|
|
16802
|
-
|
|
16966
|
+
showIdleTime && data2.idleMinutes > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16967
|
+
/* @__PURE__ */ jsx("div", { className: "border-t border-gray-100 pt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
16968
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Idle Time" }),
|
|
16969
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-orange-600 text-sm", children: [
|
|
16970
|
+
data2.idleMinutes,
|
|
16971
|
+
" minutes"
|
|
16972
|
+
] })
|
|
16973
|
+
] }) }),
|
|
16974
|
+
idleRanges.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-gray-50 rounded-lg p-2.5", children: [
|
|
16975
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
|
|
16976
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idleRanges.map((range, index) => {
|
|
16977
|
+
const duration = range.end - range.start + 1;
|
|
16978
|
+
const startTime = formatIdleTimestamp(range.start);
|
|
16979
|
+
const endTime = formatIdleTimestamp(range.end + 1);
|
|
16980
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
|
|
16981
|
+
/* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
|
|
16982
|
+
/* @__PURE__ */ jsx("span", { children: duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16983
|
+
startTime,
|
|
16984
|
+
" ",
|
|
16985
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
|
|
16986
|
+
"(",
|
|
16987
|
+
duration,
|
|
16988
|
+
" min)"
|
|
16989
|
+
] })
|
|
16990
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
16991
|
+
startTime,
|
|
16992
|
+
" - ",
|
|
16993
|
+
endTime,
|
|
16994
|
+
" ",
|
|
16995
|
+
/* @__PURE__ */ jsxs("span", { className: "text-gray-400", children: [
|
|
16996
|
+
"(",
|
|
16997
|
+
duration,
|
|
16998
|
+
" min)"
|
|
16999
|
+
] })
|
|
17000
|
+
] }) })
|
|
17001
|
+
] }, index);
|
|
17002
|
+
}) })
|
|
17003
|
+
] })
|
|
16803
17004
|
] })
|
|
16804
17005
|
] })
|
|
16805
17006
|
] });
|
|
@@ -16889,10 +17090,40 @@ var HourlyOutputChart = ({
|
|
|
16889
17090
|
radius: [10, 10, 0, 0],
|
|
16890
17091
|
fill: "url(#idlePattern)",
|
|
16891
17092
|
opacity: 0.7,
|
|
16892
|
-
isAnimationActive:
|
|
16893
|
-
animationBegin: 200,
|
|
16894
|
-
animationDuration: 800,
|
|
16895
|
-
animationEasing: "ease-out"
|
|
17093
|
+
isAnimationActive: shouldAnimateIdle,
|
|
17094
|
+
animationBegin: shouldAnimateIdle ? 200 : 0,
|
|
17095
|
+
animationDuration: shouldAnimateIdle ? 800 : 0,
|
|
17096
|
+
animationEasing: "ease-out",
|
|
17097
|
+
children: /* @__PURE__ */ jsx(
|
|
17098
|
+
LabelList,
|
|
17099
|
+
{
|
|
17100
|
+
dataKey: "idleMinutes",
|
|
17101
|
+
position: "top",
|
|
17102
|
+
content: (props) => {
|
|
17103
|
+
const { x, y, width, value } = props;
|
|
17104
|
+
if (!value || value === 0) return null;
|
|
17105
|
+
return /* @__PURE__ */ jsxs(
|
|
17106
|
+
"text",
|
|
17107
|
+
{
|
|
17108
|
+
x: x + width / 2,
|
|
17109
|
+
y: y - 2,
|
|
17110
|
+
textAnchor: "middle",
|
|
17111
|
+
fontSize: "9",
|
|
17112
|
+
fontWeight: "600",
|
|
17113
|
+
fill: "#6b7280",
|
|
17114
|
+
style: {
|
|
17115
|
+
opacity: 1,
|
|
17116
|
+
pointerEvents: "none"
|
|
17117
|
+
},
|
|
17118
|
+
children: [
|
|
17119
|
+
value,
|
|
17120
|
+
"m"
|
|
17121
|
+
]
|
|
17122
|
+
}
|
|
17123
|
+
);
|
|
17124
|
+
}
|
|
17125
|
+
}
|
|
17126
|
+
)
|
|
16896
17127
|
}
|
|
16897
17128
|
),
|
|
16898
17129
|
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("pattern", { id: "idlePattern", patternUnits: "userSpaceOnUse", width: "4", height: "4", children: [
|
|
@@ -16905,155 +17136,479 @@ var HourlyOutputChart = ({
|
|
|
16905
17136
|
renderLegend()
|
|
16906
17137
|
] });
|
|
16907
17138
|
};
|
|
16908
|
-
var
|
|
16909
|
-
|
|
16910
|
-
|
|
16911
|
-
|
|
16912
|
-
|
|
16913
|
-
|
|
16914
|
-
|
|
16915
|
-
Button,
|
|
16916
|
-
HourlyOutputChart
|
|
16917
|
-
};
|
|
16918
|
-
var RegistryCtx = createContext(defaults);
|
|
16919
|
-
var useRegistry = () => {
|
|
16920
|
-
const context = useContext(RegistryCtx);
|
|
16921
|
-
if (!context) {
|
|
16922
|
-
throw new Error("useRegistry must be used within a RegistryProvider");
|
|
16923
|
-
}
|
|
16924
|
-
return context;
|
|
16925
|
-
};
|
|
16926
|
-
function RegistryProvider({
|
|
16927
|
-
children,
|
|
16928
|
-
components = {}
|
|
16929
|
-
}) {
|
|
16930
|
-
if (process.env.NODE_ENV === "development") {
|
|
16931
|
-
const validKeys = Object.keys(defaults);
|
|
16932
|
-
Object.keys(components).forEach((key) => {
|
|
16933
|
-
if (!validKeys.includes(key)) {
|
|
16934
|
-
console.warn(`[RegistryProvider] Unknown component key: "${key}". Valid keys are: ${validKeys.join(", ")}`);
|
|
16935
|
-
}
|
|
16936
|
-
});
|
|
16937
|
-
}
|
|
16938
|
-
const mergedComponents = { ...defaults, ...components };
|
|
16939
|
-
return /* @__PURE__ */ jsx(RegistryCtx.Provider, { value: mergedComponents, children });
|
|
16940
|
-
}
|
|
16941
|
-
function withRegistry(Component3) {
|
|
16942
|
-
function WithRegistry(props) {
|
|
16943
|
-
useRegistry();
|
|
16944
|
-
return /* @__PURE__ */ jsx(Component3, { ...props });
|
|
16945
|
-
}
|
|
16946
|
-
WithRegistry.displayName = `withRegistry(${Component3.displayName || Component3.name})`;
|
|
16947
|
-
return WithRegistry;
|
|
16948
|
-
}
|
|
16949
|
-
var HourlyOutputChart2 = (props) => {
|
|
16950
|
-
const { HourlyOutputChart: RegisteredHourlyOutputChart } = useRegistry();
|
|
16951
|
-
return /* @__PURE__ */ jsx(RegisteredHourlyOutputChart, { ...props });
|
|
16952
|
-
};
|
|
16953
|
-
var HourlyComplianceDot = (props) => {
|
|
16954
|
-
const { cx: cx2, cy, index, payload, targetCompliance } = props;
|
|
16955
|
-
const complianceValue = payload?.compliance;
|
|
16956
|
-
if (typeof index !== "number" || index % 60 !== 0 || typeof complianceValue !== "number" || complianceValue === null) {
|
|
16957
|
-
return null;
|
|
16958
|
-
}
|
|
16959
|
-
const roundedValue = Math.round(complianceValue);
|
|
16960
|
-
const isAboveTarget = roundedValue >= targetCompliance;
|
|
16961
|
-
const labelColor = isAboveTarget ? "#10B981" : "#EF4444";
|
|
16962
|
-
return /* @__PURE__ */ jsxs("g", { children: [
|
|
16963
|
-
/* @__PURE__ */ jsx("circle", { cx: cx2, cy, r: 4, fill: "#EF4444" }),
|
|
16964
|
-
" ",
|
|
16965
|
-
/* @__PURE__ */ jsx(
|
|
16966
|
-
"text",
|
|
16967
|
-
{
|
|
16968
|
-
x: cx2,
|
|
16969
|
-
y: cy ? cy - 10 : 0,
|
|
16970
|
-
dy: 0,
|
|
16971
|
-
textAnchor: "middle",
|
|
16972
|
-
fill: labelColor,
|
|
16973
|
-
fontSize: 12,
|
|
16974
|
-
fontWeight: 600,
|
|
16975
|
-
children: `${roundedValue}%`
|
|
16976
|
-
}
|
|
16977
|
-
)
|
|
16978
|
-
] });
|
|
17139
|
+
var TREND_STYLES = {
|
|
17140
|
+
0: { arrow: "\u2193", color: "text-red-500 font-bold text-shadow" },
|
|
17141
|
+
// Down
|
|
17142
|
+
1: { arrow: "\u2013", color: "text-gray-500 font-bold text-shadow" },
|
|
17143
|
+
// Unchanged
|
|
17144
|
+
2: { arrow: "\u2191", color: "text-green-500 font-bold text-shadow" }
|
|
17145
|
+
// Up
|
|
16979
17146
|
};
|
|
16980
|
-
var
|
|
16981
|
-
|
|
16982
|
-
|
|
16983
|
-
|
|
17147
|
+
var getTrendArrowAndColor = (trend) => TREND_STYLES[trend] || { arrow: "", color: "" };
|
|
17148
|
+
var VideoCard = React14__default.memo(({
|
|
17149
|
+
workspace,
|
|
17150
|
+
hlsUrl,
|
|
17151
|
+
shouldPlay,
|
|
17152
|
+
onClick,
|
|
17153
|
+
onFatalError,
|
|
17154
|
+
isVeryLowEfficiency = false,
|
|
16984
17155
|
className = ""
|
|
16985
17156
|
}) => {
|
|
16986
|
-
const
|
|
16987
|
-
|
|
16988
|
-
|
|
16989
|
-
|
|
16990
|
-
|
|
16991
|
-
|
|
16992
|
-
const
|
|
16993
|
-
|
|
16994
|
-
const
|
|
16995
|
-
|
|
16996
|
-
|
|
16997
|
-
|
|
16998
|
-
|
|
16999
|
-
|
|
17000
|
-
|
|
17001
|
-
const animateToNewData = useCallback((targetData) => {
|
|
17002
|
-
const startData = [...prevDataRef.current];
|
|
17003
|
-
while (startData.length < targetData.length) {
|
|
17004
|
-
startData.push(startData.length > 0 ? startData[startData.length - 1] : 0);
|
|
17005
|
-
}
|
|
17006
|
-
const startTime = performance.now();
|
|
17007
|
-
const duration = 400;
|
|
17008
|
-
const animate = (currentTime) => {
|
|
17009
|
-
const elapsed = currentTime - startTime;
|
|
17010
|
-
const progress6 = Math.min(elapsed / duration, 1);
|
|
17011
|
-
const easeOutQuad = (t) => 1 - (1 - t) * (1 - t);
|
|
17012
|
-
const easedProgress = easeOutQuad(progress6);
|
|
17013
|
-
const newData = startData.map((start, index) => {
|
|
17014
|
-
if (index >= targetData.length) return start;
|
|
17015
|
-
const target = targetData[index];
|
|
17016
|
-
const change = target - start;
|
|
17017
|
-
return start + change * easedProgress;
|
|
17018
|
-
});
|
|
17019
|
-
setAnimatedData(newData);
|
|
17020
|
-
prevDataRef.current = newData;
|
|
17021
|
-
if (progress6 < 1) {
|
|
17022
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
17023
|
-
} else {
|
|
17024
|
-
setAnimatedData(targetData);
|
|
17025
|
-
prevDataRef.current = targetData;
|
|
17026
|
-
}
|
|
17027
|
-
};
|
|
17028
|
-
if (animationFrameRef.current) {
|
|
17029
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
17030
|
-
}
|
|
17031
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
17032
|
-
}, []);
|
|
17033
|
-
useEffect(() => {
|
|
17034
|
-
if (data.length === 0) {
|
|
17035
|
-
if (prevDataRef.current.length === 0) {
|
|
17036
|
-
animateToNewData(mockData);
|
|
17037
|
-
}
|
|
17038
|
-
return;
|
|
17157
|
+
const videoRef = useRef(null);
|
|
17158
|
+
useHlsStream(videoRef, {
|
|
17159
|
+
src: hlsUrl,
|
|
17160
|
+
shouldPlay,
|
|
17161
|
+
onFatalError: onFatalError ?? (() => throttledReloadDashboard())
|
|
17162
|
+
});
|
|
17163
|
+
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
17164
|
+
workspace.workspace_uuid || workspace.workspace_name;
|
|
17165
|
+
const getEfficiencyOverlayColor = (efficiency) => {
|
|
17166
|
+
if (efficiency >= 80) {
|
|
17167
|
+
return "bg-[#00D654]/25";
|
|
17168
|
+
} else if (efficiency >= 70) {
|
|
17169
|
+
return "bg-[#FFD700]/30";
|
|
17170
|
+
} else {
|
|
17171
|
+
return "bg-[#FF2D0A]/30";
|
|
17039
17172
|
}
|
|
17040
|
-
|
|
17041
|
-
|
|
17042
|
-
|
|
17173
|
+
};
|
|
17174
|
+
const getEfficiencyBarColor = (efficiency) => {
|
|
17175
|
+
if (efficiency >= 80) {
|
|
17176
|
+
return "bg-[#00AB45]";
|
|
17177
|
+
} else if (efficiency >= 70) {
|
|
17178
|
+
return "bg-[#FFB020]";
|
|
17179
|
+
} else {
|
|
17180
|
+
return "bg-[#E34329]";
|
|
17043
17181
|
}
|
|
17044
|
-
|
|
17045
|
-
|
|
17046
|
-
|
|
17047
|
-
|
|
17048
|
-
|
|
17049
|
-
|
|
17050
|
-
|
|
17051
|
-
|
|
17052
|
-
|
|
17053
|
-
|
|
17054
|
-
|
|
17055
|
-
|
|
17056
|
-
|
|
17182
|
+
};
|
|
17183
|
+
const efficiencyOverlayClass = getEfficiencyOverlayColor(workspace.efficiency);
|
|
17184
|
+
const efficiencyBarClass = getEfficiencyBarColor(workspace.efficiency);
|
|
17185
|
+
const trendInfo = workspace.trend !== void 0 ? getTrendArrowAndColor(workspace.trend) : null;
|
|
17186
|
+
const handleClick = useCallback(() => {
|
|
17187
|
+
if (onClick) {
|
|
17188
|
+
onClick();
|
|
17189
|
+
}
|
|
17190
|
+
}, [onClick]);
|
|
17191
|
+
return /* @__PURE__ */ jsxs(
|
|
17192
|
+
"div",
|
|
17193
|
+
{
|
|
17194
|
+
className: `workspace-card relative bg-gray-950 rounded-md overflow-hidden cursor-pointer transform hover:scale-[1.005] transition-transform duration-200 shadow-sm ${className}`,
|
|
17195
|
+
style: { width: "100%", height: "100%" },
|
|
17196
|
+
onClick: handleClick,
|
|
17197
|
+
title: displayName,
|
|
17198
|
+
tabIndex: 0,
|
|
17199
|
+
"aria-label": `Open workspace ${displayName}`,
|
|
17200
|
+
onKeyDown: (e) => {
|
|
17201
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
17202
|
+
e.preventDefault();
|
|
17203
|
+
handleClick();
|
|
17204
|
+
}
|
|
17205
|
+
},
|
|
17206
|
+
children: [
|
|
17207
|
+
isVeryLowEfficiency && /* @__PURE__ */ jsx("div", { className: "absolute top-1 left-2 z-30", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
17208
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -inset-1 bg-red-400/50 rounded-full blur-sm animate-pulse" }),
|
|
17209
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -inset-0.5 bg-red-500/30 rounded-full blur-md animate-ping [animation-duration:1.5s]" }),
|
|
17210
|
+
/* @__PURE__ */ jsx("div", { className: "bg-[#E34329] w-5 h-5 rounded-full flex items-center justify-center text-white font-bold text-xs shadow-lg ring-2 ring-red-400/40 border border-red-400/80 animate-pulse", children: "!" })
|
|
17211
|
+
] }) }),
|
|
17212
|
+
/* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden bg-black", children: [
|
|
17213
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black z-0", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse flex flex-col items-center", children: [
|
|
17214
|
+
/* @__PURE__ */ jsx(Camera, { className: "w-6 h-6 text-gray-500" }),
|
|
17215
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500 mt-1", children: "Loading..." })
|
|
17216
|
+
] }) }),
|
|
17217
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10", children: /* @__PURE__ */ jsx(
|
|
17218
|
+
"video",
|
|
17219
|
+
{
|
|
17220
|
+
ref: videoRef,
|
|
17221
|
+
className: "h-full w-full object-cover",
|
|
17222
|
+
playsInline: true,
|
|
17223
|
+
muted: true,
|
|
17224
|
+
disablePictureInPicture: true,
|
|
17225
|
+
controlsList: "nodownload noplaybackrate"
|
|
17226
|
+
}
|
|
17227
|
+
) }),
|
|
17228
|
+
/* @__PURE__ */ jsx("div", { className: `absolute inset-0 z-20 pointer-events-none ${efficiencyOverlayClass}` }),
|
|
17229
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute top-2 right-2 z-30 bg-black/70 backdrop-blur-sm rounded px-2 py-0.5 text-white text-xs font-semibold border border-white/10", children: [
|
|
17230
|
+
Math.round(workspace.efficiency),
|
|
17231
|
+
"%"
|
|
17232
|
+
] }),
|
|
17233
|
+
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 h-1 bg-black/50 z-30", children: /* @__PURE__ */ jsx(
|
|
17234
|
+
"div",
|
|
17235
|
+
{
|
|
17236
|
+
className: `h-full ${efficiencyBarClass} transition-all duration-500`,
|
|
17237
|
+
style: { width: `${Math.min(100, workspace.efficiency)}%` }
|
|
17238
|
+
}
|
|
17239
|
+
) })
|
|
17240
|
+
] }),
|
|
17241
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 p-1.5 flex justify-between items-center z-10", children: [
|
|
17242
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
17243
|
+
/* @__PURE__ */ jsx(Camera, { size: 12, className: "text-white" }),
|
|
17244
|
+
/* @__PURE__ */ jsx("p", { className: "text-white text-xs font-medium tracking-wide", children: displayName })
|
|
17245
|
+
] }),
|
|
17246
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
17247
|
+
trendInfo && /* @__PURE__ */ jsx(
|
|
17248
|
+
"div",
|
|
17249
|
+
{
|
|
17250
|
+
className: `text-lg ${trendInfo.color}`,
|
|
17251
|
+
style: { lineHeight: 1, display: "flex", alignItems: "center" },
|
|
17252
|
+
children: trendInfo.arrow
|
|
17253
|
+
}
|
|
17254
|
+
),
|
|
17255
|
+
/* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-green-500" }),
|
|
17256
|
+
/* @__PURE__ */ jsx("span", { className: "text-white text-xs", children: "Live" })
|
|
17257
|
+
] })
|
|
17258
|
+
] })
|
|
17259
|
+
]
|
|
17260
|
+
}
|
|
17261
|
+
);
|
|
17262
|
+
}, (prevProps, nextProps) => {
|
|
17263
|
+
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay;
|
|
17264
|
+
});
|
|
17265
|
+
VideoCard.displayName = "VideoCard";
|
|
17266
|
+
var DEFAULT_WORKSPACE_HLS_URLS = {
|
|
17267
|
+
"WS1": "https://dnh-hls.optifye.ai/cam1/index.m3u8",
|
|
17268
|
+
"WS2": "https://dnh-hls.optifye.ai/cam2/index.m3u8",
|
|
17269
|
+
"WS3": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
17270
|
+
"WS4": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
17271
|
+
"WS01": "https://59.144.218.58:8443/camera6.m3u8",
|
|
17272
|
+
"WS02": "https://59.144.218.58:8443/camera2.m3u8",
|
|
17273
|
+
"WS03": "https://59.144.218.58:8443/camera3.m3u8",
|
|
17274
|
+
"WS04": "https://59.144.218.58:8443/camera4.m3u8",
|
|
17275
|
+
"WS05": "https://59.144.218.58:8443/camera1.m3u8",
|
|
17276
|
+
"WS06": "https://59.144.218.58:8443/camera5.m3u8"
|
|
17277
|
+
};
|
|
17278
|
+
var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
|
|
17279
|
+
var VideoGridView = React14__default.memo(({
|
|
17280
|
+
workspaces,
|
|
17281
|
+
selectedLine,
|
|
17282
|
+
className = "",
|
|
17283
|
+
lineIdMapping = {},
|
|
17284
|
+
videoSources = {}
|
|
17285
|
+
}) => {
|
|
17286
|
+
const router = useRouter();
|
|
17287
|
+
const containerRef = useRef(null);
|
|
17288
|
+
const observerRef = useRef(null);
|
|
17289
|
+
const [gridCols, setGridCols] = useState(4);
|
|
17290
|
+
const [visibleWorkspaces, setVisibleWorkspaces] = useState(/* @__PURE__ */ new Set());
|
|
17291
|
+
const mergedVideoSources = {
|
|
17292
|
+
defaultHlsUrl: videoSources.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17293
|
+
workspaceHlsUrls: { ...DEFAULT_WORKSPACE_HLS_URLS, ...videoSources.workspaceHlsUrls }
|
|
17294
|
+
};
|
|
17295
|
+
const getWorkspaceHlsUrl = useCallback((workspaceName) => {
|
|
17296
|
+
const wsName = workspaceName.toUpperCase();
|
|
17297
|
+
return mergedVideoSources.workspaceHlsUrls[wsName] || mergedVideoSources.defaultHlsUrl;
|
|
17298
|
+
}, [mergedVideoSources]);
|
|
17299
|
+
const veryLowEfficiencyWorkspaces = useMemo(() => {
|
|
17300
|
+
return new Set(
|
|
17301
|
+
workspaces.filter((w) => w.efficiency < 50 && w.efficiency >= 10).map((w) => w.workspace_name)
|
|
17302
|
+
);
|
|
17303
|
+
}, [workspaces]);
|
|
17304
|
+
const filteredWorkspaces = useMemo(() => {
|
|
17305
|
+
return selectedLine === 1 ? workspaces.filter((w) => {
|
|
17306
|
+
if (w.workspace_name === "WS5-5") return true;
|
|
17307
|
+
if (w.workspace_name === "WS32-5") return false;
|
|
17308
|
+
try {
|
|
17309
|
+
const wsNumber = parseInt(w.workspace_name.replace("WS", ""));
|
|
17310
|
+
return wsNumber >= 1 && wsNumber <= 22;
|
|
17311
|
+
} catch {
|
|
17312
|
+
return true;
|
|
17313
|
+
}
|
|
17314
|
+
}) : selectedLine === 2 ? workspaces.filter((w) => {
|
|
17315
|
+
if (w.workspace_name === "WS5-5") return false;
|
|
17316
|
+
if (w.workspace_name === "WS32-5") return true;
|
|
17317
|
+
try {
|
|
17318
|
+
const wsNumber = parseInt(w.workspace_name.replace("WS", ""));
|
|
17319
|
+
return wsNumber >= 23 && wsNumber <= 44;
|
|
17320
|
+
} catch {
|
|
17321
|
+
return false;
|
|
17322
|
+
}
|
|
17323
|
+
}) : workspaces;
|
|
17324
|
+
}, [workspaces, selectedLine]);
|
|
17325
|
+
const calculateOptimalGrid = useCallback(() => {
|
|
17326
|
+
if (!containerRef.current) return;
|
|
17327
|
+
const containerPadding = 16;
|
|
17328
|
+
const containerWidth = containerRef.current.clientWidth - containerPadding;
|
|
17329
|
+
const containerHeight = containerRef.current.clientHeight - containerPadding;
|
|
17330
|
+
const count = filteredWorkspaces.length;
|
|
17331
|
+
if (count === 0) {
|
|
17332
|
+
setGridCols(1);
|
|
17333
|
+
return;
|
|
17334
|
+
}
|
|
17335
|
+
let bestCols = 1;
|
|
17336
|
+
let bestScore = 0;
|
|
17337
|
+
const targetAspectRatio = 16 / 9;
|
|
17338
|
+
const gap = 8;
|
|
17339
|
+
const maxCols = Math.min(count, 6);
|
|
17340
|
+
for (let cols = 1; cols <= maxCols; cols++) {
|
|
17341
|
+
const rows = Math.ceil(count / cols);
|
|
17342
|
+
const availableWidth = containerWidth - gap * (cols - 1);
|
|
17343
|
+
const availableHeight = containerHeight - gap * (rows - 1);
|
|
17344
|
+
const cellWidth = availableWidth / cols;
|
|
17345
|
+
const cellHeight = availableHeight / rows;
|
|
17346
|
+
const minCellWidth = containerWidth < 800 ? 120 : 150;
|
|
17347
|
+
const minCellHeight = containerHeight < 600 ? 80 : 100;
|
|
17348
|
+
if (cellWidth < minCellWidth || cellHeight < minCellHeight) continue;
|
|
17349
|
+
const totalUsedArea = cellWidth * cellHeight * count;
|
|
17350
|
+
const totalAvailableArea = containerWidth * containerHeight;
|
|
17351
|
+
const spaceUtilization = totalUsedArea / totalAvailableArea;
|
|
17352
|
+
const actualAspectRatio = cellWidth / cellHeight;
|
|
17353
|
+
const aspectRatioScore = 1 / (1 + Math.abs(actualAspectRatio - targetAspectRatio) * 0.3);
|
|
17354
|
+
const score = spaceUtilization * 0.9 + aspectRatioScore * 0.1;
|
|
17355
|
+
if (score > bestScore) {
|
|
17356
|
+
bestScore = score;
|
|
17357
|
+
bestCols = cols;
|
|
17358
|
+
}
|
|
17359
|
+
}
|
|
17360
|
+
if (bestScore === 0) {
|
|
17361
|
+
bestCols = Math.ceil(Math.sqrt(count));
|
|
17362
|
+
}
|
|
17363
|
+
setGridCols(bestCols);
|
|
17364
|
+
}, [filteredWorkspaces.length]);
|
|
17365
|
+
useEffect(() => {
|
|
17366
|
+
calculateOptimalGrid();
|
|
17367
|
+
const handleResize = () => calculateOptimalGrid();
|
|
17368
|
+
window.addEventListener("resize", handleResize);
|
|
17369
|
+
return () => window.removeEventListener("resize", handleResize);
|
|
17370
|
+
}, [calculateOptimalGrid]);
|
|
17371
|
+
useEffect(() => {
|
|
17372
|
+
if (!containerRef.current) return;
|
|
17373
|
+
const options = {
|
|
17374
|
+
root: null,
|
|
17375
|
+
rootMargin: "50px",
|
|
17376
|
+
threshold: 0.1
|
|
17377
|
+
};
|
|
17378
|
+
observerRef.current = new IntersectionObserver((entries) => {
|
|
17379
|
+
entries.forEach((entry) => {
|
|
17380
|
+
const workspaceId = entry.target.getAttribute("data-workspace-id");
|
|
17381
|
+
if (!workspaceId) return;
|
|
17382
|
+
setVisibleWorkspaces((prev) => {
|
|
17383
|
+
const next = new Set(prev);
|
|
17384
|
+
if (entry.isIntersecting) {
|
|
17385
|
+
next.add(workspaceId);
|
|
17386
|
+
} else {
|
|
17387
|
+
next.delete(workspaceId);
|
|
17388
|
+
}
|
|
17389
|
+
return next;
|
|
17390
|
+
});
|
|
17391
|
+
});
|
|
17392
|
+
}, options);
|
|
17393
|
+
const elements = containerRef.current.querySelectorAll("[data-workspace-id]");
|
|
17394
|
+
elements.forEach((el) => observerRef.current?.observe(el));
|
|
17395
|
+
return () => {
|
|
17396
|
+
observerRef.current?.disconnect();
|
|
17397
|
+
};
|
|
17398
|
+
}, [filteredWorkspaces]);
|
|
17399
|
+
const handleWorkspaceClick = useCallback((workspace) => {
|
|
17400
|
+
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
17401
|
+
trackCoreEvent("Workspace Detail Clicked", {
|
|
17402
|
+
workspace_name: workspace.workspace_name,
|
|
17403
|
+
workspace_id: workspaceId,
|
|
17404
|
+
view_type: "video_grid",
|
|
17405
|
+
performance_score: workspace.performance_score,
|
|
17406
|
+
efficiency: workspace.efficiency,
|
|
17407
|
+
action_count: workspace.action_count
|
|
17408
|
+
});
|
|
17409
|
+
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
17410
|
+
const navParams = getWorkspaceNavigationParams(workspaceId, displayName);
|
|
17411
|
+
router.push(`/workspace/${workspaceId}${navParams}`);
|
|
17412
|
+
}, [router]);
|
|
17413
|
+
return /* @__PURE__ */ jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "h-full w-full p-2", children: /* @__PURE__ */ jsx(
|
|
17414
|
+
"div",
|
|
17415
|
+
{
|
|
17416
|
+
className: "grid h-full w-full gap-2",
|
|
17417
|
+
style: {
|
|
17418
|
+
gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
|
|
17419
|
+
gridTemplateRows: `repeat(${Math.ceil(filteredWorkspaces.length / gridCols)}, 1fr)`,
|
|
17420
|
+
minHeight: "100%"
|
|
17421
|
+
},
|
|
17422
|
+
children: filteredWorkspaces.sort((a, b) => {
|
|
17423
|
+
const aNum = parseInt(a.workspace_name.slice(2));
|
|
17424
|
+
const bNum = parseInt(b.workspace_name.slice(2));
|
|
17425
|
+
if (!selectedLine) {
|
|
17426
|
+
const aIsLine2 = a.line_id === lineIdMapping.line2;
|
|
17427
|
+
const bIsLine2 = b.line_id === lineIdMapping.line2;
|
|
17428
|
+
if (aIsLine2 !== bIsLine2) {
|
|
17429
|
+
return aIsLine2 ? 1 : -1;
|
|
17430
|
+
}
|
|
17431
|
+
}
|
|
17432
|
+
return aNum - bNum;
|
|
17433
|
+
}).map((workspace) => {
|
|
17434
|
+
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
17435
|
+
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
17436
|
+
const isVeryLowEfficiency = veryLowEfficiencyWorkspaces.has(workspace.workspace_name);
|
|
17437
|
+
return /* @__PURE__ */ jsx(
|
|
17438
|
+
"div",
|
|
17439
|
+
{
|
|
17440
|
+
"data-workspace-id": workspaceId,
|
|
17441
|
+
className: "workspace-card relative min-h-0 min-w-0",
|
|
17442
|
+
style: { width: "100%", height: "100%" },
|
|
17443
|
+
children: /* @__PURE__ */ jsx(
|
|
17444
|
+
VideoCard,
|
|
17445
|
+
{
|
|
17446
|
+
workspace,
|
|
17447
|
+
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name),
|
|
17448
|
+
shouldPlay: isVisible,
|
|
17449
|
+
onClick: () => handleWorkspaceClick(workspace),
|
|
17450
|
+
onFatalError: throttledReloadDashboard,
|
|
17451
|
+
isVeryLowEfficiency
|
|
17452
|
+
}
|
|
17453
|
+
)
|
|
17454
|
+
},
|
|
17455
|
+
workspaceId
|
|
17456
|
+
);
|
|
17457
|
+
})
|
|
17458
|
+
}
|
|
17459
|
+
) }) });
|
|
17460
|
+
});
|
|
17461
|
+
VideoGridView.displayName = "VideoGridView";
|
|
17462
|
+
var defaults = {
|
|
17463
|
+
Card,
|
|
17464
|
+
CardHeader,
|
|
17465
|
+
CardTitle,
|
|
17466
|
+
CardDescription,
|
|
17467
|
+
CardContent,
|
|
17468
|
+
CardFooter,
|
|
17469
|
+
Button,
|
|
17470
|
+
HourlyOutputChart,
|
|
17471
|
+
VideoGridView
|
|
17472
|
+
};
|
|
17473
|
+
var RegistryCtx = createContext(defaults);
|
|
17474
|
+
var useRegistry = () => {
|
|
17475
|
+
const context = useContext(RegistryCtx);
|
|
17476
|
+
if (!context) {
|
|
17477
|
+
throw new Error("useRegistry must be used within a RegistryProvider");
|
|
17478
|
+
}
|
|
17479
|
+
return context;
|
|
17480
|
+
};
|
|
17481
|
+
function RegistryProvider({
|
|
17482
|
+
children,
|
|
17483
|
+
components = {}
|
|
17484
|
+
}) {
|
|
17485
|
+
if (process.env.NODE_ENV === "development") {
|
|
17486
|
+
const validKeys = Object.keys(defaults);
|
|
17487
|
+
Object.keys(components).forEach((key) => {
|
|
17488
|
+
if (!validKeys.includes(key)) {
|
|
17489
|
+
console.warn(`[RegistryProvider] Unknown component key: "${key}". Valid keys are: ${validKeys.join(", ")}`);
|
|
17490
|
+
}
|
|
17491
|
+
});
|
|
17492
|
+
}
|
|
17493
|
+
const mergedComponents = { ...defaults, ...components };
|
|
17494
|
+
return /* @__PURE__ */ jsx(RegistryCtx.Provider, { value: mergedComponents, children });
|
|
17495
|
+
}
|
|
17496
|
+
function withRegistry(Component3) {
|
|
17497
|
+
function WithRegistry(props) {
|
|
17498
|
+
useRegistry();
|
|
17499
|
+
return /* @__PURE__ */ jsx(Component3, { ...props });
|
|
17500
|
+
}
|
|
17501
|
+
WithRegistry.displayName = `withRegistry(${Component3.displayName || Component3.name})`;
|
|
17502
|
+
return WithRegistry;
|
|
17503
|
+
}
|
|
17504
|
+
var HourlyOutputChart2 = (props) => {
|
|
17505
|
+
const { HourlyOutputChart: RegisteredHourlyOutputChart } = useRegistry();
|
|
17506
|
+
return /* @__PURE__ */ jsx(RegisteredHourlyOutputChart, { ...props });
|
|
17507
|
+
};
|
|
17508
|
+
var HourlyComplianceDot = (props) => {
|
|
17509
|
+
const { cx: cx2, cy, index, payload, targetCompliance } = props;
|
|
17510
|
+
const complianceValue = payload?.compliance;
|
|
17511
|
+
if (typeof index !== "number" || index % 60 !== 0 || typeof complianceValue !== "number" || complianceValue === null) {
|
|
17512
|
+
return null;
|
|
17513
|
+
}
|
|
17514
|
+
const roundedValue = Math.round(complianceValue);
|
|
17515
|
+
const isAboveTarget = roundedValue >= targetCompliance;
|
|
17516
|
+
const labelColor = isAboveTarget ? "#10B981" : "#EF4444";
|
|
17517
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
17518
|
+
/* @__PURE__ */ jsx("circle", { cx: cx2, cy, r: 4, fill: "#EF4444" }),
|
|
17519
|
+
" ",
|
|
17520
|
+
/* @__PURE__ */ jsx(
|
|
17521
|
+
"text",
|
|
17522
|
+
{
|
|
17523
|
+
x: cx2,
|
|
17524
|
+
y: cy ? cy - 10 : 0,
|
|
17525
|
+
dy: 0,
|
|
17526
|
+
textAnchor: "middle",
|
|
17527
|
+
fill: labelColor,
|
|
17528
|
+
fontSize: 12,
|
|
17529
|
+
fontWeight: 600,
|
|
17530
|
+
children: `${roundedValue}%`
|
|
17531
|
+
}
|
|
17532
|
+
)
|
|
17533
|
+
] });
|
|
17534
|
+
};
|
|
17535
|
+
var SOPComplianceChart = ({
|
|
17536
|
+
data = [],
|
|
17537
|
+
targetCompliance = 95,
|
|
17538
|
+
shiftStart,
|
|
17539
|
+
className = ""
|
|
17540
|
+
}) => {
|
|
17541
|
+
const getHourFromTimeString = (timeStr) => {
|
|
17542
|
+
const [hours, minutes] = timeStr.split(":");
|
|
17543
|
+
return parseInt(hours);
|
|
17544
|
+
};
|
|
17545
|
+
const shiftStartHour = getHourFromTimeString(shiftStart);
|
|
17546
|
+
const SHIFT_DURATION_HOURS = 9;
|
|
17547
|
+
const MINUTES_PER_HOUR = 60;
|
|
17548
|
+
const TOTAL_MINUTES = SHIFT_DURATION_HOURS * MINUTES_PER_HOUR;
|
|
17549
|
+
const mockData = Array.from(
|
|
17550
|
+
{ length: TOTAL_MINUTES },
|
|
17551
|
+
() => Math.floor(Math.random() * 10) + 90
|
|
17552
|
+
);
|
|
17553
|
+
const [animatedData, setAnimatedData] = useState([]);
|
|
17554
|
+
const prevDataRef = useRef([]);
|
|
17555
|
+
const animationFrameRef = useRef(null);
|
|
17556
|
+
const animateToNewData = useCallback((targetData) => {
|
|
17557
|
+
const startData = [...prevDataRef.current];
|
|
17558
|
+
while (startData.length < targetData.length) {
|
|
17559
|
+
startData.push(startData.length > 0 ? startData[startData.length - 1] : 0);
|
|
17560
|
+
}
|
|
17561
|
+
const startTime = performance.now();
|
|
17562
|
+
const duration = 400;
|
|
17563
|
+
const animate = (currentTime) => {
|
|
17564
|
+
const elapsed = currentTime - startTime;
|
|
17565
|
+
const progress6 = Math.min(elapsed / duration, 1);
|
|
17566
|
+
const easeOutQuad = (t) => 1 - (1 - t) * (1 - t);
|
|
17567
|
+
const easedProgress = easeOutQuad(progress6);
|
|
17568
|
+
const newData = startData.map((start, index) => {
|
|
17569
|
+
if (index >= targetData.length) return start;
|
|
17570
|
+
const target = targetData[index];
|
|
17571
|
+
const change = target - start;
|
|
17572
|
+
return start + change * easedProgress;
|
|
17573
|
+
});
|
|
17574
|
+
setAnimatedData(newData);
|
|
17575
|
+
prevDataRef.current = newData;
|
|
17576
|
+
if (progress6 < 1) {
|
|
17577
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
17578
|
+
} else {
|
|
17579
|
+
setAnimatedData(targetData);
|
|
17580
|
+
prevDataRef.current = targetData;
|
|
17581
|
+
}
|
|
17582
|
+
};
|
|
17583
|
+
if (animationFrameRef.current) {
|
|
17584
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
17585
|
+
}
|
|
17586
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
17587
|
+
}, []);
|
|
17588
|
+
useEffect(() => {
|
|
17589
|
+
if (data.length === 0) {
|
|
17590
|
+
if (prevDataRef.current.length === 0) {
|
|
17591
|
+
animateToNewData(mockData);
|
|
17592
|
+
}
|
|
17593
|
+
return;
|
|
17594
|
+
}
|
|
17595
|
+
const actualData = [...data];
|
|
17596
|
+
if (JSON.stringify(actualData) !== JSON.stringify(prevDataRef.current)) {
|
|
17597
|
+
animateToNewData(actualData);
|
|
17598
|
+
}
|
|
17599
|
+
return () => {
|
|
17600
|
+
if (animationFrameRef.current) {
|
|
17601
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
17602
|
+
}
|
|
17603
|
+
};
|
|
17604
|
+
}, [data, animateToNewData, mockData]);
|
|
17605
|
+
const formatTime2 = (minuteIndex) => {
|
|
17606
|
+
const totalMinutes = shiftStartHour * 60 + minuteIndex;
|
|
17607
|
+
const hours = Math.floor(totalMinutes / 60) % 24;
|
|
17608
|
+
const minutes = totalMinutes % 60;
|
|
17609
|
+
const formattedHour = hours === 0 ? 12 : hours > 12 ? hours - 12 : hours;
|
|
17610
|
+
const ampm = hours >= 12 ? "PM" : "AM";
|
|
17611
|
+
return `${formattedHour}:${minutes.toString().padStart(2, "0")} ${ampm}`;
|
|
17057
17612
|
};
|
|
17058
17613
|
const chartData = Array.from({ length: TOTAL_MINUTES }, (_, index) => {
|
|
17059
17614
|
const hasDataForMinute = index < animatedData.length - 10;
|
|
@@ -17321,7 +17876,7 @@ var EmptyStateMessage = ({
|
|
|
17321
17876
|
iconClassName
|
|
17322
17877
|
}) => {
|
|
17323
17878
|
let IconContent = null;
|
|
17324
|
-
if (
|
|
17879
|
+
if (React14__default.isValidElement(iconType)) {
|
|
17325
17880
|
IconContent = iconType;
|
|
17326
17881
|
} else if (typeof iconType === "string") {
|
|
17327
17882
|
const MappedIcon = IconMap[iconType];
|
|
@@ -17420,11 +17975,6 @@ var BreakNotificationPopup = ({
|
|
|
17420
17975
|
}, 6e4);
|
|
17421
17976
|
return () => clearInterval(timer);
|
|
17422
17977
|
}, []);
|
|
17423
|
-
useEffect(() => {
|
|
17424
|
-
if (activeBreaks.length > 0) {
|
|
17425
|
-
setIsDismissed(false);
|
|
17426
|
-
}
|
|
17427
|
-
}, [activeBreaks]);
|
|
17428
17978
|
const handleDismiss = () => {
|
|
17429
17979
|
setIsDismissed(true);
|
|
17430
17980
|
onDismiss?.();
|
|
@@ -17447,57 +17997,54 @@ var BreakNotificationPopup = ({
|
|
|
17447
17997
|
animate: { opacity: 1, x: 0, y: 0 },
|
|
17448
17998
|
exit: { opacity: 0, x: 100, y: -20 },
|
|
17449
17999
|
transition: { duration: 0.3, ease: "easeOut" },
|
|
17450
|
-
className: `fixed top-
|
|
17451
|
-
children: /* @__PURE__ */
|
|
17452
|
-
|
|
17453
|
-
|
|
17454
|
-
{
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17458
|
-
|
|
17459
|
-
|
|
17460
|
-
/* @__PURE__ */
|
|
17461
|
-
|
|
17462
|
-
/* @__PURE__ */
|
|
17463
|
-
|
|
17464
|
-
|
|
17465
|
-
|
|
17466
|
-
|
|
17467
|
-
|
|
17468
|
-
|
|
17469
|
-
|
|
17470
|
-
|
|
17471
|
-
|
|
17472
|
-
|
|
17473
|
-
|
|
17474
|
-
|
|
17475
|
-
|
|
17476
|
-
|
|
17477
|
-
|
|
17478
|
-
|
|
17479
|
-
|
|
17480
|
-
width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
|
|
17481
|
-
}
|
|
18000
|
+
className: `fixed top-24 right-4 z-50 max-w-xs w-full ${className}`,
|
|
18001
|
+
children: /* @__PURE__ */ jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: activeBreaks.map((breakItem, index) => /* @__PURE__ */ jsx(
|
|
18002
|
+
motion.div,
|
|
18003
|
+
{
|
|
18004
|
+
initial: { opacity: 0, y: 20 },
|
|
18005
|
+
animate: { opacity: 1, y: 0 },
|
|
18006
|
+
transition: { delay: index * 0.1 },
|
|
18007
|
+
className: `p-3 ${index > 0 ? "border-t border-gray-100" : ""}`,
|
|
18008
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
|
|
18009
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 flex-1", children: [
|
|
18010
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-amber-500 rounded-full animate-pulse flex-shrink-0 mt-2" }),
|
|
18011
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
18012
|
+
/* @__PURE__ */ jsx("div", { className: "mb-1", children: /* @__PURE__ */ jsx("h4", { className: "font-semibold text-sm text-gray-900", children: breakItem.remarks || "Break" }) }),
|
|
18013
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-600 font-medium", children: [
|
|
18014
|
+
breakItem.startTime,
|
|
18015
|
+
" - ",
|
|
18016
|
+
breakItem.endTime
|
|
18017
|
+
] }) }),
|
|
18018
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxs("div", { className: "text-xs text-gray-500", children: [
|
|
18019
|
+
formatTime2(breakItem.elapsedMinutes),
|
|
18020
|
+
" / ",
|
|
18021
|
+
breakItem.duration,
|
|
18022
|
+
" min"
|
|
18023
|
+
] }) }),
|
|
18024
|
+
/* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsx(
|
|
18025
|
+
"div",
|
|
18026
|
+
{
|
|
18027
|
+
className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
|
|
18028
|
+
style: {
|
|
18029
|
+
width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
|
|
17482
18030
|
}
|
|
17483
|
-
|
|
17484
|
-
|
|
17485
|
-
] })
|
|
17486
|
-
|
|
17487
|
-
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17493
|
-
}
|
|
17494
|
-
|
|
17495
|
-
|
|
17496
|
-
}
|
|
17497
|
-
|
|
17498
|
-
|
|
17499
|
-
|
|
17500
|
-
] })
|
|
18031
|
+
}
|
|
18032
|
+
) }) })
|
|
18033
|
+
] })
|
|
18034
|
+
] }),
|
|
18035
|
+
index === 0 && /* @__PURE__ */ jsx(
|
|
18036
|
+
"button",
|
|
18037
|
+
{
|
|
18038
|
+
onClick: handleDismiss,
|
|
18039
|
+
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-1 rounded-full hover:bg-gray-100",
|
|
18040
|
+
"aria-label": "Dismiss notification",
|
|
18041
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-3 h-3" })
|
|
18042
|
+
}
|
|
18043
|
+
)
|
|
18044
|
+
] })
|
|
18045
|
+
},
|
|
18046
|
+
`${breakItem.lineId}-${breakItem.startTime}-${index}`
|
|
18047
|
+
)) })
|
|
17501
18048
|
}
|
|
17502
18049
|
) });
|
|
17503
18050
|
};
|
|
@@ -19887,7 +20434,7 @@ function Skeleton({ className, ...props }) {
|
|
|
19887
20434
|
var Select = SelectPrimitive.Root;
|
|
19888
20435
|
var SelectGroup = SelectPrimitive.Group;
|
|
19889
20436
|
var SelectValue = SelectPrimitive.Value;
|
|
19890
|
-
var SelectTrigger =
|
|
20437
|
+
var SelectTrigger = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
19891
20438
|
SelectPrimitive.Trigger,
|
|
19892
20439
|
{
|
|
19893
20440
|
ref,
|
|
@@ -19903,7 +20450,7 @@ var SelectTrigger = React33.forwardRef(({ className, children, ...props }, ref)
|
|
|
19903
20450
|
}
|
|
19904
20451
|
));
|
|
19905
20452
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
19906
|
-
var SelectScrollUpButton =
|
|
20453
|
+
var SelectScrollUpButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19907
20454
|
SelectPrimitive.ScrollUpButton,
|
|
19908
20455
|
{
|
|
19909
20456
|
ref,
|
|
@@ -19913,7 +20460,7 @@ var SelectScrollUpButton = React33.forwardRef(({ className, ...props }, ref) =>
|
|
|
19913
20460
|
}
|
|
19914
20461
|
));
|
|
19915
20462
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
19916
|
-
var SelectScrollDownButton =
|
|
20463
|
+
var SelectScrollDownButton = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19917
20464
|
SelectPrimitive.ScrollDownButton,
|
|
19918
20465
|
{
|
|
19919
20466
|
ref,
|
|
@@ -19923,7 +20470,7 @@ var SelectScrollDownButton = React33.forwardRef(({ className, ...props }, ref) =
|
|
|
19923
20470
|
}
|
|
19924
20471
|
));
|
|
19925
20472
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
19926
|
-
var SelectContent =
|
|
20473
|
+
var SelectContent = React14.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
19927
20474
|
SelectPrimitive.Content,
|
|
19928
20475
|
{
|
|
19929
20476
|
ref,
|
|
@@ -19951,7 +20498,7 @@ var SelectContent = React33.forwardRef(({ className, children, position = "poppe
|
|
|
19951
20498
|
}
|
|
19952
20499
|
) }));
|
|
19953
20500
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
19954
|
-
var SelectLabel =
|
|
20501
|
+
var SelectLabel = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19955
20502
|
SelectPrimitive.Label,
|
|
19956
20503
|
{
|
|
19957
20504
|
ref,
|
|
@@ -19960,7 +20507,7 @@ var SelectLabel = React33.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
19960
20507
|
}
|
|
19961
20508
|
));
|
|
19962
20509
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
19963
|
-
var SelectItem =
|
|
20510
|
+
var SelectItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
19964
20511
|
SelectPrimitive.Item,
|
|
19965
20512
|
{
|
|
19966
20513
|
ref,
|
|
@@ -19976,7 +20523,7 @@ var SelectItem = React33.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
19976
20523
|
}
|
|
19977
20524
|
));
|
|
19978
20525
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
19979
|
-
var SelectSeparator =
|
|
20526
|
+
var SelectSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
19980
20527
|
SelectPrimitive.Separator,
|
|
19981
20528
|
{
|
|
19982
20529
|
ref,
|
|
@@ -21686,352 +22233,29 @@ var BottlenecksContent = ({
|
|
|
21686
22233
|
handlePrevious();
|
|
21687
22234
|
},
|
|
21688
22235
|
disabled: currentIndex === 0 || filteredVideos.length === 0,
|
|
21689
|
-
className: `absolute left-4 top-1/2 -translate-y-1/2 z-[102] p-3 rounded-full bg-black/30 hover:bg-black/50 text-white transition-all ${currentIndex === 0 ? "opacity-30 cursor-not-allowed" : ""}`,
|
|
21690
|
-
"aria-label": "Previous video",
|
|
21691
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-7 w-7" })
|
|
21692
|
-
}
|
|
21693
|
-
),
|
|
21694
|
-
/* @__PURE__ */ jsx(
|
|
21695
|
-
"button",
|
|
21696
|
-
{
|
|
21697
|
-
onClick: (e) => {
|
|
21698
|
-
e.stopPropagation();
|
|
21699
|
-
handleNext();
|
|
21700
|
-
},
|
|
21701
|
-
disabled: currentIndex === filteredVideos.length - 1 || filteredVideos.length === 0,
|
|
21702
|
-
className: `absolute right-4 top-1/2 -translate-y-1/2 z-[102] p-3 rounded-full bg-black/30 hover:bg-black/50 text-white transition-all ${currentIndex === filteredVideos.length - 1 ? "opacity-30 cursor-not-allowed" : ""}`,
|
|
21703
|
-
"aria-label": "Next video",
|
|
21704
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-7 w-7" })
|
|
21705
|
-
}
|
|
21706
|
-
)
|
|
21707
|
-
]
|
|
21708
|
-
}
|
|
21709
|
-
)
|
|
21710
|
-
] });
|
|
21711
|
-
};
|
|
21712
|
-
var TREND_STYLES = {
|
|
21713
|
-
0: { arrow: "\u2193", color: "text-red-500 font-bold text-shadow" },
|
|
21714
|
-
// Down
|
|
21715
|
-
1: { arrow: "\u2013", color: "text-gray-500 font-bold text-shadow" },
|
|
21716
|
-
// Unchanged
|
|
21717
|
-
2: { arrow: "\u2191", color: "text-green-500 font-bold text-shadow" }
|
|
21718
|
-
// Up
|
|
21719
|
-
};
|
|
21720
|
-
var getTrendArrowAndColor = (trend) => TREND_STYLES[trend] || { arrow: "", color: "" };
|
|
21721
|
-
var VideoCard = React33__default.memo(({
|
|
21722
|
-
workspace,
|
|
21723
|
-
hlsUrl,
|
|
21724
|
-
shouldPlay,
|
|
21725
|
-
onClick,
|
|
21726
|
-
onFatalError,
|
|
21727
|
-
isVeryLowEfficiency = false,
|
|
21728
|
-
className = ""
|
|
21729
|
-
}) => {
|
|
21730
|
-
const videoRef = useRef(null);
|
|
21731
|
-
useHlsStream(videoRef, {
|
|
21732
|
-
src: hlsUrl,
|
|
21733
|
-
shouldPlay,
|
|
21734
|
-
onFatalError: onFatalError ?? (() => throttledReloadDashboard())
|
|
21735
|
-
});
|
|
21736
|
-
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
21737
|
-
workspace.workspace_uuid || workspace.workspace_name;
|
|
21738
|
-
const getEfficiencyOverlayColor = (efficiency) => {
|
|
21739
|
-
if (efficiency >= 80) {
|
|
21740
|
-
return "bg-[#00D654]/25";
|
|
21741
|
-
} else if (efficiency >= 70) {
|
|
21742
|
-
return "bg-[#FFD700]/30";
|
|
21743
|
-
} else {
|
|
21744
|
-
return "bg-[#FF2D0A]/30";
|
|
21745
|
-
}
|
|
21746
|
-
};
|
|
21747
|
-
const getEfficiencyBarColor = (efficiency) => {
|
|
21748
|
-
if (efficiency >= 80) {
|
|
21749
|
-
return "bg-[#00AB45]";
|
|
21750
|
-
} else if (efficiency >= 70) {
|
|
21751
|
-
return "bg-[#FFB020]";
|
|
21752
|
-
} else {
|
|
21753
|
-
return "bg-[#E34329]";
|
|
21754
|
-
}
|
|
21755
|
-
};
|
|
21756
|
-
const efficiencyOverlayClass = getEfficiencyOverlayColor(workspace.efficiency);
|
|
21757
|
-
const efficiencyBarClass = getEfficiencyBarColor(workspace.efficiency);
|
|
21758
|
-
const trendInfo = workspace.trend !== void 0 ? getTrendArrowAndColor(workspace.trend) : null;
|
|
21759
|
-
const handleClick = useCallback(() => {
|
|
21760
|
-
if (onClick) {
|
|
21761
|
-
onClick();
|
|
21762
|
-
}
|
|
21763
|
-
}, [onClick]);
|
|
21764
|
-
return /* @__PURE__ */ jsxs(
|
|
21765
|
-
"div",
|
|
21766
|
-
{
|
|
21767
|
-
className: `workspace-card relative bg-gray-950 rounded-md overflow-hidden cursor-pointer transform hover:scale-[1.005] transition-transform duration-200 shadow-sm ${className}`,
|
|
21768
|
-
style: { width: "100%", height: "100%" },
|
|
21769
|
-
onClick: handleClick,
|
|
21770
|
-
title: displayName,
|
|
21771
|
-
tabIndex: 0,
|
|
21772
|
-
"aria-label": `Open workspace ${displayName}`,
|
|
21773
|
-
onKeyDown: (e) => {
|
|
21774
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
21775
|
-
e.preventDefault();
|
|
21776
|
-
handleClick();
|
|
21777
|
-
}
|
|
21778
|
-
},
|
|
21779
|
-
children: [
|
|
21780
|
-
isVeryLowEfficiency && /* @__PURE__ */ jsx("div", { className: "absolute top-1 left-2 z-30", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
21781
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -inset-1 bg-red-400/50 rounded-full blur-sm animate-pulse" }),
|
|
21782
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -inset-0.5 bg-red-500/30 rounded-full blur-md animate-ping [animation-duration:1.5s]" }),
|
|
21783
|
-
/* @__PURE__ */ jsx("div", { className: "bg-[#E34329] w-5 h-5 rounded-full flex items-center justify-center text-white font-bold text-xs shadow-lg ring-2 ring-red-400/40 border border-red-400/80 animate-pulse", children: "!" })
|
|
21784
|
-
] }) }),
|
|
21785
|
-
/* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden bg-black", children: [
|
|
21786
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black z-0", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse flex flex-col items-center", children: [
|
|
21787
|
-
/* @__PURE__ */ jsx(Camera, { className: "w-6 h-6 text-gray-500" }),
|
|
21788
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs text-gray-500 mt-1", children: "Loading..." })
|
|
21789
|
-
] }) }),
|
|
21790
|
-
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10", children: /* @__PURE__ */ jsx(
|
|
21791
|
-
"video",
|
|
21792
|
-
{
|
|
21793
|
-
ref: videoRef,
|
|
21794
|
-
className: "h-full w-full object-cover",
|
|
21795
|
-
playsInline: true,
|
|
21796
|
-
muted: true,
|
|
21797
|
-
disablePictureInPicture: true,
|
|
21798
|
-
controlsList: "nodownload noplaybackrate"
|
|
22236
|
+
className: `absolute left-4 top-1/2 -translate-y-1/2 z-[102] p-3 rounded-full bg-black/30 hover:bg-black/50 text-white transition-all ${currentIndex === 0 ? "opacity-30 cursor-not-allowed" : ""}`,
|
|
22237
|
+
"aria-label": "Previous video",
|
|
22238
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-7 w-7" })
|
|
21799
22239
|
}
|
|
21800
|
-
)
|
|
21801
|
-
/* @__PURE__ */ jsx(
|
|
21802
|
-
|
|
21803
|
-
Math.round(workspace.efficiency),
|
|
21804
|
-
"%"
|
|
21805
|
-
] }),
|
|
21806
|
-
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 h-1 bg-black/50 z-30", children: /* @__PURE__ */ jsx(
|
|
21807
|
-
"div",
|
|
22240
|
+
),
|
|
22241
|
+
/* @__PURE__ */ jsx(
|
|
22242
|
+
"button",
|
|
21808
22243
|
{
|
|
21809
|
-
|
|
21810
|
-
|
|
22244
|
+
onClick: (e) => {
|
|
22245
|
+
e.stopPropagation();
|
|
22246
|
+
handleNext();
|
|
22247
|
+
},
|
|
22248
|
+
disabled: currentIndex === filteredVideos.length - 1 || filteredVideos.length === 0,
|
|
22249
|
+
className: `absolute right-4 top-1/2 -translate-y-1/2 z-[102] p-3 rounded-full bg-black/30 hover:bg-black/50 text-white transition-all ${currentIndex === filteredVideos.length - 1 ? "opacity-30 cursor-not-allowed" : ""}`,
|
|
22250
|
+
"aria-label": "Next video",
|
|
22251
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-7 w-7" })
|
|
21811
22252
|
}
|
|
21812
|
-
)
|
|
21813
|
-
]
|
|
21814
|
-
/* @__PURE__ */ jsxs("div", { className: "absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 p-1.5 flex justify-between items-center z-10", children: [
|
|
21815
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
21816
|
-
/* @__PURE__ */ jsx(Camera, { size: 12, className: "text-white" }),
|
|
21817
|
-
/* @__PURE__ */ jsx("p", { className: "text-white text-xs font-medium tracking-wide", children: displayName })
|
|
21818
|
-
] }),
|
|
21819
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
21820
|
-
trendInfo && /* @__PURE__ */ jsx(
|
|
21821
|
-
"div",
|
|
21822
|
-
{
|
|
21823
|
-
className: `text-lg ${trendInfo.color}`,
|
|
21824
|
-
style: { lineHeight: 1, display: "flex", alignItems: "center" },
|
|
21825
|
-
children: trendInfo.arrow
|
|
21826
|
-
}
|
|
21827
|
-
),
|
|
21828
|
-
/* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-green-500" }),
|
|
21829
|
-
/* @__PURE__ */ jsx("span", { className: "text-white text-xs", children: "Live" })
|
|
21830
|
-
] })
|
|
21831
|
-
] })
|
|
21832
|
-
]
|
|
21833
|
-
}
|
|
21834
|
-
);
|
|
21835
|
-
}, (prevProps, nextProps) => {
|
|
21836
|
-
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay;
|
|
21837
|
-
});
|
|
21838
|
-
VideoCard.displayName = "VideoCard";
|
|
21839
|
-
var DEFAULT_WORKSPACE_HLS_URLS = {
|
|
21840
|
-
"WS1": "https://dnh-hls.optifye.ai/cam1/index.m3u8",
|
|
21841
|
-
"WS2": "https://dnh-hls.optifye.ai/cam2/index.m3u8",
|
|
21842
|
-
"WS3": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
21843
|
-
"WS4": "https://dnh-hls.optifye.ai/cam3/index.m3u8",
|
|
21844
|
-
"WS01": "https://59.144.218.58:8443/camera6.m3u8",
|
|
21845
|
-
"WS02": "https://59.144.218.58:8443/camera2.m3u8",
|
|
21846
|
-
"WS03": "https://59.144.218.58:8443/camera3.m3u8",
|
|
21847
|
-
"WS04": "https://59.144.218.58:8443/camera4.m3u8",
|
|
21848
|
-
"WS05": "https://59.144.218.58:8443/camera1.m3u8",
|
|
21849
|
-
"WS06": "https://59.144.218.58:8443/camera5.m3u8"
|
|
21850
|
-
};
|
|
21851
|
-
var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
|
|
21852
|
-
var VideoGridView = React33__default.memo(({
|
|
21853
|
-
workspaces,
|
|
21854
|
-
selectedLine,
|
|
21855
|
-
className = "",
|
|
21856
|
-
lineIdMapping = {},
|
|
21857
|
-
videoSources = {}
|
|
21858
|
-
}) => {
|
|
21859
|
-
const router = useRouter();
|
|
21860
|
-
const containerRef = useRef(null);
|
|
21861
|
-
const observerRef = useRef(null);
|
|
21862
|
-
const [gridCols, setGridCols] = useState(4);
|
|
21863
|
-
const [visibleWorkspaces, setVisibleWorkspaces] = useState(/* @__PURE__ */ new Set());
|
|
21864
|
-
const mergedVideoSources = {
|
|
21865
|
-
defaultHlsUrl: videoSources.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
21866
|
-
workspaceHlsUrls: { ...DEFAULT_WORKSPACE_HLS_URLS, ...videoSources.workspaceHlsUrls }
|
|
21867
|
-
};
|
|
21868
|
-
const getWorkspaceHlsUrl = useCallback((workspaceName) => {
|
|
21869
|
-
const wsName = workspaceName.toUpperCase();
|
|
21870
|
-
return mergedVideoSources.workspaceHlsUrls[wsName] || mergedVideoSources.defaultHlsUrl;
|
|
21871
|
-
}, [mergedVideoSources]);
|
|
21872
|
-
const veryLowEfficiencyWorkspaces = useMemo(() => {
|
|
21873
|
-
return new Set(
|
|
21874
|
-
workspaces.filter((w) => w.efficiency < 50 && w.efficiency >= 10).map((w) => w.workspace_name)
|
|
21875
|
-
);
|
|
21876
|
-
}, [workspaces]);
|
|
21877
|
-
const filteredWorkspaces = useMemo(() => {
|
|
21878
|
-
return selectedLine === 1 ? workspaces.filter((w) => {
|
|
21879
|
-
if (w.workspace_name === "WS5-5") return true;
|
|
21880
|
-
if (w.workspace_name === "WS32-5") return false;
|
|
21881
|
-
try {
|
|
21882
|
-
const wsNumber = parseInt(w.workspace_name.replace("WS", ""));
|
|
21883
|
-
return wsNumber >= 1 && wsNumber <= 22;
|
|
21884
|
-
} catch {
|
|
21885
|
-
return true;
|
|
21886
|
-
}
|
|
21887
|
-
}) : selectedLine === 2 ? workspaces.filter((w) => {
|
|
21888
|
-
if (w.workspace_name === "WS5-5") return false;
|
|
21889
|
-
if (w.workspace_name === "WS32-5") return true;
|
|
21890
|
-
try {
|
|
21891
|
-
const wsNumber = parseInt(w.workspace_name.replace("WS", ""));
|
|
21892
|
-
return wsNumber >= 23 && wsNumber <= 44;
|
|
21893
|
-
} catch {
|
|
21894
|
-
return false;
|
|
21895
|
-
}
|
|
21896
|
-
}) : workspaces;
|
|
21897
|
-
}, [workspaces, selectedLine]);
|
|
21898
|
-
const calculateOptimalGrid = useCallback(() => {
|
|
21899
|
-
if (!containerRef.current) return;
|
|
21900
|
-
const containerPadding = 16;
|
|
21901
|
-
const containerWidth = containerRef.current.clientWidth - containerPadding;
|
|
21902
|
-
const containerHeight = containerRef.current.clientHeight - containerPadding;
|
|
21903
|
-
const count = filteredWorkspaces.length;
|
|
21904
|
-
if (count === 0) {
|
|
21905
|
-
setGridCols(1);
|
|
21906
|
-
return;
|
|
21907
|
-
}
|
|
21908
|
-
let bestCols = 1;
|
|
21909
|
-
let bestScore = 0;
|
|
21910
|
-
const targetAspectRatio = 16 / 9;
|
|
21911
|
-
const gap = 8;
|
|
21912
|
-
const maxCols = Math.min(count, 6);
|
|
21913
|
-
for (let cols = 1; cols <= maxCols; cols++) {
|
|
21914
|
-
const rows = Math.ceil(count / cols);
|
|
21915
|
-
const availableWidth = containerWidth - gap * (cols - 1);
|
|
21916
|
-
const availableHeight = containerHeight - gap * (rows - 1);
|
|
21917
|
-
const cellWidth = availableWidth / cols;
|
|
21918
|
-
const cellHeight = availableHeight / rows;
|
|
21919
|
-
const minCellWidth = containerWidth < 800 ? 120 : 150;
|
|
21920
|
-
const minCellHeight = containerHeight < 600 ? 80 : 100;
|
|
21921
|
-
if (cellWidth < minCellWidth || cellHeight < minCellHeight) continue;
|
|
21922
|
-
const totalUsedArea = cellWidth * cellHeight * count;
|
|
21923
|
-
const totalAvailableArea = containerWidth * containerHeight;
|
|
21924
|
-
const spaceUtilization = totalUsedArea / totalAvailableArea;
|
|
21925
|
-
const actualAspectRatio = cellWidth / cellHeight;
|
|
21926
|
-
const aspectRatioScore = 1 / (1 + Math.abs(actualAspectRatio - targetAspectRatio) * 0.3);
|
|
21927
|
-
const score = spaceUtilization * 0.9 + aspectRatioScore * 0.1;
|
|
21928
|
-
if (score > bestScore) {
|
|
21929
|
-
bestScore = score;
|
|
21930
|
-
bestCols = cols;
|
|
22253
|
+
)
|
|
22254
|
+
]
|
|
21931
22255
|
}
|
|
21932
|
-
|
|
21933
|
-
|
|
21934
|
-
|
|
21935
|
-
}
|
|
21936
|
-
setGridCols(bestCols);
|
|
21937
|
-
}, [filteredWorkspaces.length]);
|
|
21938
|
-
useEffect(() => {
|
|
21939
|
-
calculateOptimalGrid();
|
|
21940
|
-
const handleResize = () => calculateOptimalGrid();
|
|
21941
|
-
window.addEventListener("resize", handleResize);
|
|
21942
|
-
return () => window.removeEventListener("resize", handleResize);
|
|
21943
|
-
}, [calculateOptimalGrid]);
|
|
21944
|
-
useEffect(() => {
|
|
21945
|
-
if (!containerRef.current) return;
|
|
21946
|
-
const options = {
|
|
21947
|
-
root: null,
|
|
21948
|
-
rootMargin: "50px",
|
|
21949
|
-
threshold: 0.1
|
|
21950
|
-
};
|
|
21951
|
-
observerRef.current = new IntersectionObserver((entries) => {
|
|
21952
|
-
entries.forEach((entry) => {
|
|
21953
|
-
const workspaceId = entry.target.getAttribute("data-workspace-id");
|
|
21954
|
-
if (!workspaceId) return;
|
|
21955
|
-
setVisibleWorkspaces((prev) => {
|
|
21956
|
-
const next = new Set(prev);
|
|
21957
|
-
if (entry.isIntersecting) {
|
|
21958
|
-
next.add(workspaceId);
|
|
21959
|
-
} else {
|
|
21960
|
-
next.delete(workspaceId);
|
|
21961
|
-
}
|
|
21962
|
-
return next;
|
|
21963
|
-
});
|
|
21964
|
-
});
|
|
21965
|
-
}, options);
|
|
21966
|
-
const elements = containerRef.current.querySelectorAll("[data-workspace-id]");
|
|
21967
|
-
elements.forEach((el) => observerRef.current?.observe(el));
|
|
21968
|
-
return () => {
|
|
21969
|
-
observerRef.current?.disconnect();
|
|
21970
|
-
};
|
|
21971
|
-
}, [filteredWorkspaces]);
|
|
21972
|
-
const handleWorkspaceClick = useCallback((workspace) => {
|
|
21973
|
-
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
21974
|
-
trackCoreEvent("Workspace Detail Clicked", {
|
|
21975
|
-
workspace_name: workspace.workspace_name,
|
|
21976
|
-
workspace_id: workspaceId,
|
|
21977
|
-
view_type: "video_grid",
|
|
21978
|
-
performance_score: workspace.performance_score,
|
|
21979
|
-
efficiency: workspace.efficiency,
|
|
21980
|
-
action_count: workspace.action_count
|
|
21981
|
-
});
|
|
21982
|
-
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
21983
|
-
const navParams = getWorkspaceNavigationParams(workspaceId, displayName);
|
|
21984
|
-
router.push(`/workspace/${workspaceId}${navParams}`);
|
|
21985
|
-
}, [router]);
|
|
21986
|
-
return /* @__PURE__ */ jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsx("div", { ref: containerRef, className: "h-full w-full p-2", children: /* @__PURE__ */ jsx(
|
|
21987
|
-
"div",
|
|
21988
|
-
{
|
|
21989
|
-
className: "grid h-full w-full gap-2",
|
|
21990
|
-
style: {
|
|
21991
|
-
gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
|
|
21992
|
-
gridTemplateRows: `repeat(${Math.ceil(filteredWorkspaces.length / gridCols)}, 1fr)`,
|
|
21993
|
-
minHeight: "100%"
|
|
21994
|
-
},
|
|
21995
|
-
children: filteredWorkspaces.sort((a, b) => {
|
|
21996
|
-
const aNum = parseInt(a.workspace_name.slice(2));
|
|
21997
|
-
const bNum = parseInt(b.workspace_name.slice(2));
|
|
21998
|
-
if (!selectedLine) {
|
|
21999
|
-
const aIsLine2 = a.line_id === lineIdMapping.line2;
|
|
22000
|
-
const bIsLine2 = b.line_id === lineIdMapping.line2;
|
|
22001
|
-
if (aIsLine2 !== bIsLine2) {
|
|
22002
|
-
return aIsLine2 ? 1 : -1;
|
|
22003
|
-
}
|
|
22004
|
-
}
|
|
22005
|
-
return aNum - bNum;
|
|
22006
|
-
}).map((workspace) => {
|
|
22007
|
-
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
22008
|
-
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
22009
|
-
const isVeryLowEfficiency = veryLowEfficiencyWorkspaces.has(workspace.workspace_name);
|
|
22010
|
-
return /* @__PURE__ */ jsx(
|
|
22011
|
-
"div",
|
|
22012
|
-
{
|
|
22013
|
-
"data-workspace-id": workspaceId,
|
|
22014
|
-
className: "workspace-card relative min-h-0 min-w-0",
|
|
22015
|
-
style: { width: "100%", height: "100%" },
|
|
22016
|
-
children: /* @__PURE__ */ jsx(
|
|
22017
|
-
VideoCard,
|
|
22018
|
-
{
|
|
22019
|
-
workspace,
|
|
22020
|
-
hlsUrl: getWorkspaceHlsUrl(workspace.workspace_name),
|
|
22021
|
-
shouldPlay: isVisible,
|
|
22022
|
-
onClick: () => handleWorkspaceClick(workspace),
|
|
22023
|
-
onFatalError: throttledReloadDashboard,
|
|
22024
|
-
isVeryLowEfficiency
|
|
22025
|
-
}
|
|
22026
|
-
)
|
|
22027
|
-
},
|
|
22028
|
-
workspaceId
|
|
22029
|
-
);
|
|
22030
|
-
})
|
|
22031
|
-
}
|
|
22032
|
-
) }) });
|
|
22033
|
-
});
|
|
22034
|
-
VideoGridView.displayName = "VideoGridView";
|
|
22256
|
+
)
|
|
22257
|
+
] });
|
|
22258
|
+
};
|
|
22035
22259
|
var getEfficiencyColor = (efficiency) => {
|
|
22036
22260
|
if (efficiency >= 80) {
|
|
22037
22261
|
return "bg-[#00AB45]/90 hover:bg-[#00AB45]/95";
|
|
@@ -22132,7 +22356,7 @@ var arePropsEqual = (prevProps, nextProps) => {
|
|
|
22132
22356
|
return prevProps.data.efficiency === nextProps.data.efficiency && prevProps.data.trend_score === nextProps.data.trend_score && prevProps.data.workspace_id === nextProps.data.workspace_id && prevProps.data.workspace_name === nextProps.data.workspace_name && prevProps.isBottleneck === nextProps.isBottleneck && prevProps.isLowEfficiency === nextProps.isLowEfficiency && prevProps.isVeryLowEfficiency === nextProps.isVeryLowEfficiency && // Position doesn't need deep equality check as it's generally static
|
|
22133
22357
|
prevProps.position.id === nextProps.position.id;
|
|
22134
22358
|
};
|
|
22135
|
-
var WorkspaceGridItem =
|
|
22359
|
+
var WorkspaceGridItem = React14__default.memo(({
|
|
22136
22360
|
data,
|
|
22137
22361
|
position,
|
|
22138
22362
|
isBottleneck = false,
|
|
@@ -22225,7 +22449,7 @@ var WorkspaceGridItem = React33__default.memo(({
|
|
|
22225
22449
|
);
|
|
22226
22450
|
}, arePropsEqual);
|
|
22227
22451
|
WorkspaceGridItem.displayName = "WorkspaceGridItem";
|
|
22228
|
-
var WorkspaceGrid =
|
|
22452
|
+
var WorkspaceGrid = React14__default.memo(({
|
|
22229
22453
|
workspaces,
|
|
22230
22454
|
isPdfMode = false,
|
|
22231
22455
|
customWorkspacePositions,
|
|
@@ -22241,13 +22465,14 @@ var WorkspaceGrid = React33__default.memo(({
|
|
|
22241
22465
|
total_workspaces: workspaces.length
|
|
22242
22466
|
});
|
|
22243
22467
|
}, [workspaces.length]);
|
|
22468
|
+
const { VideoGridView: VideoGridViewComponent } = useRegistry();
|
|
22244
22469
|
return /* @__PURE__ */ jsxs("div", { className: `relative w-full h-full overflow-hidden ${className}`, children: [
|
|
22245
22470
|
/* @__PURE__ */ jsxs("div", { className: "absolute top-0 left-2 sm:left-4 right-2 sm:right-8 z-20", children: [
|
|
22246
22471
|
/* @__PURE__ */ jsx("div", { className: "flex flex-row items-center justify-between py-1 sm:py-1.5 gap-2", children: /* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsx(Legend5, {}) }) }),
|
|
22247
22472
|
/* @__PURE__ */ jsx("div", { className: "sm:hidden mt-1", children: /* @__PURE__ */ jsx(Legend5, {}) })
|
|
22248
22473
|
] }),
|
|
22249
22474
|
/* @__PURE__ */ jsx("div", { className: "absolute top-10 sm:top-16 left-0 right-0 bottom-0", children: /* @__PURE__ */ jsx(
|
|
22250
|
-
|
|
22475
|
+
VideoGridViewComponent,
|
|
22251
22476
|
{
|
|
22252
22477
|
workspaces,
|
|
22253
22478
|
videoSources
|
|
@@ -22414,7 +22639,7 @@ var KPICard = ({
|
|
|
22414
22639
|
}) => {
|
|
22415
22640
|
useThemeConfig();
|
|
22416
22641
|
const { formatNumber } = useFormatNumber();
|
|
22417
|
-
const trendInfo =
|
|
22642
|
+
const trendInfo = React14__default.useMemo(() => {
|
|
22418
22643
|
let trendValue = trend || "neutral";
|
|
22419
22644
|
if (change !== void 0 && trend === void 0) {
|
|
22420
22645
|
trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
|
|
@@ -22437,7 +22662,7 @@ var KPICard = ({
|
|
|
22437
22662
|
const shouldShowTrend = !(change === 0 && trend === void 0);
|
|
22438
22663
|
return { trendValue, Icon: Icon2, colorClass, shouldShowTrend };
|
|
22439
22664
|
}, [trend, change]);
|
|
22440
|
-
const formattedValue =
|
|
22665
|
+
const formattedValue = React14__default.useMemo(() => {
|
|
22441
22666
|
if (title === "Quality Compliance" && typeof value === "number") {
|
|
22442
22667
|
return value.toFixed(1);
|
|
22443
22668
|
}
|
|
@@ -22451,7 +22676,7 @@ var KPICard = ({
|
|
|
22451
22676
|
}
|
|
22452
22677
|
return value;
|
|
22453
22678
|
}, [value, title]);
|
|
22454
|
-
const formattedChange =
|
|
22679
|
+
const formattedChange = React14__default.useMemo(() => {
|
|
22455
22680
|
if (change === void 0 || change === 0) return null;
|
|
22456
22681
|
const absChange = Math.abs(change);
|
|
22457
22682
|
return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
|
|
@@ -22863,7 +23088,7 @@ var Breadcrumbs = ({ items }) => {
|
|
|
22863
23088
|
}
|
|
22864
23089
|
}
|
|
22865
23090
|
};
|
|
22866
|
-
return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
23091
|
+
return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React14__default.Fragment, { children: [
|
|
22867
23092
|
index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
|
|
22868
23093
|
/* @__PURE__ */ jsxs(
|
|
22869
23094
|
"span",
|
|
@@ -23682,7 +23907,7 @@ var ThreadSidebar = ({
|
|
|
23682
23907
|
] });
|
|
23683
23908
|
};
|
|
23684
23909
|
var axelProfilePng = "/axel-profile.png";
|
|
23685
|
-
var ProfilePicture =
|
|
23910
|
+
var ProfilePicture = React14__default.memo(({ alt = "Axel", className = "w-12 h-12" }) => {
|
|
23686
23911
|
return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: `${className} rounded-xl overflow-hidden shadow-sm`, children: /* @__PURE__ */ jsx(
|
|
23687
23912
|
"img",
|
|
23688
23913
|
{
|
|
@@ -24412,7 +24637,7 @@ var AIAgentView = () => {
|
|
|
24412
24637
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
24413
24638
|
});
|
|
24414
24639
|
},
|
|
24415
|
-
placeholder: "Ask me about
|
|
24640
|
+
placeholder: "Ask me anything about your shop-floor",
|
|
24416
24641
|
className: "w-full resize-none bg-transparent px-2 py-2 pr-12 focus:outline-none placeholder-gray-500 text-gray-900 text-sm leading-relaxed",
|
|
24417
24642
|
rows: 1,
|
|
24418
24643
|
style: { minHeight: "24px", maxHeight: "120px" }
|
|
@@ -24587,7 +24812,7 @@ var AIAgentView = () => {
|
|
|
24587
24812
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
24588
24813
|
});
|
|
24589
24814
|
},
|
|
24590
|
-
placeholder: "Ask me about
|
|
24815
|
+
placeholder: "Ask me anything about your shop-floor",
|
|
24591
24816
|
className: "w-full resize-none bg-transparent px-2 py-2 pr-12 focus:outline-none placeholder-gray-500 text-gray-900 text-sm leading-relaxed",
|
|
24592
24817
|
rows: 1,
|
|
24593
24818
|
style: { minHeight: "24px", maxHeight: "120px" }
|
|
@@ -25547,6 +25772,24 @@ function HomeView({
|
|
|
25547
25772
|
const [selectedLineId, setSelectedLineId] = useState(defaultLineId);
|
|
25548
25773
|
const [isChangingFilter, setIsChangingFilter] = useState(false);
|
|
25549
25774
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
25775
|
+
const [displayNamesInitialized, setDisplayNamesInitialized] = useState(false);
|
|
25776
|
+
useEffect(() => {
|
|
25777
|
+
const initDisplayNames = async () => {
|
|
25778
|
+
try {
|
|
25779
|
+
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
25780
|
+
setDisplayNamesInitialized(true);
|
|
25781
|
+
} catch (error) {
|
|
25782
|
+
console.error("Failed to pre-initialize workspace display names:", error);
|
|
25783
|
+
setDisplayNamesInitialized(true);
|
|
25784
|
+
}
|
|
25785
|
+
};
|
|
25786
|
+
initDisplayNames();
|
|
25787
|
+
}, [selectedLineId]);
|
|
25788
|
+
const {
|
|
25789
|
+
displayNames: workspaceDisplayNames,
|
|
25790
|
+
loading: displayNamesLoading,
|
|
25791
|
+
error: displayNamesError
|
|
25792
|
+
} = useWorkspaceDisplayNames(void 0, selectedLineId);
|
|
25550
25793
|
useCallback(() => {
|
|
25551
25794
|
console.log("Refetching KPIs after line metrics update");
|
|
25552
25795
|
}, []);
|
|
@@ -25619,16 +25862,16 @@ function HomeView({
|
|
|
25619
25862
|
const lineTitle = useMemo(() => {
|
|
25620
25863
|
return factoryName;
|
|
25621
25864
|
}, [factoryName]);
|
|
25622
|
-
const isLoading = !isHydrated || metricsLoading || kpisLoading || isChangingFilter;
|
|
25865
|
+
const isLoading = !isHydrated || metricsLoading || kpisLoading || isChangingFilter || displayNamesLoading || !displayNamesInitialized;
|
|
25623
25866
|
if (isLoading) {
|
|
25624
25867
|
return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-slate-50", children: /* @__PURE__ */ jsx(LoadingPageCmp, { message: "Loading dashboard..." }) });
|
|
25625
25868
|
}
|
|
25626
|
-
if (errorMessage) {
|
|
25869
|
+
if (errorMessage || displayNamesError) {
|
|
25627
25870
|
return /* @__PURE__ */ jsx("div", { className: "flex h-screen items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-white p-6 shadow-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 text-red-500", children: [
|
|
25628
25871
|
/* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-6 w-6", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
25629
25872
|
/* @__PURE__ */ jsxs("span", { className: "text-lg font-medium", children: [
|
|
25630
25873
|
"Error: ",
|
|
25631
|
-
errorMessage
|
|
25874
|
+
errorMessage || displayNamesError?.message
|
|
25632
25875
|
] })
|
|
25633
25876
|
] }) }) });
|
|
25634
25877
|
}
|
|
@@ -25648,7 +25891,7 @@ function HomeView({
|
|
|
25648
25891
|
/* @__PURE__ */ jsx(DashboardHeader, { lineTitle, className: "mb-1 sm:mb-0" }),
|
|
25649
25892
|
memoizedKPIs && /* @__PURE__ */ jsx(KPISection2, { kpis: memoizedKPIs, className: "w-full sm:w-auto" })
|
|
25650
25893
|
] }) }),
|
|
25651
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden", children: memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children:
|
|
25894
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden", children: memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children: React14__default.createElement(WorkspaceGrid, {
|
|
25652
25895
|
workspaces: memoizedWorkspaceMetrics,
|
|
25653
25896
|
lineNames,
|
|
25654
25897
|
factoryView: factoryViewId,
|
|
@@ -25669,7 +25912,7 @@ function HomeView({
|
|
|
25669
25912
|
}
|
|
25670
25913
|
);
|
|
25671
25914
|
}
|
|
25672
|
-
var AuthenticatedHomeView = withAuth(
|
|
25915
|
+
var AuthenticatedHomeView = withAuth(React14__default.memo(HomeView));
|
|
25673
25916
|
var HomeView_default = HomeView;
|
|
25674
25917
|
|
|
25675
25918
|
// src/views/kpi-detail-view.types.ts
|
|
@@ -26502,7 +26745,7 @@ var LineCard = ({ line, onClick }) => {
|
|
|
26502
26745
|
const { kpis, isLoading, error } = useLineKPIs({ lineId: line.id });
|
|
26503
26746
|
const shiftConfig = useShiftConfig();
|
|
26504
26747
|
const dateTimeConfig = useDateTimeConfig();
|
|
26505
|
-
const isOnTrack =
|
|
26748
|
+
const isOnTrack = React14__default.useMemo(() => {
|
|
26506
26749
|
if (!kpis) return null;
|
|
26507
26750
|
const currentTime = /* @__PURE__ */ new Date();
|
|
26508
26751
|
const timezone = dateTimeConfig.defaultTimezone || "Asia/Kolkata";
|
|
@@ -30466,4 +30709,4 @@ var S3Service = class {
|
|
|
30466
30709
|
}
|
|
30467
30710
|
};
|
|
30468
30711
|
|
|
30469
|
-
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GridComponentsPlaceholder, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, ProfileView_default as ProfileView, RegistryProvider, S3Service, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
|
|
30712
|
+
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedTargetsView, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_THEME_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, EmptyStateMessage, FactoryView_default as FactoryView, GridComponentsPlaceholder, Header, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LiveTimer, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSpinner_default as LoadingSpinner, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, NoWorkspaceData, OptifyeAgentClient, OutputProgressChart, PageHeader, ProfileView_default as ProfileView, RegistryProvider, S3Service, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SingleVideoStream_default as SingleVideoStream, Skeleton, SlackAPI, SupabaseProvider, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TimeDisplay_default as TimeDisplay, TimePickerDropdown, VideoCard, VideoGridView, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceGrid, WorkspaceGridItem, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createStreamProxyHandler, createSupabaseClient, createThrottledReload, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultTabForWorkspace, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isTransitionPeriod, isValidLineInfoPayload, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, mergeWithDefaultConfig, optifyeAgentClient, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, s3VideoPreloader, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useActiveBreaks, useAnalyticsConfig, useAuth, useAuthConfig, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHookOverride, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, useRealtimeLineMetrics, useRegistry, useShiftConfig, useShifts, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, videoPreloader, whatsappService, withAuth, withRegistry, workspaceService };
|