@optifye/dashboard-core 6.6.10 → 6.6.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +40 -13
- package/dist/index.d.mts +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +591 -299
- package/dist/index.mjs +592 -301
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -13,7 +13,7 @@ import { noop, warning, invariant, progress, secondsToMilliseconds, milliseconds
|
|
|
13
13
|
import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
|
|
14
14
|
import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell, ReferenceLine, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
|
|
15
15
|
import { Slot } from '@radix-ui/react-slot';
|
|
16
|
-
import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, Minus, ArrowDown, ArrowUp, Settings2, CheckCircle2, Search, Loader2,
|
|
16
|
+
import { Camera, ChevronDown, ChevronUp, Check, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, Minus, ArrowDown, ArrowUp, Sparkles, AlertCircle, TrendingUp, Settings2, CheckCircle2, Search, Loader2, Edit2, CheckCircle, AlertTriangle, Info, Share2, Trophy, Target, Download, User, RefreshCw, Sliders, TrendingDown, FolderOpen, Folder, HelpCircle, Play, Activity, Layers, Filter, XCircle, ChevronLeft, ChevronRight, Sun, Moon, MousePointer, ArrowRight, MessageSquare, Trash2, Menu, Send, Copy, UserCheck, LogOut, Package, Building2, Settings, LifeBuoy, EyeOff, Eye, Zap, UserCircle } from 'lucide-react';
|
|
17
17
|
import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
|
|
18
18
|
import { XMarkIcon, ArrowRightIcon, HomeIcon, TrophyIcon, ChartBarIcon, AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, CubeIcon, SparklesIcon, QuestionMarkCircleIcon, HeartIcon, UserCircleIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, Bars3Icon, CheckCircleIcon, ChatBubbleLeftRightIcon, ArrowLeftIcon, XCircleIcon, InformationCircleIcon } from '@heroicons/react/24/outline';
|
|
19
19
|
import { CheckIcon } from '@heroicons/react/24/solid';
|
|
@@ -4014,12 +4014,8 @@ var S3ClipsSupabaseService = class {
|
|
|
4014
4014
|
id: clip.clip_id,
|
|
4015
4015
|
src: clip.playlist,
|
|
4016
4016
|
// Raw playlist content
|
|
4017
|
-
timestamp:
|
|
4018
|
-
|
|
4019
|
-
hour: "2-digit",
|
|
4020
|
-
minute: "2-digit",
|
|
4021
|
-
second: "2-digit"
|
|
4022
|
-
}),
|
|
4017
|
+
timestamp: clip.timestamp,
|
|
4018
|
+
// Use pre-formatted timestamp from API (already in 12-hour format with seconds)
|
|
4023
4019
|
severity: this.getSeverityFromClipType(clip.clip_type_name),
|
|
4024
4020
|
description: this.getDescriptionFromClipType(clip.clip_type_name),
|
|
4025
4021
|
type: clip.clip_type_name,
|
|
@@ -6515,6 +6511,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6515
6511
|
const lineIdRef = useRef(lineId);
|
|
6516
6512
|
const isFetchingRef = useRef(false);
|
|
6517
6513
|
const updateQueueRef = useRef(false);
|
|
6514
|
+
const onLineMetricsUpdateRef = useRef(onLineMetricsUpdate);
|
|
6515
|
+
useEffect(() => {
|
|
6516
|
+
onLineMetricsUpdateRef.current = onLineMetricsUpdate;
|
|
6517
|
+
}, [onLineMetricsUpdate]);
|
|
6518
6518
|
const companySpecificMetricsTable = useMemo(
|
|
6519
6519
|
() => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
|
|
6520
6520
|
[entityConfig.companyId]
|
|
@@ -6630,13 +6630,17 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6630
6630
|
defaultTimezone,
|
|
6631
6631
|
shiftConfig
|
|
6632
6632
|
]);
|
|
6633
|
+
const fetchAllMetricsRef = useRef(fetchAllMetrics);
|
|
6634
|
+
useEffect(() => {
|
|
6635
|
+
fetchAllMetricsRef.current = fetchAllMetrics;
|
|
6636
|
+
}, [fetchAllMetrics]);
|
|
6633
6637
|
const queueUpdate = useCallback(() => {
|
|
6634
6638
|
if (updateQueueRef.current || !supabase) {
|
|
6635
6639
|
return;
|
|
6636
6640
|
}
|
|
6637
6641
|
updateQueueRef.current = true;
|
|
6638
|
-
|
|
6639
|
-
}, [
|
|
6642
|
+
fetchAllMetricsRef.current();
|
|
6643
|
+
}, [supabase]);
|
|
6640
6644
|
useEffect(() => {
|
|
6641
6645
|
if (lineId && supabase) {
|
|
6642
6646
|
fetchAllMetrics();
|
|
@@ -6651,11 +6655,11 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6651
6655
|
const operationalDateForSubscription = getOperationalDate(defaultTimezone);
|
|
6652
6656
|
const targetLineIds = currentLineIdToUse === (entityConfig.factoryViewId || "factory") ? getConfiguredLineIds(entityConfig) : [currentLineIdToUse];
|
|
6653
6657
|
if (targetLineIds.length === 0) return;
|
|
6654
|
-
const wsMetricsFilter = `
|
|
6655
|
-
const lineMetricsFilter = `
|
|
6658
|
+
const wsMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
6659
|
+
const lineMetricsFilter = `line_id=in.(${targetLineIds.map((id3) => `"${id3}"`).join(",")})`;
|
|
6656
6660
|
const channels = [];
|
|
6657
6661
|
const createSubscription = (table, filter2, channelNameBase, callback) => {
|
|
6658
|
-
const channelName = `${channelNameBase}-${
|
|
6662
|
+
const channelName = `${channelNameBase}-${Date.now()}`.replace(/[^a-zA-Z0-9_-]/g, "");
|
|
6659
6663
|
const channel = supabase.channel(channelName).on(
|
|
6660
6664
|
"postgres_changes",
|
|
6661
6665
|
{ event: "*", schema, table, filter: filter2 },
|
|
@@ -6665,40 +6669,29 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
6665
6669
|
callback();
|
|
6666
6670
|
}
|
|
6667
6671
|
}
|
|
6668
|
-
).subscribe(
|
|
6669
|
-
if (status === REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR && err) {
|
|
6670
|
-
console.error(`[useDashboardMetrics] Subscription error for ${table} on ${currentLineIdToUse}:`, err.message);
|
|
6671
|
-
} else if (status === REALTIME_SUBSCRIBE_STATES.TIMED_OUT) {
|
|
6672
|
-
console.warn(`[useDashboardMetrics] Subscription timeout for ${table} on ${currentLineIdToUse}.`);
|
|
6673
|
-
}
|
|
6674
|
-
});
|
|
6672
|
+
).subscribe();
|
|
6675
6673
|
channels.push(channel);
|
|
6676
6674
|
};
|
|
6677
6675
|
createSubscription(companySpecificMetricsTable, wsMetricsFilter, "dashboard-ws-metrics", queueUpdate);
|
|
6678
6676
|
createSubscription(configuredLineMetricsTable, lineMetricsFilter, "dashboard-line-metrics", () => {
|
|
6679
6677
|
queueUpdate();
|
|
6680
|
-
|
|
6678
|
+
onLineMetricsUpdateRef.current?.();
|
|
6681
6679
|
});
|
|
6682
6680
|
return () => {
|
|
6683
6681
|
channels.forEach((channel) => {
|
|
6684
|
-
supabase?.removeChannel(channel)
|
|
6682
|
+
supabase?.removeChannel(channel);
|
|
6685
6683
|
});
|
|
6686
6684
|
};
|
|
6687
6685
|
}, [
|
|
6688
6686
|
supabase,
|
|
6689
|
-
// fetchAllMetrics, // fetchAllMetrics is now a dependency of queueUpdate
|
|
6690
6687
|
queueUpdate,
|
|
6691
|
-
// Section 6: Add queueUpdate as dependency
|
|
6692
6688
|
companySpecificMetricsTable,
|
|
6693
6689
|
configuredLineMetricsTable,
|
|
6694
6690
|
schema,
|
|
6695
|
-
entityConfig,
|
|
6696
|
-
|
|
6691
|
+
entityConfig?.companyId,
|
|
6692
|
+
entityConfig?.factoryViewId,
|
|
6697
6693
|
defaultTimezone,
|
|
6698
|
-
shiftConfig,
|
|
6699
|
-
onLineMetricsUpdate,
|
|
6700
6694
|
lineId
|
|
6701
|
-
// Add lineId from props to re-run effect if it changes, managed by lineIdRef inside effect
|
|
6702
6695
|
]);
|
|
6703
6696
|
return {
|
|
6704
6697
|
workspaceMetrics: metrics2?.workspaceMetrics || [],
|
|
@@ -6859,6 +6852,7 @@ var useRealtimeLineMetrics = ({
|
|
|
6859
6852
|
const updateQueueRef = useRef(false);
|
|
6860
6853
|
const isFetchingRef = useRef(false);
|
|
6861
6854
|
const channelsRef = useRef([]);
|
|
6855
|
+
const fetchTimeoutRef = useRef(null);
|
|
6862
6856
|
const currentShift = useMemo(() => getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig), [dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
6863
6857
|
const shiftId = useMemo(
|
|
6864
6858
|
() => urlShiftId !== void 0 ? urlShiftId : currentShift.shiftId,
|
|
@@ -7068,9 +7062,17 @@ var useRealtimeLineMetrics = ({
|
|
|
7068
7062
|
}
|
|
7069
7063
|
}, [supabase, date, shiftId, urlShiftId, onMetricsUpdate, entityConfig, dateTimeConfig.defaultTimezone]);
|
|
7070
7064
|
const queueUpdate = useCallback(() => {
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7065
|
+
console.log("[useRealtimeLineMetrics] Update queued, debouncing...");
|
|
7066
|
+
if (fetchTimeoutRef.current) {
|
|
7067
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
7068
|
+
}
|
|
7069
|
+
fetchTimeoutRef.current = setTimeout(() => {
|
|
7070
|
+
if (updateQueueRef.current) return;
|
|
7071
|
+
updateQueueRef.current = true;
|
|
7072
|
+
console.log("[useRealtimeLineMetrics] Debounced fetch triggered");
|
|
7073
|
+
fetchData();
|
|
7074
|
+
fetchTimeoutRef.current = null;
|
|
7075
|
+
}, 500);
|
|
7074
7076
|
}, [fetchData]);
|
|
7075
7077
|
const setupSubscriptions = useCallback(() => {
|
|
7076
7078
|
if (channelsRef.current.length > 0) {
|
|
@@ -7148,6 +7150,10 @@ var useRealtimeLineMetrics = ({
|
|
|
7148
7150
|
}
|
|
7149
7151
|
setupSubscriptions();
|
|
7150
7152
|
return () => {
|
|
7153
|
+
if (fetchTimeoutRef.current) {
|
|
7154
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
7155
|
+
fetchTimeoutRef.current = null;
|
|
7156
|
+
}
|
|
7151
7157
|
if (channelsRef.current.length > 0) {
|
|
7152
7158
|
channelsRef.current.forEach((channel) => {
|
|
7153
7159
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -8094,13 +8100,10 @@ var getWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
8094
8100
|
}
|
|
8095
8101
|
}
|
|
8096
8102
|
if (displayName) {
|
|
8097
|
-
console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${displayName} (from Supabase)`);
|
|
8098
8103
|
return displayName;
|
|
8099
8104
|
} else {
|
|
8100
8105
|
if (isInitialized) {
|
|
8101
|
-
console.
|
|
8102
|
-
} else {
|
|
8103
|
-
console.log(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (Supabase not initialized yet)`);
|
|
8106
|
+
console.warn(`getWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
|
|
8104
8107
|
}
|
|
8105
8108
|
return workspaceId;
|
|
8106
8109
|
}
|
|
@@ -8137,13 +8140,10 @@ var getShortWorkspaceDisplayName = (workspaceId, lineId) => {
|
|
|
8137
8140
|
}
|
|
8138
8141
|
}
|
|
8139
8142
|
if (displayName) {
|
|
8140
|
-
console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${displayName} (from Supabase)`);
|
|
8141
8143
|
return displayName;
|
|
8142
8144
|
} else {
|
|
8143
8145
|
if (isInitialized) {
|
|
8144
|
-
console.
|
|
8145
|
-
} else {
|
|
8146
|
-
console.log(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (Supabase not initialized yet)`);
|
|
8146
|
+
console.warn(`getShortWorkspaceDisplayName(${workspaceId}, lineId: ${lineId}) -> ${workspaceId} (not found in Supabase data)`);
|
|
8147
8147
|
}
|
|
8148
8148
|
return workspaceId;
|
|
8149
8149
|
}
|
|
@@ -8449,6 +8449,8 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8449
8449
|
const [loading, setLoading] = useState(true);
|
|
8450
8450
|
const [error, setError] = useState(null);
|
|
8451
8451
|
const [initialized, setInitialized] = useState(false);
|
|
8452
|
+
const fetchTimeoutRef = useRef(null);
|
|
8453
|
+
const isFetchingRef = useRef(false);
|
|
8452
8454
|
const queryShiftId = useMemo(() => {
|
|
8453
8455
|
const currentShift = getCurrentShift(
|
|
8454
8456
|
dateTimeConfig.defaultTimezone || "Asia/Kolkata",
|
|
@@ -8467,16 +8469,15 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8467
8469
|
}, [entityConfig.companyId]);
|
|
8468
8470
|
const schema = databaseConfig.schema ?? "public";
|
|
8469
8471
|
const fetchWorkspaceMetrics = useCallback(async () => {
|
|
8472
|
+
if (isFetchingRef.current) {
|
|
8473
|
+
return;
|
|
8474
|
+
}
|
|
8475
|
+
isFetchingRef.current = true;
|
|
8470
8476
|
if (!initialized) {
|
|
8471
8477
|
setLoading(true);
|
|
8472
8478
|
}
|
|
8473
8479
|
setError(null);
|
|
8474
8480
|
try {
|
|
8475
|
-
console.log("Fetching all workspace metrics with params:", {
|
|
8476
|
-
queryDate,
|
|
8477
|
-
queryShiftId,
|
|
8478
|
-
metricsTable
|
|
8479
|
-
});
|
|
8480
8481
|
const configuredLineIds = getConfiguredLineIds(entityConfig);
|
|
8481
8482
|
let enabledWorkspaceIds = [];
|
|
8482
8483
|
for (const lineId of configuredLineIds) {
|
|
@@ -8519,13 +8520,26 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8519
8520
|
efficiency: item.efficiency || 0,
|
|
8520
8521
|
action_threshold: item.total_day_output || 0
|
|
8521
8522
|
}));
|
|
8522
|
-
setWorkspaces(
|
|
8523
|
+
setWorkspaces((prevWorkspaces) => {
|
|
8524
|
+
if (prevWorkspaces.length !== transformedData.length) {
|
|
8525
|
+
return transformedData;
|
|
8526
|
+
}
|
|
8527
|
+
const hasChanges = transformedData.some((newWs) => {
|
|
8528
|
+
const prevWs = prevWorkspaces.find((w) => w.workspace_uuid === newWs.workspace_uuid);
|
|
8529
|
+
if (!prevWs) {
|
|
8530
|
+
return true;
|
|
8531
|
+
}
|
|
8532
|
+
return prevWs.efficiency !== newWs.efficiency || prevWs.action_count !== newWs.action_count || prevWs.action_threshold !== newWs.action_threshold || prevWs.avg_cycle_time !== newWs.avg_cycle_time || prevWs.workspace_name !== newWs.workspace_name;
|
|
8533
|
+
});
|
|
8534
|
+
return hasChanges ? transformedData : prevWorkspaces;
|
|
8535
|
+
});
|
|
8523
8536
|
setInitialized(true);
|
|
8524
8537
|
} catch (err) {
|
|
8525
|
-
console.error("Error
|
|
8538
|
+
console.error("[useAllWorkspaceMetrics] Error:", err.message);
|
|
8526
8539
|
setError({ message: err.message, code: err.code || "FETCH_ERROR" });
|
|
8527
8540
|
} finally {
|
|
8528
8541
|
setLoading(false);
|
|
8542
|
+
isFetchingRef.current = false;
|
|
8529
8543
|
}
|
|
8530
8544
|
}, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId]);
|
|
8531
8545
|
useEffect(() => {
|
|
@@ -8533,25 +8547,37 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
8533
8547
|
fetchWorkspaceMetrics();
|
|
8534
8548
|
}
|
|
8535
8549
|
const setupSubscription = () => {
|
|
8536
|
-
const filter2 = `date=eq.${queryDate} AND shift_id=eq.${queryShiftId}`;
|
|
8537
|
-
console.log("Setting up subscription for all workspaces with filter:", filter2);
|
|
8538
8550
|
const channel2 = supabase.channel(`all-workspace-metrics-${Date.now()}`).on(
|
|
8539
8551
|
"postgres_changes",
|
|
8540
8552
|
{
|
|
8541
8553
|
event: "*",
|
|
8542
8554
|
schema,
|
|
8543
|
-
table: metricsTable
|
|
8544
|
-
filter: filter2
|
|
8555
|
+
table: metricsTable
|
|
8545
8556
|
},
|
|
8546
8557
|
async (payload) => {
|
|
8547
|
-
|
|
8548
|
-
|
|
8558
|
+
const data = payload.new || payload.old;
|
|
8559
|
+
if (data?.date !== queryDate || data?.shift_id !== queryShiftId) {
|
|
8560
|
+
return;
|
|
8561
|
+
}
|
|
8562
|
+
if (fetchTimeoutRef.current) {
|
|
8563
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
8564
|
+
}
|
|
8565
|
+
fetchTimeoutRef.current = setTimeout(async () => {
|
|
8566
|
+
if (!isFetchingRef.current) {
|
|
8567
|
+
await fetchWorkspaceMetrics();
|
|
8568
|
+
}
|
|
8569
|
+
fetchTimeoutRef.current = null;
|
|
8570
|
+
}, 300);
|
|
8549
8571
|
}
|
|
8550
8572
|
).subscribe();
|
|
8551
8573
|
return channel2;
|
|
8552
8574
|
};
|
|
8553
8575
|
const channel = setupSubscription();
|
|
8554
8576
|
return () => {
|
|
8577
|
+
if (fetchTimeoutRef.current) {
|
|
8578
|
+
clearTimeout(fetchTimeoutRef.current);
|
|
8579
|
+
fetchTimeoutRef.current = null;
|
|
8580
|
+
}
|
|
8555
8581
|
if (channel) {
|
|
8556
8582
|
supabase.removeChannel(channel);
|
|
8557
8583
|
}
|
|
@@ -21953,7 +21979,16 @@ var VideoCard = React21__default.memo(({
|
|
|
21953
21979
|
}
|
|
21954
21980
|
);
|
|
21955
21981
|
}, (prevProps, nextProps) => {
|
|
21956
|
-
|
|
21982
|
+
if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
|
|
21983
|
+
return false;
|
|
21984
|
+
}
|
|
21985
|
+
if (prevProps.hlsUrl !== nextProps.hlsUrl || prevProps.shouldPlay !== nextProps.shouldPlay) {
|
|
21986
|
+
return false;
|
|
21987
|
+
}
|
|
21988
|
+
if (prevProps.cropping?.x !== nextProps.cropping?.x || prevProps.cropping?.y !== nextProps.cropping?.y || prevProps.cropping?.width !== nextProps.cropping?.width || prevProps.cropping?.height !== nextProps.cropping?.height) {
|
|
21989
|
+
return false;
|
|
21990
|
+
}
|
|
21991
|
+
return true;
|
|
21957
21992
|
});
|
|
21958
21993
|
VideoCard.displayName = "VideoCard";
|
|
21959
21994
|
var DEFAULT_HLS_URL = "https://192.168.5.9:8443/cam1.m3u8";
|
|
@@ -22249,7 +22284,7 @@ var WorkspaceMetricCardsImpl = ({
|
|
|
22249
22284
|
/* @__PURE__ */ jsxs(Card2, { className: "flex flex-col bg-white shadow-sm h-full min-h-[150px] sm:min-h-0", children: [
|
|
22250
22285
|
/* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
22251
22286
|
/* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6 sm:py-3", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
22252
|
-
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
22287
|
+
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
22253
22288
|
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
22254
22289
|
"Standard: ",
|
|
22255
22290
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -22961,7 +22996,8 @@ var BreakNotificationPopup = ({
|
|
|
22961
22996
|
onDismiss,
|
|
22962
22997
|
isVisible = true,
|
|
22963
22998
|
className = "",
|
|
22964
|
-
lineNames = {}
|
|
22999
|
+
lineNames = {},
|
|
23000
|
+
axelImagePath = "/axel-profile.png"
|
|
22965
23001
|
}) => {
|
|
22966
23002
|
const [isDismissed, setIsDismissed] = useState(false);
|
|
22967
23003
|
const [currentTime, setCurrentTime] = useState(/* @__PURE__ */ new Date());
|
|
@@ -22986,6 +23022,109 @@ var BreakNotificationPopup = ({
|
|
|
22986
23022
|
if (!isVisible || isDismissed || activeBreaks.length === 0) {
|
|
22987
23023
|
return null;
|
|
22988
23024
|
}
|
|
23025
|
+
return /* @__PURE__ */ jsx(AnimatePresence, { children: activeBreaks.map((breakItem, index) => /* @__PURE__ */ jsx(
|
|
23026
|
+
motion.div,
|
|
23027
|
+
{
|
|
23028
|
+
initial: { opacity: 0, x: 100, y: -20 },
|
|
23029
|
+
animate: { opacity: 1, x: 0, y: 0 },
|
|
23030
|
+
exit: { opacity: 0, x: 100, y: -20 },
|
|
23031
|
+
transition: { duration: 0.3, ease: "easeOut", delay: index * 0.1 },
|
|
23032
|
+
className: `fixed right-4 z-50 max-w-xs w-full ${className}`,
|
|
23033
|
+
style: { top: `${6 + index * 12}rem` },
|
|
23034
|
+
children: /* @__PURE__ */ jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
|
|
23035
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
|
|
23036
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
|
|
23037
|
+
"img",
|
|
23038
|
+
{
|
|
23039
|
+
src: axelImagePath,
|
|
23040
|
+
alt: "Axel AI",
|
|
23041
|
+
className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
|
|
23042
|
+
onError: (e) => {
|
|
23043
|
+
const target = e.currentTarget;
|
|
23044
|
+
target.style.display = "none";
|
|
23045
|
+
const fallback = document.createElement("div");
|
|
23046
|
+
fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
|
|
23047
|
+
fallback.textContent = "A";
|
|
23048
|
+
target.parentElement?.appendChild(fallback);
|
|
23049
|
+
}
|
|
23050
|
+
}
|
|
23051
|
+
) }),
|
|
23052
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
23053
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
|
|
23054
|
+
/* @__PURE__ */ jsxs("h4", { className: "font-semibold text-sm text-gray-900", children: [
|
|
23055
|
+
breakItem.remarks || "Break",
|
|
23056
|
+
(activeBreaks.length > 1 || lineNames[breakItem.lineId]) && /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-500 ml-1", children: [
|
|
23057
|
+
"\u2022 ",
|
|
23058
|
+
lineNames[breakItem.lineId] || `Line ${breakItem.lineId.substring(0, 8)}`
|
|
23059
|
+
] })
|
|
23060
|
+
] }),
|
|
23061
|
+
/* @__PURE__ */ jsx(Coffee, { className: "w-4 h-4 text-amber-500" })
|
|
23062
|
+
] }),
|
|
23063
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-600 leading-relaxed mb-2", children: [
|
|
23064
|
+
"Currently active from ",
|
|
23065
|
+
breakItem.startTime,
|
|
23066
|
+
" to ",
|
|
23067
|
+
breakItem.endTime,
|
|
23068
|
+
". ",
|
|
23069
|
+
formatTime3(breakItem.elapsedMinutes),
|
|
23070
|
+
" elapsed of ",
|
|
23071
|
+
formatTime3(breakItem.duration),
|
|
23072
|
+
" total."
|
|
23073
|
+
] }),
|
|
23074
|
+
/* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsx(
|
|
23075
|
+
"div",
|
|
23076
|
+
{
|
|
23077
|
+
className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
|
|
23078
|
+
style: {
|
|
23079
|
+
width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
|
|
23080
|
+
}
|
|
23081
|
+
}
|
|
23082
|
+
) }) })
|
|
23083
|
+
] })
|
|
23084
|
+
] }),
|
|
23085
|
+
/* @__PURE__ */ jsx(
|
|
23086
|
+
"button",
|
|
23087
|
+
{
|
|
23088
|
+
onClick: handleDismiss,
|
|
23089
|
+
onTouchStart: () => {
|
|
23090
|
+
},
|
|
23091
|
+
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center flex-shrink-0",
|
|
23092
|
+
"aria-label": "Dismiss notification",
|
|
23093
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4 sm:w-3 sm:h-3" })
|
|
23094
|
+
}
|
|
23095
|
+
)
|
|
23096
|
+
] }) }) })
|
|
23097
|
+
},
|
|
23098
|
+
`${breakItem.lineId}-${breakItem.startTime}-${index}`
|
|
23099
|
+
)) });
|
|
23100
|
+
};
|
|
23101
|
+
var AxelNotificationPopup = ({
|
|
23102
|
+
suggestion,
|
|
23103
|
+
isVisible = true,
|
|
23104
|
+
onDismiss,
|
|
23105
|
+
className = "",
|
|
23106
|
+
axelImagePath = "/axel-profile.png"
|
|
23107
|
+
}) => {
|
|
23108
|
+
const [isDismissed, setIsDismissed] = useState(false);
|
|
23109
|
+
const handleDismiss = () => {
|
|
23110
|
+
setIsDismissed(true);
|
|
23111
|
+
onDismiss?.();
|
|
23112
|
+
};
|
|
23113
|
+
if (!isVisible || isDismissed || !suggestion) {
|
|
23114
|
+
return null;
|
|
23115
|
+
}
|
|
23116
|
+
const getTypeIcon = () => {
|
|
23117
|
+
switch (suggestion.type) {
|
|
23118
|
+
case "improvement":
|
|
23119
|
+
return /* @__PURE__ */ jsx(TrendingUp, { className: "w-4 h-4 text-blue-500" });
|
|
23120
|
+
case "alert":
|
|
23121
|
+
return /* @__PURE__ */ jsx(AlertCircle, { className: "w-4 h-4 text-amber-500" });
|
|
23122
|
+
case "insight":
|
|
23123
|
+
return /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 text-purple-500" });
|
|
23124
|
+
default:
|
|
23125
|
+
return /* @__PURE__ */ jsx(Sparkles, { className: "w-4 h-4 text-blue-500" });
|
|
23126
|
+
}
|
|
23127
|
+
};
|
|
22989
23128
|
return /* @__PURE__ */ jsx(AnimatePresence, { children: /* @__PURE__ */ jsx(
|
|
22990
23129
|
motion.div,
|
|
22991
23130
|
{
|
|
@@ -22993,58 +23132,54 @@ var BreakNotificationPopup = ({
|
|
|
22993
23132
|
animate: { opacity: 1, x: 0, y: 0 },
|
|
22994
23133
|
exit: { opacity: 0, x: 100, y: -20 },
|
|
22995
23134
|
transition: { duration: 0.3, ease: "easeOut" },
|
|
22996
|
-
className: `fixed top-24 right-4 z-
|
|
22997
|
-
children: /* @__PURE__ */ jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children:
|
|
23135
|
+
className: `fixed top-24 right-4 z-40 max-w-xs w-full ${className}`,
|
|
23136
|
+
children: /* @__PURE__ */ jsx("div", { className: "bg-white text-gray-900 rounded-lg border border-gray-200 shadow-lg overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
22998
23137
|
motion.div,
|
|
22999
23138
|
{
|
|
23000
|
-
initial: { opacity: 0, y:
|
|
23139
|
+
initial: { opacity: 0, y: 10 },
|
|
23001
23140
|
animate: { opacity: 1, y: 0 },
|
|
23002
|
-
transition: { delay:
|
|
23003
|
-
className:
|
|
23141
|
+
transition: { delay: 0.1 },
|
|
23142
|
+
className: "p-3",
|
|
23004
23143
|
children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
|
|
23005
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-
|
|
23006
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
23144
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-3 flex-1", children: [
|
|
23145
|
+
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
|
|
23146
|
+
"img",
|
|
23147
|
+
{
|
|
23148
|
+
src: axelImagePath,
|
|
23149
|
+
alt: "Axel AI",
|
|
23150
|
+
className: "w-10 h-10 rounded-full object-cover border-2 border-gray-200 shadow-sm",
|
|
23151
|
+
onError: (e) => {
|
|
23152
|
+
const target = e.currentTarget;
|
|
23153
|
+
target.style.display = "none";
|
|
23154
|
+
const fallback = document.createElement("div");
|
|
23155
|
+
fallback.className = "w-10 h-10 rounded-full bg-blue-500 flex items-center justify-center text-white font-bold text-base shadow-sm border-2 border-gray-200";
|
|
23156
|
+
fallback.textContent = "A";
|
|
23157
|
+
target.parentElement?.appendChild(fallback);
|
|
23158
|
+
}
|
|
23159
|
+
}
|
|
23160
|
+
) }),
|
|
23007
23161
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
23008
|
-
/* @__PURE__ */ jsxs("div", { className: "mb-1", children: [
|
|
23009
|
-
/* @__PURE__ */ jsx("h4", { className: "font-semibold text-
|
|
23010
|
-
|
|
23162
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mb-1.5", children: [
|
|
23163
|
+
/* @__PURE__ */ jsx("h4", { className: "font-semibold text-sm text-gray-900", children: suggestion.title }),
|
|
23164
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: getTypeIcon() })
|
|
23011
23165
|
] }),
|
|
23012
|
-
/* @__PURE__ */ jsx("
|
|
23013
|
-
breakItem.startTime,
|
|
23014
|
-
" - ",
|
|
23015
|
-
breakItem.endTime
|
|
23016
|
-
] }) }),
|
|
23017
|
-
/* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxs("div", { className: "text-sm sm:text-xs text-gray-500", children: [
|
|
23018
|
-
formatTime3(breakItem.elapsedMinutes),
|
|
23019
|
-
" / ",
|
|
23020
|
-
formatTime3(breakItem.duration)
|
|
23021
|
-
] }) }),
|
|
23022
|
-
/* @__PURE__ */ jsx("div", { className: "mt-2", children: /* @__PURE__ */ jsx("div", { className: "w-full bg-gray-200 rounded-full h-1.5", children: /* @__PURE__ */ jsx(
|
|
23023
|
-
"div",
|
|
23024
|
-
{
|
|
23025
|
-
className: "h-1.5 bg-blue-500 rounded-full transition-all duration-1000",
|
|
23026
|
-
style: {
|
|
23027
|
-
width: `${Math.min(100, Math.max(0, breakItem.elapsedMinutes / breakItem.duration * 100))}%`
|
|
23028
|
-
}
|
|
23029
|
-
}
|
|
23030
|
-
) }) })
|
|
23166
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-600 leading-relaxed", children: suggestion.message })
|
|
23031
23167
|
] })
|
|
23032
23168
|
] }),
|
|
23033
|
-
|
|
23169
|
+
/* @__PURE__ */ jsx(
|
|
23034
23170
|
"button",
|
|
23035
23171
|
{
|
|
23036
23172
|
onClick: handleDismiss,
|
|
23037
23173
|
onTouchStart: () => {
|
|
23038
23174
|
},
|
|
23039
|
-
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center",
|
|
23175
|
+
className: "ml-2 text-gray-400 hover:text-gray-600 transition-colors p-2 sm:p-1 rounded-full hover:bg-gray-100 active:bg-gray-200 touch-manipulation min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center flex-shrink-0",
|
|
23040
23176
|
"aria-label": "Dismiss notification",
|
|
23041
23177
|
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4 sm:w-3 sm:h-3" })
|
|
23042
23178
|
}
|
|
23043
23179
|
)
|
|
23044
23180
|
] })
|
|
23045
|
-
}
|
|
23046
|
-
|
|
23047
|
-
)) })
|
|
23181
|
+
}
|
|
23182
|
+
) })
|
|
23048
23183
|
}
|
|
23049
23184
|
) });
|
|
23050
23185
|
};
|
|
@@ -25875,12 +26010,6 @@ var WorkspaceHistoryCalendar = ({
|
|
|
25875
26010
|
] })
|
|
25876
26011
|
] });
|
|
25877
26012
|
};
|
|
25878
|
-
|
|
25879
|
-
// src/lib/constants/design-tokens.ts
|
|
25880
|
-
var designTokens = {
|
|
25881
|
-
// Typography scale with clear hierarchy
|
|
25882
|
-
typography: {
|
|
25883
|
-
body: "text-sm text-gray-600"}};
|
|
25884
26013
|
var WEEKDAYS3 = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
25885
26014
|
var getOrdinal = (n) => {
|
|
25886
26015
|
const suffix = ["th", "st", "nd", "rd"];
|
|
@@ -25929,8 +26058,19 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25929
26058
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
25930
26059
|
const dailyData = [];
|
|
25931
26060
|
let maxOutput = 0;
|
|
25932
|
-
let
|
|
25933
|
-
let
|
|
26061
|
+
let lastSetTarget = 0;
|
|
26062
|
+
for (let day = daysInMonth; day >= 1; day--) {
|
|
26063
|
+
const dayData = data.find((d) => {
|
|
26064
|
+
const date = new Date(d.date);
|
|
26065
|
+
return date.getDate() === day;
|
|
26066
|
+
});
|
|
26067
|
+
const shiftData = dayData ? selectedShift === "day" ? dayData.dayShift : dayData.nightShift : null;
|
|
26068
|
+
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
26069
|
+
if (idealOutput > 0) {
|
|
26070
|
+
lastSetTarget = idealOutput;
|
|
26071
|
+
break;
|
|
26072
|
+
}
|
|
26073
|
+
}
|
|
25934
26074
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
25935
26075
|
const dayData = data.find((d) => {
|
|
25936
26076
|
const date = new Date(d.date);
|
|
@@ -25940,11 +26080,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25940
26080
|
const output = shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
25941
26081
|
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
25942
26082
|
if (output > maxOutput) maxOutput = output;
|
|
25943
|
-
|
|
25944
|
-
totalIdealOutput += idealOutput;
|
|
25945
|
-
validDaysCount++;
|
|
25946
|
-
}
|
|
25947
|
-
const color2 = output >= idealOutput ? "#00AB45" : "#E34329";
|
|
26083
|
+
const color2 = output >= lastSetTarget ? "#00AB45" : "#E34329";
|
|
25948
26084
|
dailyData.push({
|
|
25949
26085
|
hour: getOrdinal(day),
|
|
25950
26086
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -25959,14 +26095,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25959
26095
|
// Not used but keeps structure consistent
|
|
25960
26096
|
});
|
|
25961
26097
|
}
|
|
25962
|
-
const
|
|
25963
|
-
const calculatedMax = Math.max(maxOutput, avgIdealOutput);
|
|
26098
|
+
const calculatedMax = Math.max(maxOutput, lastSetTarget);
|
|
25964
26099
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
25965
|
-
return { data: dailyData, maxOutput,
|
|
26100
|
+
return { data: dailyData, maxOutput, lastSetTarget, yAxisMax };
|
|
25966
26101
|
}, [data, month, year, selectedShift]);
|
|
25967
26102
|
const yAxisTicks = useMemo(() => {
|
|
25968
26103
|
const max = chartData.yAxisMax;
|
|
25969
|
-
const target = chartData.
|
|
26104
|
+
const target = chartData.lastSetTarget;
|
|
25970
26105
|
if (!max || max <= 0) return void 0;
|
|
25971
26106
|
const desiredIntervals = 4;
|
|
25972
26107
|
const roughStep = max / desiredIntervals;
|
|
@@ -25984,7 +26119,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25984
26119
|
ticks.push(Math.round(target));
|
|
25985
26120
|
}
|
|
25986
26121
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
25987
|
-
}, [chartData.yAxisMax, chartData.
|
|
26122
|
+
}, [chartData.yAxisMax, chartData.lastSetTarget]);
|
|
25988
26123
|
const pieChartData = useMemo(() => {
|
|
25989
26124
|
const validShifts = data.map((d) => selectedShift === "day" ? d.dayShift : d.nightShift).filter(hasRealData);
|
|
25990
26125
|
if (validShifts.length === 0) return [];
|
|
@@ -26058,10 +26193,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26058
26193
|
}
|
|
26059
26194
|
}, [workspaceId, onShiftChange]);
|
|
26060
26195
|
if (monthlyDataLoading) {
|
|
26061
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */
|
|
26062
|
-
|
|
26063
|
-
|
|
26064
|
-
|
|
26196
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */ jsx(
|
|
26197
|
+
OptifyeLogoLoader_default,
|
|
26198
|
+
{
|
|
26199
|
+
size: "lg",
|
|
26200
|
+
message: "Loading monthly performance data..."
|
|
26201
|
+
}
|
|
26202
|
+
) });
|
|
26065
26203
|
}
|
|
26066
26204
|
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-2 min-h-0 overflow-y-auto pb-6 ${className}`, children: [
|
|
26067
26205
|
/* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: [
|
|
@@ -26296,7 +26434,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26296
26434
|
tick: (props) => {
|
|
26297
26435
|
const { x, y, payload } = props;
|
|
26298
26436
|
const value = Math.round(payload.value);
|
|
26299
|
-
const targetValue = Math.round(chartData.
|
|
26437
|
+
const targetValue = Math.round(chartData.lastSetTarget);
|
|
26300
26438
|
const isTarget = Math.abs(value - targetValue) < 1 && targetValue > 0;
|
|
26301
26439
|
return /* @__PURE__ */ jsx(
|
|
26302
26440
|
"text",
|
|
@@ -26320,10 +26458,10 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26320
26458
|
content: CustomTooltip
|
|
26321
26459
|
}
|
|
26322
26460
|
),
|
|
26323
|
-
chartData.
|
|
26461
|
+
chartData.lastSetTarget > 0 && /* @__PURE__ */ jsx(
|
|
26324
26462
|
ReferenceLine,
|
|
26325
26463
|
{
|
|
26326
|
-
y: chartData.
|
|
26464
|
+
y: chartData.lastSetTarget,
|
|
26327
26465
|
stroke: "#E34329",
|
|
26328
26466
|
strokeDasharray: "5 5",
|
|
26329
26467
|
strokeWidth: 2
|
|
@@ -26381,11 +26519,11 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26381
26519
|
]
|
|
26382
26520
|
}
|
|
26383
26521
|
) }) }),
|
|
26384
|
-
/* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.
|
|
26522
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.lastSetTarget > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26385
26523
|
/* @__PURE__ */ jsx("div", { className: "w-12 h-0.5 border-t-2 border-dashed", style: { borderColor: "#E34329" } }),
|
|
26386
26524
|
/* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
|
|
26387
26525
|
"Target: ",
|
|
26388
|
-
Math.round(chartData.
|
|
26526
|
+
Math.round(chartData.lastSetTarget),
|
|
26389
26527
|
" units/day"
|
|
26390
26528
|
] })
|
|
26391
26529
|
] }) })
|
|
@@ -26498,7 +26636,7 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
|
|
|
26498
26636
|
doc.roundedRect(22, y - 7, 165, 12, 2, 2, "S");
|
|
26499
26637
|
};
|
|
26500
26638
|
doc.setFillColor(245, 245, 245);
|
|
26501
|
-
doc.roundedRect(15, 95, 180,
|
|
26639
|
+
doc.roundedRect(15, 95, 180, 60, 3, 3, "F");
|
|
26502
26640
|
doc.setFontSize(18);
|
|
26503
26641
|
doc.setFont("helvetica", "bold");
|
|
26504
26642
|
doc.setTextColor(40, 40, 40);
|
|
@@ -26527,34 +26665,29 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
|
|
|
26527
26665
|
doc.text("PPH (Pieces Per Hour):", 25, kpiStartY + kpiSpacing * 3);
|
|
26528
26666
|
doc.setFont("helvetica", "bold");
|
|
26529
26667
|
doc.text(`${workspace.avg_pph.toFixed(1)} (Standard: ${workspace.pph_threshold.toFixed(1)})`, 120, kpiStartY + kpiSpacing * 3);
|
|
26530
|
-
createKPIBox(kpiStartY + kpiSpacing * 4);
|
|
26531
|
-
doc.setFont("helvetica", "normal");
|
|
26532
|
-
doc.text("Rank:", 25, kpiStartY + kpiSpacing * 4);
|
|
26533
|
-
doc.setFont("helvetica", "bold");
|
|
26534
|
-
doc.text(`${workspace.workspace_rank} of ${workspace.total_workspaces}`, 120, kpiStartY + kpiSpacing * 4);
|
|
26535
26668
|
doc.setDrawColor(180, 180, 180);
|
|
26536
26669
|
doc.setLineWidth(0.8);
|
|
26537
|
-
doc.line(20,
|
|
26670
|
+
doc.line(20, 170, 190, 170);
|
|
26538
26671
|
doc.setFillColor(245, 245, 245);
|
|
26539
|
-
doc.roundedRect(15,
|
|
26672
|
+
doc.roundedRect(15, 175, 180, 85, 3, 3, "F");
|
|
26540
26673
|
doc.setFontSize(18);
|
|
26541
26674
|
doc.setFont("helvetica", "bold");
|
|
26542
26675
|
doc.setTextColor(40, 40, 40);
|
|
26543
|
-
doc.text("Hourly Performance", 20,
|
|
26676
|
+
doc.text("Hourly Performance", 20, 185);
|
|
26544
26677
|
doc.setTextColor(0, 0, 0);
|
|
26545
26678
|
doc.setFontSize(11);
|
|
26546
26679
|
doc.setFont("helvetica", "bold");
|
|
26547
26680
|
doc.setFillColor(245, 245, 245);
|
|
26548
|
-
doc.roundedRect(20,
|
|
26549
|
-
doc.text("Time Range", 25,
|
|
26550
|
-
doc.text("Output", 95,
|
|
26551
|
-
doc.text("Target", 135,
|
|
26552
|
-
doc.text("Status", 170,
|
|
26681
|
+
doc.roundedRect(20, 177, 170, 8, 1, 1, "F");
|
|
26682
|
+
doc.text("Time Range", 25, 182);
|
|
26683
|
+
doc.text("Output", 95, 182);
|
|
26684
|
+
doc.text("Target", 135, 182);
|
|
26685
|
+
doc.text("Status", 170, 182);
|
|
26553
26686
|
doc.setLineWidth(0.2);
|
|
26554
26687
|
doc.setDrawColor(220, 220, 220);
|
|
26555
|
-
doc.line(20,
|
|
26688
|
+
doc.line(20, 185, 190, 185);
|
|
26556
26689
|
doc.setFont("helvetica", "normal");
|
|
26557
|
-
let yPos =
|
|
26690
|
+
let yPos = 191;
|
|
26558
26691
|
const hourlyData = workspace.hourly_action_counts || [];
|
|
26559
26692
|
const hourlyTarget = workspace.pph_threshold;
|
|
26560
26693
|
hourlyData.forEach((output, index) => {
|
|
@@ -27231,6 +27364,36 @@ var TimePickerDropdown = ({
|
|
|
27231
27364
|
] })
|
|
27232
27365
|
] });
|
|
27233
27366
|
};
|
|
27367
|
+
var ERROR_MAPPING = {
|
|
27368
|
+
1: {
|
|
27369
|
+
// MEDIA_ERR_ABORTED
|
|
27370
|
+
code: 1,
|
|
27371
|
+
type: "recoverable" /* RECOVERABLE */,
|
|
27372
|
+
message: "Video loading was interrupted",
|
|
27373
|
+
canRetry: true
|
|
27374
|
+
},
|
|
27375
|
+
2: {
|
|
27376
|
+
// MEDIA_ERR_NETWORK
|
|
27377
|
+
code: 2,
|
|
27378
|
+
type: "recoverable" /* RECOVERABLE */,
|
|
27379
|
+
message: "Network error - please check your internet connection",
|
|
27380
|
+
canRetry: true
|
|
27381
|
+
},
|
|
27382
|
+
3: {
|
|
27383
|
+
// MEDIA_ERR_DECODE
|
|
27384
|
+
code: 3,
|
|
27385
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27386
|
+
message: "Stream corrupted due to internet connection",
|
|
27387
|
+
canRetry: false
|
|
27388
|
+
},
|
|
27389
|
+
4: {
|
|
27390
|
+
// MEDIA_ERR_SRC_NOT_SUPPORTED
|
|
27391
|
+
code: 4,
|
|
27392
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27393
|
+
message: "Video format not supported by your browser. Please use Google Chrome.",
|
|
27394
|
+
canRetry: false
|
|
27395
|
+
}
|
|
27396
|
+
};
|
|
27234
27397
|
var videoPlayerStyles = `
|
|
27235
27398
|
.video-player-container {
|
|
27236
27399
|
width: 100%;
|
|
@@ -27461,8 +27624,21 @@ var VideoPlayer = React21__default.forwardRef(({
|
|
|
27461
27624
|
player.on("seeked", () => onSeeked?.(player));
|
|
27462
27625
|
player.on("error", () => {
|
|
27463
27626
|
const error = player.error();
|
|
27464
|
-
|
|
27465
|
-
|
|
27627
|
+
const errorCode = error?.code ?? 0;
|
|
27628
|
+
const errorInfo = ERROR_MAPPING[errorCode] || {
|
|
27629
|
+
code: errorCode || 0,
|
|
27630
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27631
|
+
message: "Unknown playback error occurred",
|
|
27632
|
+
canRetry: false
|
|
27633
|
+
};
|
|
27634
|
+
console.error("[VideoPlayer] Video.js error:", {
|
|
27635
|
+
code: errorCode,
|
|
27636
|
+
type: errorInfo.type,
|
|
27637
|
+
message: errorInfo.message,
|
|
27638
|
+
canRetry: errorInfo.canRetry,
|
|
27639
|
+
originalError: error
|
|
27640
|
+
});
|
|
27641
|
+
onError?.(player, errorInfo);
|
|
27466
27642
|
});
|
|
27467
27643
|
if (src) {
|
|
27468
27644
|
const isHLS = src.endsWith(".m3u8") || src.startsWith("#EXTM3U");
|
|
@@ -28305,7 +28481,10 @@ var FilterDialogTrigger = ({
|
|
|
28305
28481
|
}
|
|
28306
28482
|
);
|
|
28307
28483
|
};
|
|
28308
|
-
var getSeverityIcon = (severity) => {
|
|
28484
|
+
var getSeverityIcon = (severity, categoryId) => {
|
|
28485
|
+
if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
|
|
28486
|
+
return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3 w-3 text-red-500" });
|
|
28487
|
+
}
|
|
28309
28488
|
switch (severity) {
|
|
28310
28489
|
case "high":
|
|
28311
28490
|
return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3 w-3 text-red-500" });
|
|
@@ -28532,17 +28711,17 @@ var FileManagerFilters = ({
|
|
|
28532
28711
|
const colorClasses = getColorClasses(category.color);
|
|
28533
28712
|
const clipNodes = filteredClips.map((clip, index) => {
|
|
28534
28713
|
const timeString = new Date(clip.clip_timestamp).toLocaleTimeString("en-US", {
|
|
28535
|
-
hour12:
|
|
28536
|
-
hour: "
|
|
28714
|
+
hour12: true,
|
|
28715
|
+
hour: "numeric",
|
|
28537
28716
|
minute: "2-digit",
|
|
28538
28717
|
timeZone: timezone
|
|
28539
28718
|
// Use database timezone for display
|
|
28540
28719
|
});
|
|
28541
28720
|
return {
|
|
28542
28721
|
id: clip.id,
|
|
28543
|
-
label: `${timeString}
|
|
28722
|
+
label: `${timeString}${clip.duration && category.id !== "idle_time" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`,
|
|
28544
28723
|
type: "video",
|
|
28545
|
-
icon: getSeverityIcon(clip.severity),
|
|
28724
|
+
icon: getSeverityIcon(clip.severity, category.id),
|
|
28546
28725
|
timestamp: clip.clip_timestamp,
|
|
28547
28726
|
severity: clip.severity,
|
|
28548
28727
|
clipId: clip.clipId,
|
|
@@ -28582,9 +28761,9 @@ var FileManagerFilters = ({
|
|
|
28582
28761
|
children: (percentileClips["fast-cycles"] || []).map((clip, index) => ({
|
|
28583
28762
|
id: clip.id,
|
|
28584
28763
|
// Remove prefix to match currentVideoId
|
|
28585
|
-
label: `${clip.timestamp}
|
|
28764
|
+
label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
28586
28765
|
type: "video",
|
|
28587
|
-
icon: getSeverityIcon(clip.severity),
|
|
28766
|
+
icon: getSeverityIcon(clip.severity, "fast-cycles"),
|
|
28588
28767
|
timestamp: clip.creation_timestamp,
|
|
28589
28768
|
severity: clip.severity,
|
|
28590
28769
|
clipId: clip.id,
|
|
@@ -28605,9 +28784,9 @@ var FileManagerFilters = ({
|
|
|
28605
28784
|
children: (percentileClips["slow-cycles"] || []).map((clip, index) => ({
|
|
28606
28785
|
id: clip.id,
|
|
28607
28786
|
// Remove prefix to match currentVideoId
|
|
28608
|
-
label: `${clip.timestamp}
|
|
28787
|
+
label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ""}`,
|
|
28609
28788
|
type: "video",
|
|
28610
|
-
icon: getSeverityIcon(clip.severity),
|
|
28789
|
+
icon: getSeverityIcon(clip.severity, "slow-cycles"),
|
|
28611
28790
|
timestamp: clip.creation_timestamp,
|
|
28612
28791
|
severity: clip.severity,
|
|
28613
28792
|
clipId: clip.id,
|
|
@@ -28628,9 +28807,9 @@ var FileManagerFilters = ({
|
|
|
28628
28807
|
isPercentile: true,
|
|
28629
28808
|
children: (percentileClips['idle-times'] || []).map((clip, index) => ({
|
|
28630
28809
|
id: clip.id, // Remove prefix to match currentVideoId
|
|
28631
|
-
label: `${clip.timestamp}
|
|
28810
|
+
label: `${clip.timestamp}${clip.cycle_time_seconds ? ` - (${clip.cycle_time_seconds.toFixed(1)}s)` : ''}`,
|
|
28632
28811
|
type: 'video' as const,
|
|
28633
|
-
icon: getSeverityIcon(clip.severity),
|
|
28812
|
+
icon: getSeverityIcon(clip.severity, 'longest-idles'),
|
|
28634
28813
|
timestamp: clip.creation_timestamp,
|
|
28635
28814
|
severity: clip.severity,
|
|
28636
28815
|
clipId: clip.id,
|
|
@@ -28640,7 +28819,7 @@ var FileManagerFilters = ({
|
|
|
28640
28819
|
];
|
|
28641
28820
|
percentileCategories.forEach((category) => {
|
|
28642
28821
|
if (category.count > 0 && shouldShowCategory(category.id)) {
|
|
28643
|
-
tree.
|
|
28822
|
+
tree.push(category);
|
|
28644
28823
|
}
|
|
28645
28824
|
});
|
|
28646
28825
|
return tree;
|
|
@@ -28685,7 +28864,7 @@ var FileManagerFilters = ({
|
|
|
28685
28864
|
/* @__PURE__ */ jsxs(
|
|
28686
28865
|
"div",
|
|
28687
28866
|
{
|
|
28688
|
-
className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-
|
|
28867
|
+
className: `flex items-center cursor-pointer transition-all duration-300 ease-out group relative overflow-hidden ${node.type === "category" && depth === 0 ? `py-3 px-4 rounded-2xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-blue-50/30 hover:shadow-lg hover:shadow-blue-100/20 hover:scale-[1.02] hover:-translate-y-0.5 ${isActive ? "bg-gradient-to-r from-blue-50 via-blue-50/80 to-indigo-50/60 border border-blue-200/50 shadow-lg shadow-blue-100/30 scale-[1.02]" : "border border-transparent"}` : `py-2 px-3 rounded-xl hover:bg-gradient-to-r hover:from-slate-50 hover:to-slate-50/50 hover:shadow-sm ${isActive ? "bg-gradient-to-r from-blue-50/80 to-blue-50/40 border border-blue-200/30 shadow-sm" : "border border-transparent"} ${isCurrentVideo ? "bg-gradient-to-r from-blue-50 to-blue-50/60 border border-blue-200/50 shadow-md shadow-blue-100/20" : ""}`} ${node.type === "video" ? "ml-6" : ""}`,
|
|
28689
28868
|
onClick: () => handleNodeClick(node),
|
|
28690
28869
|
children: [
|
|
28691
28870
|
hasChildren && /* @__PURE__ */ jsx(
|
|
@@ -28702,13 +28881,10 @@ var FileManagerFilters = ({
|
|
|
28702
28881
|
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 mr-3 ${node.type === "category" || node.type === "percentile-category" ? "p-2 rounded-lg shadow-sm group-hover:scale-110 transition-transform duration-200" : "p-0.5"} ${colorClasses && (node.type === "category" || node.type === "percentile-category") ? `${colorClasses.bg} border border-white/60` : ""}`, children: node.icon }),
|
|
28703
28882
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
|
|
28704
28883
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
28705
|
-
/* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-
|
|
28884
|
+
/* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-blue-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
|
|
28706
28885
|
node.type === "category" && categories.find((c) => c.id === node.id)?.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: categories.find((c) => c.id === node.id)?.description }),
|
|
28707
28886
|
node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
|
|
28708
|
-
node.type === "video" && node.severity && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */
|
|
28709
|
-
node.severity,
|
|
28710
|
-
" priority"
|
|
28711
|
-
] }) })
|
|
28887
|
+
node.type === "video" && node.severity && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 capitalize mt-0.5 font-medium", children: /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${node.categoryId === "idle_time" || node.categoryId === "low_value" ? "bg-red-100 text-red-700" : node.severity === "high" ? "bg-red-100 text-red-700" : node.severity === "medium" ? "bg-yellow-100 text-yellow-700" : "bg-green-100 text-green-700"}`, children: node.categoryId === "idle_time" || node.categoryId === "low_value" ? "Idle" : node.severity === "low" ? "Fast" : node.severity === "medium" ? "Average" : "Slow" }) })
|
|
28712
28888
|
] }),
|
|
28713
28889
|
node.count !== void 0 && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "flex items-center ml-2", children: /* @__PURE__ */ jsx("span", { className: `px-2.5 py-1 text-sm font-bold rounded-lg shadow-sm border backdrop-blur-sm flex-shrink-0 group-hover:scale-105 transition-all duration-200 ${colorClasses ? `${colorClasses.bg} ${colorClasses.text} ${colorClasses.border} bg-opacity-80` : "bg-slate-100/80 text-slate-700 border-slate-200/60"}`, children: node.count }) })
|
|
28714
28890
|
] })
|
|
@@ -29357,7 +29533,12 @@ var BottlenecksContent = ({
|
|
|
29357
29533
|
} catch (err) {
|
|
29358
29534
|
console.error("[BottlenecksContent] Error fetching clip counts:", err);
|
|
29359
29535
|
if (isMountedRef.current) {
|
|
29360
|
-
setError(
|
|
29536
|
+
setError({
|
|
29537
|
+
type: "fatal",
|
|
29538
|
+
message: "Failed to load clip counts. Please try again.",
|
|
29539
|
+
canSkip: false,
|
|
29540
|
+
canRetry: true
|
|
29541
|
+
});
|
|
29361
29542
|
setIsLoading(false);
|
|
29362
29543
|
}
|
|
29363
29544
|
} finally {
|
|
@@ -29441,7 +29622,12 @@ var BottlenecksContent = ({
|
|
|
29441
29622
|
} catch (err) {
|
|
29442
29623
|
console.error("Error loading first video for category:", err);
|
|
29443
29624
|
if (isMountedRef.current) {
|
|
29444
|
-
setError(
|
|
29625
|
+
setError({
|
|
29626
|
+
type: "fatal",
|
|
29627
|
+
message: "Failed to load clips. Please try again.",
|
|
29628
|
+
canSkip: false,
|
|
29629
|
+
canRetry: true
|
|
29630
|
+
});
|
|
29445
29631
|
setIsCategoryLoading(false);
|
|
29446
29632
|
}
|
|
29447
29633
|
} finally {
|
|
@@ -29723,7 +29909,12 @@ var BottlenecksContent = ({
|
|
|
29723
29909
|
} catch (error2) {
|
|
29724
29910
|
console.error(`[BottlenecksContent] Error loading clip by ID (${clipId}):`, error2);
|
|
29725
29911
|
if (isMountedRef.current) {
|
|
29726
|
-
setError(
|
|
29912
|
+
setError({
|
|
29913
|
+
type: "fatal",
|
|
29914
|
+
message: "Failed to load selected clip. Please try again.",
|
|
29915
|
+
canSkip: true,
|
|
29916
|
+
canRetry: true
|
|
29917
|
+
});
|
|
29727
29918
|
clearLoadingState();
|
|
29728
29919
|
}
|
|
29729
29920
|
}
|
|
@@ -29746,7 +29937,12 @@ var BottlenecksContent = ({
|
|
|
29746
29937
|
}
|
|
29747
29938
|
} catch (error2) {
|
|
29748
29939
|
console.error(`[BottlenecksContent] Error in legacy loadAndPlayClip:`, error2);
|
|
29749
|
-
setError(
|
|
29940
|
+
setError({
|
|
29941
|
+
type: "fatal",
|
|
29942
|
+
message: "Failed to load selected clip. Please try again.",
|
|
29943
|
+
canSkip: true,
|
|
29944
|
+
canRetry: true
|
|
29945
|
+
});
|
|
29750
29946
|
setIsNavigating(false);
|
|
29751
29947
|
}
|
|
29752
29948
|
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById]);
|
|
@@ -29786,7 +29982,12 @@ var BottlenecksContent = ({
|
|
|
29786
29982
|
}
|
|
29787
29983
|
} catch (error2) {
|
|
29788
29984
|
console.error(`[handleNext] Error navigating:`, error2);
|
|
29789
|
-
setError(
|
|
29985
|
+
setError({
|
|
29986
|
+
type: "fatal",
|
|
29987
|
+
message: "Failed to navigate to next clip",
|
|
29988
|
+
canSkip: true,
|
|
29989
|
+
canRetry: true
|
|
29990
|
+
});
|
|
29790
29991
|
clearLoadingState();
|
|
29791
29992
|
}
|
|
29792
29993
|
}, [clearLoadingState, s3ClipsService]);
|
|
@@ -29822,7 +30023,12 @@ var BottlenecksContent = ({
|
|
|
29822
30023
|
}
|
|
29823
30024
|
} catch (error2) {
|
|
29824
30025
|
console.error(`[handlePrevious] Error navigating:`, error2);
|
|
29825
|
-
setError(
|
|
30026
|
+
setError({
|
|
30027
|
+
type: "fatal",
|
|
30028
|
+
message: "Failed to navigate to previous clip",
|
|
30029
|
+
canSkip: true,
|
|
30030
|
+
canRetry: true
|
|
30031
|
+
});
|
|
29826
30032
|
clearLoadingState();
|
|
29827
30033
|
}
|
|
29828
30034
|
}, [clearLoadingState, s3ClipsService]);
|
|
@@ -29835,7 +30041,7 @@ var BottlenecksContent = ({
|
|
|
29835
30041
|
const handleVideoReady = useCallback((player) => {
|
|
29836
30042
|
console.log("Video.js player ready - NOT clearing loading (wait for playing event)");
|
|
29837
30043
|
videoRetryCountRef.current = 0;
|
|
29838
|
-
if (error?.
|
|
30044
|
+
if (error?.isRetrying) {
|
|
29839
30045
|
setError(null);
|
|
29840
30046
|
}
|
|
29841
30047
|
}, [error]);
|
|
@@ -29880,20 +30086,53 @@ var BottlenecksContent = ({
|
|
|
29880
30086
|
}, [clearLoadingState]);
|
|
29881
30087
|
const handleVideoLoadingChange = useCallback((isLoading2) => {
|
|
29882
30088
|
console.log(`[BottlenecksContent] Video loading state changed: ${isLoading2}`);
|
|
30089
|
+
if (error && error.type === "fatal") {
|
|
30090
|
+
console.log(`[BottlenecksContent] Ignoring loading state change - fatal error is showing`);
|
|
30091
|
+
return;
|
|
30092
|
+
}
|
|
29883
30093
|
setIsVideoBuffering(isLoading2);
|
|
29884
|
-
}, []);
|
|
30094
|
+
}, [error]);
|
|
29885
30095
|
const handleVideoEnded = useCallback((player) => {
|
|
29886
30096
|
handleNext();
|
|
29887
30097
|
}, [handleNext]);
|
|
29888
30098
|
const videoRetryCountRef = useRef(0);
|
|
29889
|
-
const handleVideoError = useCallback((player,
|
|
29890
|
-
console.error("Video.js error:",
|
|
30099
|
+
const handleVideoError = useCallback((player, errorInfo) => {
|
|
30100
|
+
console.error("[BottlenecksContent] Video.js error:", errorInfo);
|
|
29891
30101
|
setIsPlaying(false);
|
|
30102
|
+
setIsVideoBuffering(false);
|
|
30103
|
+
const errorCode = errorInfo?.code || 0;
|
|
30104
|
+
const canRetry = errorInfo?.canRetry ?? false;
|
|
30105
|
+
const errorMessage = errorInfo?.message || "Unknown error";
|
|
30106
|
+
console.log(`[Video Error] Code: ${errorCode}, Can Retry: ${canRetry}, Message: ${errorMessage}`);
|
|
30107
|
+
if (!canRetry) {
|
|
30108
|
+
console.log("[Video Error] Non-recoverable error - showing error overlay immediately");
|
|
30109
|
+
setError({
|
|
30110
|
+
type: "fatal",
|
|
30111
|
+
code: errorCode,
|
|
30112
|
+
message: errorMessage,
|
|
30113
|
+
canSkip: true,
|
|
30114
|
+
canRetry: false
|
|
30115
|
+
});
|
|
30116
|
+
clearLoadingState();
|
|
30117
|
+
videoRetryCountRef.current = 0;
|
|
30118
|
+
trackCoreEvent("clips_video_error_non_recoverable", {
|
|
30119
|
+
workspaceId,
|
|
30120
|
+
category: activeFilterRef.current,
|
|
30121
|
+
videoId: currentVideo?.id,
|
|
30122
|
+
errorCode,
|
|
30123
|
+
errorMessage
|
|
30124
|
+
});
|
|
30125
|
+
return;
|
|
30126
|
+
}
|
|
29892
30127
|
if (videoRetryCountRef.current < 3 && currentVideo) {
|
|
29893
30128
|
videoRetryCountRef.current++;
|
|
29894
30129
|
const retryDelay = 1e3 * videoRetryCountRef.current;
|
|
29895
|
-
console.log(`[Video Error] Retrying... Attempt ${videoRetryCountRef.current}/3 in ${retryDelay}ms`);
|
|
29896
|
-
setError(
|
|
30130
|
+
console.log(`[Video Error] Recoverable error - Retrying... Attempt ${videoRetryCountRef.current}/3 in ${retryDelay}ms`);
|
|
30131
|
+
setError({
|
|
30132
|
+
type: "retrying",
|
|
30133
|
+
message: `Retrying... (${videoRetryCountRef.current}/3)`,
|
|
30134
|
+
isRetrying: true
|
|
30135
|
+
});
|
|
29897
30136
|
setTimeout(() => {
|
|
29898
30137
|
if (videoRef.current && currentVideo && isMountedRef.current) {
|
|
29899
30138
|
setError(null);
|
|
@@ -29901,16 +30140,26 @@ var BottlenecksContent = ({
|
|
|
29901
30140
|
}
|
|
29902
30141
|
}, retryDelay);
|
|
29903
30142
|
} else {
|
|
29904
|
-
|
|
30143
|
+
console.log("[Video Error] Retries exhausted - showing final error overlay");
|
|
30144
|
+
setError({
|
|
30145
|
+
type: "fatal",
|
|
30146
|
+
code: errorCode,
|
|
30147
|
+
message: errorMessage,
|
|
30148
|
+
canSkip: true,
|
|
30149
|
+
canRetry: true
|
|
30150
|
+
// Allow manual retry for network errors
|
|
30151
|
+
});
|
|
29905
30152
|
videoRetryCountRef.current = 0;
|
|
29906
30153
|
trackCoreEvent("clips_video_error_final", {
|
|
29907
30154
|
workspaceId,
|
|
29908
30155
|
category: activeFilterRef.current,
|
|
29909
30156
|
videoId: currentVideo?.id,
|
|
29910
|
-
|
|
30157
|
+
errorCode,
|
|
30158
|
+
errorMessage,
|
|
30159
|
+
attempts: 3
|
|
29911
30160
|
});
|
|
29912
30161
|
}
|
|
29913
|
-
}, [currentVideo, workspaceId]);
|
|
30162
|
+
}, [currentVideo, workspaceId, clearLoadingState]);
|
|
29914
30163
|
useEffect(() => {
|
|
29915
30164
|
isMountedRef.current = true;
|
|
29916
30165
|
return () => {
|
|
@@ -29928,9 +30177,13 @@ var BottlenecksContent = ({
|
|
|
29928
30177
|
}, [s3ClipsService]);
|
|
29929
30178
|
useEffect(() => {
|
|
29930
30179
|
if (filteredVideos.length > 0 && currentIndex < filteredVideos.length) {
|
|
30180
|
+
if (error && error.type === "fatal") {
|
|
30181
|
+
console.log("[BottlenecksContent] Not clearing fatal error on video change - let user handle it");
|
|
30182
|
+
return;
|
|
30183
|
+
}
|
|
29931
30184
|
setError(null);
|
|
29932
30185
|
}
|
|
29933
|
-
}, [currentIndex, filteredVideos]);
|
|
30186
|
+
}, [currentIndex, filteredVideos, error]);
|
|
29934
30187
|
useEffect(() => {
|
|
29935
30188
|
if (!isTransitioning && pendingVideo) {
|
|
29936
30189
|
const timer = setTimeout(() => {
|
|
@@ -30005,11 +30258,11 @@ var BottlenecksContent = ({
|
|
|
30005
30258
|
if ((isLoading || clipTypesLoading) && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
30006
30259
|
return /* @__PURE__ */ jsx("div", { className: "flex-grow p-4 flex items-center justify-center h-[calc(100vh-12rem)]", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading clips..." }) });
|
|
30007
30260
|
}
|
|
30008
|
-
if (error || clipTypesError) {
|
|
30261
|
+
if (error && error.type === "fatal" && !hasInitialLoad || clipTypesError) {
|
|
30009
30262
|
return /* @__PURE__ */ jsxs("div", { className: "flex-grow p-4 flex flex-col items-center justify-center h-[calc(100vh-12rem)] text-center", children: [
|
|
30010
30263
|
/* @__PURE__ */ jsx(XCircle, { className: "w-12 h-12 text-red-400 mb-3" }),
|
|
30011
30264
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-red-700 mb-1", children: "Error Loading Clips" }),
|
|
30012
|
-
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: error || clipTypesError })
|
|
30265
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: error?.message || clipTypesError })
|
|
30013
30266
|
] });
|
|
30014
30267
|
}
|
|
30015
30268
|
const categoriesToShow = clipTypes.length > 0 ? clipTypes : [];
|
|
@@ -30056,7 +30309,7 @@ var BottlenecksContent = ({
|
|
|
30056
30309
|
),
|
|
30057
30310
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
30058
30311
|
/* @__PURE__ */ jsx("span", { className: "text-sm px-2 py-1 bg-blue-50 text-blue-700 rounded-full font-medium tabular-nums", children: categoryMetadata.length > 0 ? `${currentMetadataIndex + 1} / ${categoryMetadata.length}` : "0 / 0" }),
|
|
30059
|
-
error && /* @__PURE__ */ jsx("span", { className: "text-xs text-
|
|
30312
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsx("span", { className: "text-xs text-orange-600 font-medium", children: error.message })
|
|
30060
30313
|
] }),
|
|
30061
30314
|
/* @__PURE__ */ jsx(
|
|
30062
30315
|
"button",
|
|
@@ -30070,7 +30323,6 @@ var BottlenecksContent = ({
|
|
|
30070
30323
|
)
|
|
30071
30324
|
] })
|
|
30072
30325
|
] }) }),
|
|
30073
|
-
/* Show video if we have filtered videos and current video, or show loading */
|
|
30074
30326
|
filteredVideos.length > 0 && currentVideo ? /* @__PURE__ */ jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
|
|
30075
30327
|
/* @__PURE__ */ jsx(
|
|
30076
30328
|
CroppedVideoPlayer,
|
|
@@ -30102,30 +30354,44 @@ var BottlenecksContent = ({
|
|
|
30102
30354
|
}
|
|
30103
30355
|
}
|
|
30104
30356
|
),
|
|
30105
|
-
(isTransitioning || isVideoBuffering && isInitialLoading) && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30106
|
-
!isTransitioning && isVideoBuffering && !isInitialLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30107
|
-
error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black/
|
|
30357
|
+
(isTransitioning || isVideoBuffering && isInitialLoading) && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30358
|
+
!isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30359
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-40 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
30360
|
+
/* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md" }),
|
|
30361
|
+
/* @__PURE__ */ jsx("p", { className: "text-white text-sm mt-4 font-medium", children: error.message })
|
|
30362
|
+
] }) }),
|
|
30363
|
+
error && error.type === "fatal" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/90 text-white p-4", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-md", children: [
|
|
30108
30364
|
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto mb-4 text-red-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 16.5c-.77.833.192 2.5 1.732 2.5z" }) }),
|
|
30109
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "
|
|
30110
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-
|
|
30111
|
-
/* @__PURE__ */ jsxs("
|
|
30112
|
-
/* @__PURE__ */ jsx(
|
|
30113
|
-
|
|
30114
|
-
|
|
30115
|
-
|
|
30116
|
-
|
|
30117
|
-
|
|
30118
|
-
|
|
30119
|
-
|
|
30120
|
-
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30365
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: error.code === 3 ? "Stream Corrupted" : error.code === 4 ? "Format Not Supported" : error.code === 2 ? "Network Error" : error.code === 1 ? "Loading Interrupted" : "Playback Error" }),
|
|
30366
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-6", children: error.message }),
|
|
30367
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
30368
|
+
error.canSkip && /* @__PURE__ */ jsx(
|
|
30369
|
+
"button",
|
|
30370
|
+
{
|
|
30371
|
+
onClick: () => {
|
|
30372
|
+
setError(null);
|
|
30373
|
+
videoRetryCountRef.current = 0;
|
|
30374
|
+
handleNext();
|
|
30375
|
+
},
|
|
30376
|
+
className: "px-5 py-2.5 bg-blue-600 hover:bg-blue-700 rounded-md text-sm font-medium transition-colors",
|
|
30377
|
+
children: "Skip to Next Clip"
|
|
30378
|
+
}
|
|
30379
|
+
),
|
|
30380
|
+
error.canRetry && /* @__PURE__ */ jsx(
|
|
30381
|
+
"button",
|
|
30382
|
+
{
|
|
30383
|
+
onClick: () => {
|
|
30384
|
+
setError(null);
|
|
30385
|
+
videoRetryCountRef.current = 0;
|
|
30386
|
+
if (videoRef.current) {
|
|
30387
|
+
videoRef.current.dispose();
|
|
30388
|
+
}
|
|
30389
|
+
},
|
|
30390
|
+
className: "px-5 py-2.5 bg-gray-600 hover:bg-gray-700 rounded-md text-sm font-medium transition-colors",
|
|
30391
|
+
children: "Retry"
|
|
30392
|
+
}
|
|
30393
|
+
)
|
|
30394
|
+
] })
|
|
30129
30395
|
] }) }),
|
|
30130
30396
|
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
30131
30397
|
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" || currentVideo.type === "idle_time" ? "bg-purple-400" : isPercentileCategory(activeFilterRef.current) ? activeFilterRef.current === "fast-cycles" ? "bg-green-600" : activeFilterRef.current === "slow-cycles" ? "bg-red-700" : "bg-orange-500" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-gray-500"} mr-2 animate-pulse` }),
|
|
@@ -36859,6 +37125,8 @@ function HomeView({
|
|
|
36859
37125
|
const [errorMessage, setErrorMessage] = useState(null);
|
|
36860
37126
|
const [displayNamesInitialized, setDisplayNamesInitialized] = useState(false);
|
|
36861
37127
|
const [hasInitialDataLoaded, setHasInitialDataLoaded] = useState(false);
|
|
37128
|
+
const [axelSuggestion, setAxelSuggestion] = useState(null);
|
|
37129
|
+
const [showAxelNotification, setShowAxelNotification] = useState(false);
|
|
36862
37130
|
const dashboardConfig = useDashboardConfig();
|
|
36863
37131
|
const timezone = useAppTimezone();
|
|
36864
37132
|
useEffect(() => {
|
|
@@ -36933,12 +37201,7 @@ function HomeView({
|
|
|
36933
37201
|
}, []);
|
|
36934
37202
|
const handleWorkspaceHoverEnd = useCallback((workspaceId) => {
|
|
36935
37203
|
}, []);
|
|
36936
|
-
const memoizedWorkspaceMetrics =
|
|
36937
|
-
// Only update reference if meaningful properties change
|
|
36938
|
-
workspaceMetrics.length,
|
|
36939
|
-
// Use stable string representation instead of spreading array
|
|
36940
|
-
JSON.stringify(workspaceMetrics.map((w) => `${w.workspace_uuid}-${Math.round(w.efficiency)}-${w.trend}`))
|
|
36941
|
-
]);
|
|
37204
|
+
const memoizedWorkspaceMetrics = workspaceMetrics;
|
|
36942
37205
|
const memoizedKPIs = useMemo(() => kpis, [
|
|
36943
37206
|
// Only update reference when values change by at least 1%
|
|
36944
37207
|
kpis?.efficiency?.value ? Math.round(kpis.efficiency.value) : null,
|
|
@@ -36966,6 +37229,9 @@ function HomeView({
|
|
|
36966
37229
|
setIsChangingFilter(true);
|
|
36967
37230
|
setSelectedLineId(value);
|
|
36968
37231
|
}, []);
|
|
37232
|
+
const handleDismissAxelNotification = useCallback(() => {
|
|
37233
|
+
setShowAxelNotification(false);
|
|
37234
|
+
}, []);
|
|
36969
37235
|
useEffect(() => {
|
|
36970
37236
|
if (!metricsLoading && !kpisLoading && isChangingFilter) {
|
|
36971
37237
|
if (workspaceMetrics.length > 0 || selectedLineId === factoryViewId) {
|
|
@@ -37077,6 +37343,14 @@ function HomeView({
|
|
|
37077
37343
|
lineNames,
|
|
37078
37344
|
isVisible: !breaksLoading && !breaksError
|
|
37079
37345
|
}
|
|
37346
|
+
),
|
|
37347
|
+
/* @__PURE__ */ jsx(
|
|
37348
|
+
AxelNotificationPopup,
|
|
37349
|
+
{
|
|
37350
|
+
suggestion: axelSuggestion,
|
|
37351
|
+
isVisible: showAxelNotification,
|
|
37352
|
+
onDismiss: handleDismissAxelNotification
|
|
37353
|
+
}
|
|
37080
37354
|
)
|
|
37081
37355
|
] })
|
|
37082
37356
|
}
|
|
@@ -38510,7 +38784,7 @@ var KPIsOverviewView = ({
|
|
|
38510
38784
|
var KPIsOverviewView_default = KPIsOverviewView;
|
|
38511
38785
|
var IsolatedTimer = memo(() => {
|
|
38512
38786
|
return /* @__PURE__ */ jsx(ISTTimer_default, {});
|
|
38513
|
-
}
|
|
38787
|
+
});
|
|
38514
38788
|
IsolatedTimer.displayName = "IsolatedTimer";
|
|
38515
38789
|
var HeaderRibbon = memo(({
|
|
38516
38790
|
currentDate,
|
|
@@ -38518,42 +38792,49 @@ var HeaderRibbon = memo(({
|
|
|
38518
38792
|
shiftId,
|
|
38519
38793
|
getShiftIcon,
|
|
38520
38794
|
getShiftName
|
|
38521
|
-
}) =>
|
|
38522
|
-
|
|
38523
|
-
|
|
38524
|
-
|
|
38525
|
-
|
|
38526
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children:
|
|
38795
|
+
}) => {
|
|
38796
|
+
const shiftIcon = useMemo(() => getShiftIcon(shiftId), [getShiftIcon, shiftId]);
|
|
38797
|
+
const shiftName = useMemo(() => getShiftName(shiftId), [getShiftName, shiftId]);
|
|
38798
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
38799
|
+
/* @__PURE__ */ jsxs("div", { className: "sm:hidden mt-3 flex items-center justify-center gap-2", children: [
|
|
38800
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-gray-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: currentMobileDate }) }),
|
|
38801
|
+
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
|
|
38802
|
+
/* @__PURE__ */ jsx("div", { className: "text-gray-700 scale-90", children: shiftIcon }),
|
|
38803
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: shiftName })
|
|
38804
|
+
] }),
|
|
38805
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsx(IsolatedTimer, {}) }) })
|
|
38527
38806
|
] }),
|
|
38528
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
38529
|
-
|
|
38530
|
-
|
|
38531
|
-
|
|
38532
|
-
|
|
38533
|
-
|
|
38534
|
-
|
|
38535
|
-
|
|
38536
|
-
|
|
38537
|
-
|
|
38538
|
-
|
|
38539
|
-
" Shift"
|
|
38807
|
+
/* @__PURE__ */ jsx("div", { className: "hidden sm:block mt-3 bg-blue-50 px-3 py-2 rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-center gap-3 md:gap-4", children: [
|
|
38808
|
+
/* @__PURE__ */ jsx("div", { className: "text-base md:text-lg font-medium text-blue-600", children: /* @__PURE__ */ jsx(IsolatedTimer, {}) }),
|
|
38809
|
+
/* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" }),
|
|
38810
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: currentDate }),
|
|
38811
|
+
/* @__PURE__ */ jsx("div", { className: "w-px h-4 bg-blue-300" }),
|
|
38812
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38813
|
+
/* @__PURE__ */ jsx("div", { className: "text-blue-600", children: shiftIcon }),
|
|
38814
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
|
|
38815
|
+
shiftName,
|
|
38816
|
+
" Shift"
|
|
38817
|
+
] })
|
|
38540
38818
|
] })
|
|
38541
|
-
] })
|
|
38542
|
-
] })
|
|
38543
|
-
|
|
38819
|
+
] }) })
|
|
38820
|
+
] });
|
|
38821
|
+
});
|
|
38544
38822
|
HeaderRibbon.displayName = "HeaderRibbon";
|
|
38545
38823
|
var MobileWorkspaceCard = memo(({
|
|
38546
38824
|
workspace,
|
|
38547
38825
|
rank,
|
|
38548
38826
|
cardClass,
|
|
38549
38827
|
onWorkspaceClick,
|
|
38550
|
-
getMedalIcon
|
|
38551
|
-
getLineName
|
|
38828
|
+
getMedalIcon
|
|
38552
38829
|
}) => /* @__PURE__ */ jsxs(
|
|
38553
38830
|
"div",
|
|
38554
38831
|
{
|
|
38555
38832
|
onClick: () => onWorkspaceClick(workspace, rank),
|
|
38556
|
-
className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] transition-all cursor-pointer`,
|
|
38833
|
+
className: `${cardClass} p-3 rounded-lg border shadow-sm active:scale-[0.98] transition-all duration-300 cursor-pointer`,
|
|
38834
|
+
style: {
|
|
38835
|
+
willChange: "opacity, transform",
|
|
38836
|
+
animation: "fadeIn 0.3s ease-in-out"
|
|
38837
|
+
},
|
|
38557
38838
|
children: [
|
|
38558
38839
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
38559
38840
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
@@ -38565,8 +38846,8 @@ var MobileWorkspaceCard = memo(({
|
|
|
38565
38846
|
getMedalIcon(rank)
|
|
38566
38847
|
] }),
|
|
38567
38848
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
38568
|
-
/* @__PURE__ */ jsx("div", { className: "font-semibold text-gray-900", children:
|
|
38569
|
-
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children:
|
|
38849
|
+
/* @__PURE__ */ jsx("div", { className: "font-semibold text-gray-900", children: workspace.displayName }),
|
|
38850
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: workspace.lineName })
|
|
38570
38851
|
] })
|
|
38571
38852
|
] }),
|
|
38572
38853
|
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
@@ -38596,27 +38877,32 @@ var MobileWorkspaceCard = memo(({
|
|
|
38596
38877
|
] })
|
|
38597
38878
|
]
|
|
38598
38879
|
}
|
|
38599
|
-
))
|
|
38880
|
+
), (prevProps, nextProps) => {
|
|
38881
|
+
return prevProps.rank === nextProps.rank && prevProps.cardClass === nextProps.cardClass && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick && prevProps.getMedalIcon === nextProps.getMedalIcon;
|
|
38882
|
+
});
|
|
38600
38883
|
MobileWorkspaceCard.displayName = "MobileWorkspaceCard";
|
|
38601
38884
|
var DesktopWorkspaceRow = memo(({
|
|
38602
38885
|
workspace,
|
|
38603
38886
|
index,
|
|
38604
38887
|
rowClass,
|
|
38605
38888
|
onWorkspaceClick,
|
|
38606
|
-
getMedalIcon
|
|
38607
|
-
getLineName
|
|
38889
|
+
getMedalIcon
|
|
38608
38890
|
}) => /* @__PURE__ */ jsxs(
|
|
38609
38891
|
"tr",
|
|
38610
38892
|
{
|
|
38611
38893
|
onClick: () => onWorkspaceClick(workspace, index + 1),
|
|
38612
|
-
className: `${rowClass} hover:bg-gray-50/90 transition-
|
|
38894
|
+
className: `${rowClass} hover:bg-gray-50/90 transition-all duration-300 cursor-pointer group`,
|
|
38895
|
+
style: {
|
|
38896
|
+
willChange: "opacity, background-color",
|
|
38897
|
+
animation: "fadeIn 0.3s ease-in-out"
|
|
38898
|
+
},
|
|
38613
38899
|
children: [
|
|
38614
38900
|
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap group-hover:font-medium", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
38615
38901
|
/* @__PURE__ */ jsx("span", { children: index + 1 }),
|
|
38616
38902
|
getMedalIcon(index + 1)
|
|
38617
38903
|
] }) }),
|
|
38618
|
-
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children:
|
|
38619
|
-
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children:
|
|
38904
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: workspace.displayName }) }),
|
|
38905
|
+
/* @__PURE__ */ jsx("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base whitespace-nowrap", children: /* @__PURE__ */ jsx("div", { className: "font-medium", children: workspace.lineName }) }),
|
|
38620
38906
|
/* @__PURE__ */ jsxs("td", { className: "px-3 py-2.5 sm:p-4 text-sm sm:text-base font-medium whitespace-nowrap", children: [
|
|
38621
38907
|
(workspace.efficiency || 0).toFixed(1),
|
|
38622
38908
|
"%"
|
|
@@ -38634,7 +38920,9 @@ var DesktopWorkspaceRow = memo(({
|
|
|
38634
38920
|
] })
|
|
38635
38921
|
]
|
|
38636
38922
|
}
|
|
38637
|
-
))
|
|
38923
|
+
), (prevProps, nextProps) => {
|
|
38924
|
+
return prevProps.index === nextProps.index && prevProps.rowClass === nextProps.rowClass && prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.efficiency === nextProps.workspace.efficiency && prevProps.workspace.action_count === nextProps.workspace.action_count && prevProps.workspace.action_threshold === nextProps.workspace.action_threshold && prevProps.workspace.avg_cycle_time === nextProps.workspace.avg_cycle_time && prevProps.workspace.displayName === nextProps.workspace.displayName && prevProps.workspace.lineName === nextProps.workspace.lineName && prevProps.onWorkspaceClick === nextProps.onWorkspaceClick && prevProps.getMedalIcon === nextProps.getMedalIcon;
|
|
38925
|
+
});
|
|
38638
38926
|
DesktopWorkspaceRow.displayName = "DesktopWorkspaceRow";
|
|
38639
38927
|
var LeaderboardDetailView = memo(({
|
|
38640
38928
|
lineId,
|
|
@@ -38650,6 +38938,13 @@ var LeaderboardDetailView = memo(({
|
|
|
38650
38938
|
const navigation = useNavigation();
|
|
38651
38939
|
const entityConfig = useEntityConfig();
|
|
38652
38940
|
const [sortAscending, setSortAscending] = useState(false);
|
|
38941
|
+
const [isMobile, setIsMobile] = useState(false);
|
|
38942
|
+
React21__default.useEffect(() => {
|
|
38943
|
+
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
38944
|
+
checkMobile();
|
|
38945
|
+
window.addEventListener("resize", checkMobile);
|
|
38946
|
+
return () => window.removeEventListener("resize", checkMobile);
|
|
38947
|
+
}, []);
|
|
38653
38948
|
const configuredLineNames = useMemo(() => {
|
|
38654
38949
|
return getAllLineDisplayNames(entityConfig);
|
|
38655
38950
|
}, [entityConfig]);
|
|
@@ -38667,18 +38962,10 @@ var LeaderboardDetailView = memo(({
|
|
|
38667
38962
|
const handleSortToggle = useCallback(() => {
|
|
38668
38963
|
setSortAscending(!sortAscending);
|
|
38669
38964
|
}, [sortAscending]);
|
|
38670
|
-
const
|
|
38671
|
-
|
|
38672
|
-
|
|
38673
|
-
|
|
38674
|
-
}), [lineId, date, shift]);
|
|
38675
|
-
const {
|
|
38676
|
-
metrics: metrics2,
|
|
38677
|
-
lineDetails,
|
|
38678
|
-
loading: metricsLoading,
|
|
38679
|
-
error: metricsError,
|
|
38680
|
-
refreshMetrics
|
|
38681
|
-
} = useRealtimeLineMetrics(realtimeMetricsParams);
|
|
38965
|
+
const shiftId = useMemo(
|
|
38966
|
+
() => typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
|
|
38967
|
+
[shift]
|
|
38968
|
+
);
|
|
38682
38969
|
const {
|
|
38683
38970
|
workspaces,
|
|
38684
38971
|
loading: workspacesLoading,
|
|
@@ -38688,12 +38975,12 @@ var LeaderboardDetailView = memo(({
|
|
|
38688
38975
|
initialDate: date,
|
|
38689
38976
|
initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0
|
|
38690
38977
|
});
|
|
38691
|
-
const getShiftName = useCallback((
|
|
38692
|
-
if (
|
|
38693
|
-
return
|
|
38978
|
+
const getShiftName = useCallback((shiftId2) => {
|
|
38979
|
+
if (shiftId2 === void 0) return "Day";
|
|
38980
|
+
return shiftId2 === 0 ? "Day" : "Night";
|
|
38694
38981
|
}, []);
|
|
38695
|
-
const getShiftIcon = useCallback((
|
|
38696
|
-
const shift2 = getShiftName(
|
|
38982
|
+
const getShiftIcon = useCallback((shiftId2) => {
|
|
38983
|
+
const shift2 = getShiftName(shiftId2);
|
|
38697
38984
|
if (shift2 === "Day") {
|
|
38698
38985
|
return /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" }) });
|
|
38699
38986
|
} else {
|
|
@@ -38735,17 +39022,18 @@ var LeaderboardDetailView = memo(({
|
|
|
38735
39022
|
return null;
|
|
38736
39023
|
}
|
|
38737
39024
|
}, [sortAscending]);
|
|
39025
|
+
const workspacesLength = useMemo(() => workspaces?.length || 0, [workspaces?.length]);
|
|
38738
39026
|
const handleWorkspaceClick = useCallback((workspace, rank) => {
|
|
38739
39027
|
trackCoreEvent("Workspace from Leaderboard Clicked", {
|
|
38740
39028
|
workspace_name: workspace.workspace_name,
|
|
38741
39029
|
workspace_id: workspace.workspace_uuid,
|
|
38742
39030
|
rank,
|
|
38743
|
-
total_workspaces:
|
|
39031
|
+
total_workspaces: workspacesLength,
|
|
38744
39032
|
efficiency: workspace.efficiency,
|
|
38745
39033
|
action_count: workspace.action_count,
|
|
38746
39034
|
action_threshold: workspace.action_threshold
|
|
38747
39035
|
});
|
|
38748
|
-
const displayName = getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
39036
|
+
const displayName = workspace.displayName || getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
38749
39037
|
const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName, workspace.line_id) : "";
|
|
38750
39038
|
const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
|
|
38751
39039
|
if (onWorkspaceClick) {
|
|
@@ -38753,20 +39041,33 @@ var LeaderboardDetailView = memo(({
|
|
|
38753
39041
|
} else {
|
|
38754
39042
|
navigation.navigate(`/workspace/${workspace.workspace_uuid}${navParams}${returnToParam}`);
|
|
38755
39043
|
}
|
|
38756
|
-
}, [onWorkspaceClick, navigation, lineId,
|
|
38757
|
-
const
|
|
39044
|
+
}, [onWorkspaceClick, navigation, lineId, workspacesLength]);
|
|
39045
|
+
const workspaceDisplayData = useMemo(() => {
|
|
38758
39046
|
if (!workspaces) return [];
|
|
38759
|
-
return
|
|
39047
|
+
return workspaces.map((ws) => ({
|
|
39048
|
+
...ws,
|
|
39049
|
+
displayName: getWorkspaceDisplayName(ws.workspace_name, ws.line_id),
|
|
39050
|
+
lineName: getLineName(ws.line_id)
|
|
39051
|
+
}));
|
|
39052
|
+
}, [workspaces, getLineName]);
|
|
39053
|
+
const sortedWorkspaces = useMemo(() => {
|
|
39054
|
+
return [...workspaceDisplayData].sort((a, b) => {
|
|
38760
39055
|
const effA = a.efficiency || 0;
|
|
38761
39056
|
const effB = b.efficiency || 0;
|
|
38762
39057
|
return sortAscending ? effA - effB : effB - effA;
|
|
38763
39058
|
});
|
|
38764
|
-
}, [
|
|
38765
|
-
const loading =
|
|
38766
|
-
const error =
|
|
38767
|
-
const currentDateFormatted = useMemo(() =>
|
|
38768
|
-
|
|
38769
|
-
|
|
39059
|
+
}, [workspaceDisplayData, sortAscending]);
|
|
39060
|
+
const loading = workspacesLoading;
|
|
39061
|
+
const error = workspacesError;
|
|
39062
|
+
const currentDateFormatted = useMemo(() => {
|
|
39063
|
+
const dateStr = (/* @__PURE__ */ new Date()).toDateString();
|
|
39064
|
+
return formatDate(new Date(dateStr));
|
|
39065
|
+
}, [formatDate, date]);
|
|
39066
|
+
const currentMobileDateFormatted = useMemo(() => {
|
|
39067
|
+
const dateStr = (/* @__PURE__ */ new Date()).toDateString();
|
|
39068
|
+
return formatMobileDate(new Date(dateStr));
|
|
39069
|
+
}, [formatMobileDate, date]);
|
|
39070
|
+
if (loading && (!workspaces || workspaces.length === 0)) {
|
|
38770
39071
|
return /* @__PURE__ */ jsx("div", { className: `h-[calc(100vh-64px)] flex items-center justify-center bg-slate-50 ${className}`, children: /* @__PURE__ */ jsx("div", { className: "text-xl text-gray-600", children: "Loading workspaces..." }) });
|
|
38771
39072
|
}
|
|
38772
39073
|
if (error) {
|
|
@@ -38775,7 +39076,7 @@ var LeaderboardDetailView = memo(({
|
|
|
38775
39076
|
error.message
|
|
38776
39077
|
] }) });
|
|
38777
39078
|
}
|
|
38778
|
-
return /* @__PURE__ */ jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, children: [
|
|
39079
|
+
return /* @__PURE__ */ jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, style: { willChange: "contents" }, children: [
|
|
38779
39080
|
/* @__PURE__ */ jsx("div", { className: "sticky top-0 z-20 bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxs("div", { className: "px-3 sm:px-6 md:px-8 py-2 sm:py-2.5", children: [
|
|
38780
39081
|
/* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
38781
39082
|
/* @__PURE__ */ jsx(
|
|
@@ -38867,31 +39168,30 @@ var LeaderboardDetailView = memo(({
|
|
|
38867
39168
|
{
|
|
38868
39169
|
currentDate: currentDateFormatted,
|
|
38869
39170
|
currentMobileDate: currentMobileDateFormatted,
|
|
38870
|
-
shiftId
|
|
39171
|
+
shiftId,
|
|
38871
39172
|
getShiftIcon,
|
|
38872
39173
|
getShiftName
|
|
38873
39174
|
}
|
|
38874
39175
|
)
|
|
38875
39176
|
] }) }),
|
|
38876
|
-
/* @__PURE__ */
|
|
38877
|
-
|
|
38878
|
-
|
|
38879
|
-
|
|
38880
|
-
|
|
38881
|
-
|
|
38882
|
-
|
|
38883
|
-
|
|
38884
|
-
|
|
38885
|
-
|
|
38886
|
-
|
|
38887
|
-
|
|
38888
|
-
|
|
38889
|
-
|
|
38890
|
-
|
|
38891
|
-
|
|
38892
|
-
|
|
38893
|
-
|
|
38894
|
-
/* @__PURE__ */ jsx("div", { className: "hidden sm:block bg-white rounded-lg shadow-md overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse table-auto", children: [
|
|
39177
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 w-full mx-auto p-3 sm:p-4 md:p-6", children: isMobile ? /* @__PURE__ */ jsx("div", { className: "space-y-3", children: sortedWorkspaces.map((ws, index) => {
|
|
39178
|
+
const rank = index + 1;
|
|
39179
|
+
const isTopThree = index < 3;
|
|
39180
|
+
const cardClass = sortAscending ? isTopThree ? "bg-red-50/90 border-red-200" : "bg-white" : isTopThree ? "bg-green-50/90 border-green-200" : "bg-white";
|
|
39181
|
+
return /* @__PURE__ */ jsx(
|
|
39182
|
+
MobileWorkspaceCard,
|
|
39183
|
+
{
|
|
39184
|
+
workspace: ws,
|
|
39185
|
+
rank,
|
|
39186
|
+
cardClass,
|
|
39187
|
+
onWorkspaceClick: handleWorkspaceClick,
|
|
39188
|
+
getMedalIcon
|
|
39189
|
+
},
|
|
39190
|
+
ws.workspace_uuid
|
|
39191
|
+
);
|
|
39192
|
+
}) }) : (
|
|
39193
|
+
/* Desktop table view - only render on desktop */
|
|
39194
|
+
/* @__PURE__ */ jsx("div", { className: "bg-white rounded-lg shadow-md overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxs("table", { className: "w-full border-collapse table-auto", children: [
|
|
38895
39195
|
/* @__PURE__ */ jsx("thead", { className: "bg-gray-50 border-b border-gray-200 sticky top-0 z-10", children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
38896
39196
|
/* @__PURE__ */ jsx("th", { className: "px-3 py-2.5 sm:p-4 text-left text-xs sm:text-sm font-semibold text-gray-600 whitespace-nowrap", children: "Rank" }),
|
|
38897
39197
|
/* @__PURE__ */ jsx("th", { className: "px-3 py-2.5 sm:p-4 text-left text-xs sm:text-sm font-semibold text-gray-600 whitespace-nowrap", children: "Workspace" }),
|
|
@@ -38910,17 +39210,16 @@ var LeaderboardDetailView = memo(({
|
|
|
38910
39210
|
index,
|
|
38911
39211
|
rowClass,
|
|
38912
39212
|
onWorkspaceClick: handleWorkspaceClick,
|
|
38913
|
-
getMedalIcon
|
|
38914
|
-
getLineName
|
|
39213
|
+
getMedalIcon
|
|
38915
39214
|
},
|
|
38916
39215
|
ws.workspace_uuid
|
|
38917
39216
|
);
|
|
38918
39217
|
}) })
|
|
38919
39218
|
] }) }) })
|
|
38920
|
-
|
|
39219
|
+
) })
|
|
38921
39220
|
] });
|
|
38922
39221
|
}, (prevProps, nextProps) => {
|
|
38923
|
-
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className
|
|
39222
|
+
return prevProps.lineId === nextProps.lineId && prevProps.date === nextProps.date && prevProps.shift === nextProps.shift && prevProps.line1Id === nextProps.line1Id && prevProps.line2Id === nextProps.line2Id && JSON.stringify(prevProps.lineNames) === JSON.stringify(nextProps.lineNames) && prevProps.className === nextProps.className;
|
|
38924
39223
|
});
|
|
38925
39224
|
LeaderboardDetailView.displayName = "LeaderboardDetailView";
|
|
38926
39225
|
var LeaderboardDetailViewWithDisplayNames = withAllWorkspaceDisplayNames(LeaderboardDetailView);
|
|
@@ -40029,16 +40328,8 @@ var ACTION_NAMES = {
|
|
|
40029
40328
|
// src/views/TargetsView.utils.ts
|
|
40030
40329
|
var calculatePPH = (cycleTime, breaks = [], shiftHours = 0) => {
|
|
40031
40330
|
if (cycleTime === "" || cycleTime === 0) return "";
|
|
40032
|
-
const
|
|
40033
|
-
|
|
40034
|
-
return Number(basicPPH.toFixed(1));
|
|
40035
|
-
}
|
|
40036
|
-
const safeBreaks = Array.isArray(breaks) ? breaks : [];
|
|
40037
|
-
const totalBreakMinutes = safeBreaks.reduce((total, breakItem) => total + breakItem.duration, 0);
|
|
40038
|
-
const totalBreakHours = totalBreakMinutes / 60;
|
|
40039
|
-
const realWorkHours = shiftHours - totalBreakHours;
|
|
40040
|
-
const effectivePPH = basicPPH * (realWorkHours / shiftHours);
|
|
40041
|
-
return Number(effectivePPH.toFixed(1));
|
|
40331
|
+
const pph = 3600 / cycleTime;
|
|
40332
|
+
return Number(pph.toFixed(1));
|
|
40042
40333
|
};
|
|
40043
40334
|
var calculateDayOutput = (pph, shiftHours, breaks = []) => {
|
|
40044
40335
|
if (pph === "") return "";
|
|
@@ -42634,7 +42925,7 @@ var WorkspaceDetailView = ({
|
|
|
42634
42925
|
/* @__PURE__ */ jsxs(Card2, { children: [
|
|
42635
42926
|
/* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
42636
42927
|
/* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
42637
|
-
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42928
|
+
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42638
42929
|
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
42639
42930
|
"Standard: ",
|
|
42640
42931
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -42754,7 +43045,7 @@ var WorkspaceDetailView = ({
|
|
|
42754
43045
|
/* @__PURE__ */ jsxs(Card2, { children: [
|
|
42755
43046
|
/* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
42756
43047
|
/* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
42757
|
-
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
43048
|
+
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42758
43049
|
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
42759
43050
|
"Standard: ",
|
|
42760
43051
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -44080,4 +44371,4 @@ function shuffleArray(array) {
|
|
|
44080
44371
|
return shuffled;
|
|
44081
44372
|
}
|
|
44082
44373
|
|
|
44083
|
-
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedWorkspaceHealthView, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, CroppedVideoPlayer, 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_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UserService, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAccessControl, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealth, useWorkspaceHealthById, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|
|
44374
|
+
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedWorkspaceHealthView, AxelNotificationPopup, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, CroppedVideoPlayer, 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_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, MainLayout, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UserService, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, apiUtils, authCoreService, authOTPService, authRateLimitService, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, optifyeAgentClient, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, updateThreadTitle, useAccessControl, useActiveBreaks, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealth, useWorkspaceHealthById, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|