@optifye/dashboard-core 5.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +89 -17
- package/dist/index.d.ts +89 -17
- package/dist/index.js +459 -328
- package/dist/index.mjs +458 -329
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -79,12 +79,15 @@ var DEFAULT_DATABASE_CONFIG = {
|
|
|
79
79
|
}
|
|
80
80
|
};
|
|
81
81
|
var DEFAULT_ENTITY_CONFIG = {
|
|
82
|
-
companyId:
|
|
83
|
-
factoryId:
|
|
84
|
-
defaultLineId:
|
|
85
|
-
secondaryLineId:
|
|
82
|
+
companyId: "87ca8ebc-ef29-4543-9e12-efc526a9b669",
|
|
83
|
+
factoryId: "b3e44be4-730e-4276-b2ce-701c79d66ffa",
|
|
84
|
+
defaultLineId: "98a2287e-8d55-4020-b00d-b9940437e3e1",
|
|
85
|
+
secondaryLineId: "d93997bb-ecac-4478-a4a6-008d536b724c",
|
|
86
86
|
factoryViewId: "factory",
|
|
87
|
-
lineNames: {
|
|
87
|
+
lineNames: {
|
|
88
|
+
"98a2287e-8d55-4020-b00d-b9940437e3e1": "Cell 8",
|
|
89
|
+
"d93997bb-ecac-4478-a4a6-008d536b724c": "Cell 7"
|
|
90
|
+
}
|
|
88
91
|
};
|
|
89
92
|
var DEFAULT_SHIFT_CONFIG = {
|
|
90
93
|
dayShift: {
|
|
@@ -101,9 +104,12 @@ var DEFAULT_SHIFT_CONFIG = {
|
|
|
101
104
|
};
|
|
102
105
|
var DEFAULT_WORKSPACE_CONFIG = {
|
|
103
106
|
displayNames: {
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
+
"Cell 8 WS1": "Swaging 1",
|
|
108
|
+
"Cell 8 WS2": "Bond Testing 1",
|
|
109
|
+
"Cell 8 WS3": "QA Check 1",
|
|
110
|
+
"Cell 7 WS1": "Swaging 2",
|
|
111
|
+
"Cell 7 WS2": "Bond Testing 2",
|
|
112
|
+
"Cell 7 WS3": "QA Check 2"
|
|
107
113
|
},
|
|
108
114
|
specialWorkspaces: {
|
|
109
115
|
startId: 19,
|
|
@@ -160,7 +166,8 @@ var DEFAULT_VIDEO_CONFIG = {
|
|
|
160
166
|
useRAF: true
|
|
161
167
|
}
|
|
162
168
|
};
|
|
163
|
-
var LINE_1_UUID = "
|
|
169
|
+
var LINE_1_UUID = "98a2287e-8d55-4020-b00d-b9940437e3e1";
|
|
170
|
+
var LINE_2_UUID = "d93997bb-ecac-4478-a4a6-008d536b724c";
|
|
164
171
|
var DEFAULT_CONFIG = {
|
|
165
172
|
apiBaseUrl: void 0,
|
|
166
173
|
// No default base URL
|
|
@@ -1020,7 +1027,7 @@ var dashboardService = {
|
|
|
1020
1027
|
const formattedStartDate = formatDate(startDate);
|
|
1021
1028
|
const formattedEndDate = formatDate(endDate);
|
|
1022
1029
|
try {
|
|
1023
|
-
const { data, error } = await supabase.from(metricsTable).select("date, shift_id, efficiency, total_output, avg_cycle_time, ideal_output, avg_pph, pph_threshold, workspace_rank").eq("workspace_id", workspaceUuid).gte("date", formattedStartDate).lte("date", formattedEndDate).order("date", { ascending: true }).order("shift_id", { ascending: true });
|
|
1030
|
+
const { data, error } = await supabase.from(metricsTable).select("date, shift_id, efficiency, total_output, avg_cycle_time, ideal_output, avg_pph, pph_threshold, workspace_rank, idle_time").eq("workspace_id", workspaceUuid).gte("date", formattedStartDate).lte("date", formattedEndDate).order("date", { ascending: true }).order("shift_id", { ascending: true });
|
|
1024
1031
|
if (error) throw error;
|
|
1025
1032
|
if (!data) return [];
|
|
1026
1033
|
const transformedData = data.map((item) => ({
|
|
@@ -1033,7 +1040,8 @@ var dashboardService = {
|
|
|
1033
1040
|
ideal_output: item.ideal_output || 0,
|
|
1034
1041
|
avg_pph: item.avg_pph || 0,
|
|
1035
1042
|
pph_threshold: item.pph_threshold || 0,
|
|
1036
|
-
workspace_rank: item.workspace_rank || 0
|
|
1043
|
+
workspace_rank: item.workspace_rank || 0,
|
|
1044
|
+
idle_time: item.idle_time || 0
|
|
1037
1045
|
}));
|
|
1038
1046
|
return transformedData;
|
|
1039
1047
|
} catch (err) {
|
|
@@ -3392,6 +3400,9 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3392
3400
|
const databaseConfig = useDatabaseConfig();
|
|
3393
3401
|
const dateTimeConfig = useDateTimeConfig();
|
|
3394
3402
|
const shiftConfig = useShiftConfig();
|
|
3403
|
+
const defaultTimezone = dateTimeConfig?.defaultTimezone || "UTC";
|
|
3404
|
+
const configuredLineMetricsTable = databaseConfig?.tables?.lineMetrics ?? "line_metrics";
|
|
3405
|
+
const schema = databaseConfig?.schema ?? "public";
|
|
3395
3406
|
const supabase = useSupabase();
|
|
3396
3407
|
const [metrics2, setMetrics] = React14.useState(() => getCache(lineId) || { workspaceMetrics: [], lineMetrics: [] });
|
|
3397
3408
|
const [isLoading, setIsLoading] = React14.useState(() => !getCache(lineId));
|
|
@@ -3404,9 +3415,6 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3404
3415
|
() => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
|
|
3405
3416
|
[entityConfig.companyId]
|
|
3406
3417
|
);
|
|
3407
|
-
const configuredLineMetricsTable = databaseConfig.tables?.lineMetrics ?? "line_metrics";
|
|
3408
|
-
const schema = databaseConfig.schema ?? "public";
|
|
3409
|
-
const defaultTimezone = dateTimeConfig.defaultTimezone || "UTC";
|
|
3410
3418
|
React14.useEffect(() => {
|
|
3411
3419
|
lineIdRef.current = lineId;
|
|
3412
3420
|
const cachedData = getCache(lineId);
|
|
@@ -3416,7 +3424,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3416
3424
|
const fetchAllMetrics = React14.useCallback(async () => {
|
|
3417
3425
|
const currentLineIdToUse = lineIdRef.current;
|
|
3418
3426
|
if (!currentLineIdToUse || !supabase || isFetchingRef.current || companySpecificMetricsTable.includes("unknown_company")) {
|
|
3419
|
-
if (!metrics2
|
|
3427
|
+
if (!metrics2?.workspaceMetrics?.length && !metrics2?.lineMetrics?.length) setIsLoading(false);
|
|
3420
3428
|
if (companySpecificMetricsTable.includes("unknown_company") && !error) {
|
|
3421
3429
|
setError({ message: "Company ID not configured for metrics table.", code: "CONFIG_ERROR" });
|
|
3422
3430
|
}
|
|
@@ -3437,7 +3445,12 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3437
3445
|
if (targetLineIds.length === 0) {
|
|
3438
3446
|
throw new Error("No target line IDs available for fetching metrics.");
|
|
3439
3447
|
}
|
|
3440
|
-
const
|
|
3448
|
+
const isFactoryView = currentLineIdToUse === (entityConfig.factoryViewId || "factory");
|
|
3449
|
+
let workspaceQuery = supabase.from(companySpecificMetricsTable).select("company_id,line_id,shift_id,date,workspace_id,workspace_name,total_output,avg_pph,performance_score,avg_cycle_time,trend_score,ideal_output,efficiency,total_day_output").eq("date", operationalDate).eq("shift_id", currentShiftDetails.shiftId);
|
|
3450
|
+
if (!isFactoryView) {
|
|
3451
|
+
workspaceQuery = workspaceQuery.in("line_id", targetLineIds);
|
|
3452
|
+
}
|
|
3453
|
+
const { data: workspaceData, error: workspaceError } = await workspaceQuery;
|
|
3441
3454
|
if (workspaceError) {
|
|
3442
3455
|
throw workspaceError;
|
|
3443
3456
|
}
|
|
@@ -3468,7 +3481,11 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3468
3481
|
const wsNumB = parseInt(b.workspace_name?.replace(/[^0-9]/g, "") || "0");
|
|
3469
3482
|
return wsNumA - wsNumB;
|
|
3470
3483
|
});
|
|
3471
|
-
|
|
3484
|
+
let lineMetricsQuery = supabase.from(configuredLineMetricsTable).select("*").eq("date", operationalDate).eq("shift_id", currentShiftDetails.shiftId);
|
|
3485
|
+
if (!isFactoryView) {
|
|
3486
|
+
lineMetricsQuery = lineMetricsQuery.in("line_id", targetLineIds);
|
|
3487
|
+
}
|
|
3488
|
+
const { data: lineData, error: lineError } = await lineMetricsQuery;
|
|
3472
3489
|
if (lineError) {
|
|
3473
3490
|
throw lineError;
|
|
3474
3491
|
}
|
|
@@ -3488,9 +3505,9 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3488
3505
|
}
|
|
3489
3506
|
}, [
|
|
3490
3507
|
supabase,
|
|
3491
|
-
metrics2
|
|
3508
|
+
metrics2?.workspaceMetrics?.length || 0,
|
|
3492
3509
|
// To re-evaluate setIsLoading in fetchAllMetrics if called directly
|
|
3493
|
-
metrics2
|
|
3510
|
+
metrics2?.lineMetrics?.length || 0,
|
|
3494
3511
|
// To re-evaluate setIsLoading in fetchAllMetrics if called directly
|
|
3495
3512
|
companySpecificMetricsTable,
|
|
3496
3513
|
configuredLineMetricsTable,
|
|
@@ -3578,8 +3595,8 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId }) => {
|
|
|
3578
3595
|
// Add lineId from props to re-run effect if it changes, managed by lineIdRef inside effect
|
|
3579
3596
|
]);
|
|
3580
3597
|
return {
|
|
3581
|
-
workspaceMetrics: metrics2
|
|
3582
|
-
lineMetrics: metrics2
|
|
3598
|
+
workspaceMetrics: metrics2?.workspaceMetrics || [],
|
|
3599
|
+
lineMetrics: metrics2?.lineMetrics || [],
|
|
3583
3600
|
isLoading,
|
|
3584
3601
|
error,
|
|
3585
3602
|
refetch: fetchAllMetrics
|
|
@@ -3612,6 +3629,7 @@ var setCache2 = (lineId, data) => {
|
|
|
3612
3629
|
var useLineKPIs = ({ lineId }) => {
|
|
3613
3630
|
useDashboardConfig();
|
|
3614
3631
|
const entityConfig = useEntityConfig();
|
|
3632
|
+
const isFactoryView = lineId === (entityConfig.factoryViewId || "factory");
|
|
3615
3633
|
const databaseConfig = useDatabaseConfig();
|
|
3616
3634
|
const dateTimeConfig = useDateTimeConfig();
|
|
3617
3635
|
const shiftConfig = useShiftConfig();
|
|
@@ -3669,7 +3687,7 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
3669
3687
|
isFetchingRef.current = false;
|
|
3670
3688
|
updateQueueRef.current = false;
|
|
3671
3689
|
}
|
|
3672
|
-
}, [dashboardServiceInstance, kpis, defaultTimezone, shiftConfig, entityConfig.companyId]);
|
|
3690
|
+
}, [dashboardServiceInstance, kpis, defaultTimezone, shiftConfig, entityConfig.companyId, isFactoryView]);
|
|
3673
3691
|
const queueUpdate = React14.useCallback(() => {
|
|
3674
3692
|
if (updateQueueRef.current) return;
|
|
3675
3693
|
updateQueueRef.current = true;
|
|
@@ -3744,7 +3762,7 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
3744
3762
|
}
|
|
3745
3763
|
activeChannels.forEach((ch) => supabase.removeChannel(ch).catch((err) => console.error("[useLineKPIs] Error removing KPI channel:", err)));
|
|
3746
3764
|
};
|
|
3747
|
-
}, [supabase, lineId, fetchKPIs, queueUpdate, dashboardServiceInstance, entityConfig, schema, lineMetricsTable, companySpecificMetricsTable, defaultTimezone, shiftConfig, kpis]);
|
|
3765
|
+
}, [supabase, lineId, fetchKPIs, queueUpdate, dashboardServiceInstance, entityConfig, schema, lineMetricsTable, companySpecificMetricsTable, defaultTimezone, shiftConfig, kpis, isFactoryView]);
|
|
3748
3766
|
return {
|
|
3749
3767
|
kpis,
|
|
3750
3768
|
isLoading,
|
|
@@ -5180,6 +5198,120 @@ var useActiveBreaks = (lineIds) => {
|
|
|
5180
5198
|
error
|
|
5181
5199
|
};
|
|
5182
5200
|
};
|
|
5201
|
+
var useAllWorkspaceMetrics = (options) => {
|
|
5202
|
+
const entityConfig = useEntityConfig();
|
|
5203
|
+
const databaseConfig = useDatabaseConfig();
|
|
5204
|
+
const dateTimeConfig = useDateTimeConfig();
|
|
5205
|
+
const shiftConfig = useShiftConfig();
|
|
5206
|
+
const supabase = useSupabase();
|
|
5207
|
+
const [workspaces, setWorkspaces] = React14.useState([]);
|
|
5208
|
+
const [loading, setLoading] = React14.useState(true);
|
|
5209
|
+
const [error, setError] = React14.useState(null);
|
|
5210
|
+
const [initialized, setInitialized] = React14.useState(false);
|
|
5211
|
+
const queryShiftId = React14.useMemo(() => {
|
|
5212
|
+
const currentShift = getCurrentShift(
|
|
5213
|
+
dateTimeConfig.defaultTimezone || "Asia/Kolkata",
|
|
5214
|
+
shiftConfig
|
|
5215
|
+
);
|
|
5216
|
+
return options?.initialShiftId !== void 0 ? options.initialShiftId : currentShift.shiftId;
|
|
5217
|
+
}, [options?.initialShiftId, dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
5218
|
+
const queryDate = React14.useMemo(() => {
|
|
5219
|
+
return options?.initialDate || getOperationalDate(dateTimeConfig.defaultTimezone);
|
|
5220
|
+
}, [options?.initialDate, dateTimeConfig.defaultTimezone]);
|
|
5221
|
+
const metricsTable = React14.useMemo(() => {
|
|
5222
|
+
const companyId = entityConfig.companyId;
|
|
5223
|
+
if (!companyId) return "";
|
|
5224
|
+
const metricsTablePrefix = getMetricsTablePrefix();
|
|
5225
|
+
return `${metricsTablePrefix}_${companyId.replace(/-/g, "_")}`;
|
|
5226
|
+
}, [entityConfig.companyId]);
|
|
5227
|
+
const schema = databaseConfig.schema ?? "public";
|
|
5228
|
+
const fetchWorkspaceMetrics = React14.useCallback(async () => {
|
|
5229
|
+
if (!initialized) {
|
|
5230
|
+
setLoading(true);
|
|
5231
|
+
}
|
|
5232
|
+
setError(null);
|
|
5233
|
+
try {
|
|
5234
|
+
console.log("Fetching all workspace metrics with params:", {
|
|
5235
|
+
queryDate,
|
|
5236
|
+
queryShiftId,
|
|
5237
|
+
metricsTable
|
|
5238
|
+
});
|
|
5239
|
+
const { data, error: fetchError } = await supabase.from(metricsTable).select(`
|
|
5240
|
+
workspace_name,
|
|
5241
|
+
total_output,
|
|
5242
|
+
avg_pph,
|
|
5243
|
+
efficiency,
|
|
5244
|
+
workspace_id,
|
|
5245
|
+
avg_cycle_time,
|
|
5246
|
+
performance_score,
|
|
5247
|
+
trend_score,
|
|
5248
|
+
line_id,
|
|
5249
|
+
total_day_output
|
|
5250
|
+
`).eq("date", queryDate).eq("shift_id", queryShiftId).order("efficiency", { ascending: false });
|
|
5251
|
+
if (fetchError) throw fetchError;
|
|
5252
|
+
const transformedData = (data || []).map((item) => ({
|
|
5253
|
+
company_id: entityConfig.companyId || "unknown",
|
|
5254
|
+
line_id: item.line_id,
|
|
5255
|
+
shift_id: queryShiftId,
|
|
5256
|
+
date: queryDate,
|
|
5257
|
+
workspace_uuid: item.workspace_id,
|
|
5258
|
+
workspace_name: item.workspace_name,
|
|
5259
|
+
action_count: item.total_output || 0,
|
|
5260
|
+
pph: item.avg_pph || 0,
|
|
5261
|
+
performance_score: item.performance_score || 0,
|
|
5262
|
+
avg_cycle_time: item.avg_cycle_time || 0,
|
|
5263
|
+
trend: item.trend_score === 1 ? 2 : 0,
|
|
5264
|
+
predicted_output: 0,
|
|
5265
|
+
efficiency: item.efficiency || 0,
|
|
5266
|
+
action_threshold: item.total_day_output || 0
|
|
5267
|
+
}));
|
|
5268
|
+
setWorkspaces(transformedData);
|
|
5269
|
+
setInitialized(true);
|
|
5270
|
+
} catch (err) {
|
|
5271
|
+
console.error("Error fetching all workspace metrics:", err);
|
|
5272
|
+
setError({ message: err.message, code: err.code || "FETCH_ERROR" });
|
|
5273
|
+
} finally {
|
|
5274
|
+
setLoading(false);
|
|
5275
|
+
}
|
|
5276
|
+
}, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId]);
|
|
5277
|
+
React14.useEffect(() => {
|
|
5278
|
+
if (!initialized) {
|
|
5279
|
+
fetchWorkspaceMetrics();
|
|
5280
|
+
}
|
|
5281
|
+
const setupSubscription = () => {
|
|
5282
|
+
const filter2 = `date=eq.${queryDate} AND shift_id=eq.${queryShiftId}`;
|
|
5283
|
+
console.log("Setting up subscription for all workspaces with filter:", filter2);
|
|
5284
|
+
const channel2 = supabase.channel(`all-workspace-metrics-${Date.now()}`).on(
|
|
5285
|
+
"postgres_changes",
|
|
5286
|
+
{
|
|
5287
|
+
event: "*",
|
|
5288
|
+
schema,
|
|
5289
|
+
table: metricsTable,
|
|
5290
|
+
filter: filter2
|
|
5291
|
+
},
|
|
5292
|
+
async (payload) => {
|
|
5293
|
+
console.log("All workspace metrics update received:", payload);
|
|
5294
|
+
await fetchWorkspaceMetrics();
|
|
5295
|
+
}
|
|
5296
|
+
).subscribe();
|
|
5297
|
+
return channel2;
|
|
5298
|
+
};
|
|
5299
|
+
const channel = setupSubscription();
|
|
5300
|
+
return () => {
|
|
5301
|
+
if (channel) {
|
|
5302
|
+
supabase.removeChannel(channel);
|
|
5303
|
+
}
|
|
5304
|
+
};
|
|
5305
|
+
}, [queryDate, queryShiftId, metricsTable, fetchWorkspaceMetrics, initialized, supabase, schema]);
|
|
5306
|
+
React14.useEffect(() => {
|
|
5307
|
+
setInitialized(false);
|
|
5308
|
+
}, [queryDate, queryShiftId]);
|
|
5309
|
+
const refreshWorkspaces = fetchWorkspaceMetrics;
|
|
5310
|
+
return React14.useMemo(
|
|
5311
|
+
() => ({ workspaces, loading, error, refreshWorkspaces }),
|
|
5312
|
+
[workspaces, loading, error, refreshWorkspaces]
|
|
5313
|
+
);
|
|
5314
|
+
};
|
|
5183
5315
|
var MAX_RETRIES = 10;
|
|
5184
5316
|
var RETRY_DELAY = 500;
|
|
5185
5317
|
function useNavigation(customNavigate) {
|
|
@@ -5226,8 +5358,8 @@ function useNavigation(customNavigate) {
|
|
|
5226
5358
|
router$1.push("/shifts");
|
|
5227
5359
|
}, [router$1]);
|
|
5228
5360
|
const goToLeaderboard = React14.useCallback(() => {
|
|
5229
|
-
|
|
5230
|
-
router$1.push(`/leaderboard
|
|
5361
|
+
entityConfig?.defaultLineId || "line-1";
|
|
5362
|
+
router$1.push(`/leaderboard`);
|
|
5231
5363
|
}, [router$1, entityConfig?.defaultLineId]);
|
|
5232
5364
|
const goToFactoryView = React14.useCallback(() => {
|
|
5233
5365
|
router$1.push("/factory-view");
|
|
@@ -17367,7 +17499,8 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17367
17499
|
cropping,
|
|
17368
17500
|
canvasFps = 30,
|
|
17369
17501
|
useRAF = true,
|
|
17370
|
-
className = ""
|
|
17502
|
+
className = "",
|
|
17503
|
+
compact = false
|
|
17371
17504
|
}) => {
|
|
17372
17505
|
const videoRef = React14.useRef(null);
|
|
17373
17506
|
const canvasRef = React14.useRef(null);
|
|
@@ -17388,7 +17521,6 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17388
17521
|
});
|
|
17389
17522
|
}
|
|
17390
17523
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
17391
|
-
workspace.workspace_uuid || workspace.workspace_name;
|
|
17392
17524
|
const getEfficiencyOverlayColor = (efficiency) => {
|
|
17393
17525
|
if (efficiency >= 80) {
|
|
17394
17526
|
return "bg-[#00D654]/25";
|
|
@@ -17431,15 +17563,15 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17431
17563
|
}
|
|
17432
17564
|
},
|
|
17433
17565
|
children: [
|
|
17434
|
-
isVeryLowEfficiency && /* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
17566
|
+
isVeryLowEfficiency && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute ${compact ? "top-0.5 left-1" : "top-1 left-2"} z-30`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
17435
17567
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -inset-1 bg-red-400/50 rounded-full blur-sm animate-pulse" }),
|
|
17436
17568
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -inset-0.5 bg-red-500/30 rounded-full blur-md animate-ping [animation-duration:1.5s]" }),
|
|
17437
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
17569
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `bg-[#E34329] ${compact ? "w-4 h-4" : "w-5 h-5"} rounded-full flex items-center justify-center text-white font-bold ${compact ? "text-[10px]" : "text-xs"} shadow-lg ring-2 ring-red-400/40 border border-red-400/80 animate-pulse`, children: "!" })
|
|
17438
17570
|
] }) }),
|
|
17439
17571
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full overflow-hidden bg-black", children: [
|
|
17440
17572
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black z-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse flex flex-col items-center", children: [
|
|
17441
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { className: "w-6 h-6 text-gray-500
|
|
17442
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500 mt-1
|
|
17573
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { className: `${compact ? "w-4 h-4" : "w-6 h-6"} text-gray-500` }),
|
|
17574
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${compact ? "text-[10px]" : "text-xs"} text-gray-500 mt-1`, children: "Loading..." })
|
|
17443
17575
|
] }) }),
|
|
17444
17576
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 z-10", children: [
|
|
17445
17577
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -17462,11 +17594,11 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17462
17594
|
)
|
|
17463
17595
|
] }),
|
|
17464
17596
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute inset-0 z-20 pointer-events-none ${efficiencyOverlayClass}` }),
|
|
17465
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
17597
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute ${compact ? "top-1 right-1" : "top-2 right-2"} z-30 bg-black/70 backdrop-blur-sm rounded ${compact ? "px-1.5 py-0.5" : "px-2 py-0.5"} text-white ${compact ? "text-[10px]" : "text-xs"} font-semibold border border-white/10`, children: [
|
|
17466
17598
|
Math.round(workspace.efficiency),
|
|
17467
17599
|
"%"
|
|
17468
17600
|
] }),
|
|
17469
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
17601
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute bottom-0 left-0 right-0 ${compact ? "h-0.5" : "h-1"} bg-black/50 z-30`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
17470
17602
|
"div",
|
|
17471
17603
|
{
|
|
17472
17604
|
className: `h-full ${efficiencyBarClass} transition-all duration-500`,
|
|
@@ -17474,22 +17606,22 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17474
17606
|
}
|
|
17475
17607
|
) })
|
|
17476
17608
|
] }),
|
|
17477
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
17609
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `absolute bottom-0 left-0 right-0 bg-black bg-opacity-60 ${compact ? "p-1" : "p-1.5"} flex justify-between items-center z-10`, children: [
|
|
17478
17610
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
17479
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { size: 12, className: "text-white" }),
|
|
17480
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className:
|
|
17611
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { size: compact ? 10 : 12, className: "text-white" }),
|
|
17612
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-white ${compact ? "text-[10px]" : "text-xs"} font-medium tracking-wide`, children: displayName })
|
|
17481
17613
|
] }),
|
|
17482
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className:
|
|
17614
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center ${compact ? "gap-1" : "gap-1.5"}`, children: [
|
|
17483
17615
|
trendInfo && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17484
17616
|
"div",
|
|
17485
17617
|
{
|
|
17486
|
-
className:
|
|
17618
|
+
className: `${compact ? "text-sm" : "text-lg"} ${trendInfo.color}`,
|
|
17487
17619
|
style: { lineHeight: 1, display: "flex", alignItems: "center" },
|
|
17488
17620
|
children: trendInfo.arrow
|
|
17489
17621
|
}
|
|
17490
17622
|
),
|
|
17491
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-1.5 h-1.5 rounded-full bg-green-500
|
|
17492
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className:
|
|
17623
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `${compact ? "w-1 h-1" : "w-1.5 h-1.5"} rounded-full bg-green-500` }),
|
|
17624
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-white ${compact ? "text-[10px]" : "text-xs"}`, children: "Live" })
|
|
17493
17625
|
] })
|
|
17494
17626
|
] })
|
|
17495
17627
|
]
|
|
@@ -17516,7 +17648,6 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17516
17648
|
workspaces,
|
|
17517
17649
|
selectedLine,
|
|
17518
17650
|
className = "",
|
|
17519
|
-
lineIdMapping = {},
|
|
17520
17651
|
videoSources = {}
|
|
17521
17652
|
}) => {
|
|
17522
17653
|
const router$1 = router.useRouter();
|
|
@@ -17581,15 +17712,15 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17581
17712
|
let bestScore = 0;
|
|
17582
17713
|
const targetAspectRatio = 16 / 9;
|
|
17583
17714
|
const gap = 8;
|
|
17584
|
-
const maxCols = Math.min(count, 6);
|
|
17715
|
+
const maxCols = Math.min(count, selectedLine ? 6 : 12);
|
|
17585
17716
|
for (let cols = 1; cols <= maxCols; cols++) {
|
|
17586
17717
|
const rows = Math.ceil(count / cols);
|
|
17587
17718
|
const availableWidth = containerWidth - gap * (cols - 1);
|
|
17588
17719
|
const availableHeight = containerHeight - gap * (rows - 1);
|
|
17589
17720
|
const cellWidth = availableWidth / cols;
|
|
17590
17721
|
const cellHeight = availableHeight / rows;
|
|
17591
|
-
const minCellWidth = containerWidth < 800 ? 120 : 150;
|
|
17592
|
-
const minCellHeight = containerHeight < 600 ? 80 : 100;
|
|
17722
|
+
const minCellWidth = selectedLine ? containerWidth < 800 ? 120 : 150 : containerWidth < 800 ? 80 : 100;
|
|
17723
|
+
const minCellHeight = selectedLine ? containerHeight < 600 ? 80 : 100 : containerHeight < 600 ? 60 : 80;
|
|
17593
17724
|
if (cellWidth < minCellWidth || cellHeight < minCellHeight) continue;
|
|
17594
17725
|
const totalUsedArea = cellWidth * cellHeight * count;
|
|
17595
17726
|
const totalAvailableArea = containerWidth * containerHeight;
|
|
@@ -17606,7 +17737,7 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17606
17737
|
bestCols = Math.ceil(Math.sqrt(count));
|
|
17607
17738
|
}
|
|
17608
17739
|
setGridCols(bestCols);
|
|
17609
|
-
}, [filteredWorkspaces.length]);
|
|
17740
|
+
}, [filteredWorkspaces.length, selectedLine]);
|
|
17610
17741
|
React14.useEffect(() => {
|
|
17611
17742
|
calculateOptimalGrid();
|
|
17612
17743
|
const handleResize = () => calculateOptimalGrid();
|
|
@@ -17665,16 +17796,17 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17665
17796
|
minHeight: "100%"
|
|
17666
17797
|
},
|
|
17667
17798
|
children: filteredWorkspaces.sort((a, b) => {
|
|
17668
|
-
|
|
17669
|
-
|
|
17670
|
-
|
|
17671
|
-
|
|
17672
|
-
|
|
17673
|
-
|
|
17674
|
-
|
|
17675
|
-
|
|
17799
|
+
if (a.line_id !== b.line_id) {
|
|
17800
|
+
return (a.line_id || "").localeCompare(b.line_id || "");
|
|
17801
|
+
}
|
|
17802
|
+
const aMatch = a.workspace_name.match(/WS(\d+)/);
|
|
17803
|
+
const bMatch = b.workspace_name.match(/WS(\d+)/);
|
|
17804
|
+
if (aMatch && bMatch) {
|
|
17805
|
+
const aNum = parseInt(aMatch[1]);
|
|
17806
|
+
const bNum = parseInt(bMatch[1]);
|
|
17807
|
+
return aNum - bNum;
|
|
17676
17808
|
}
|
|
17677
|
-
return
|
|
17809
|
+
return a.workspace_name.localeCompare(b.workspace_name);
|
|
17678
17810
|
}).map((workspace) => {
|
|
17679
17811
|
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
17680
17812
|
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
@@ -17697,7 +17829,8 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17697
17829
|
isVeryLowEfficiency,
|
|
17698
17830
|
cropping: workspaceCropping,
|
|
17699
17831
|
canvasFps: canvasConfig?.fps,
|
|
17700
|
-
useRAF: canvasConfig?.useRAF
|
|
17832
|
+
useRAF: canvasConfig?.useRAF,
|
|
17833
|
+
compact: !selectedLine
|
|
17701
17834
|
}
|
|
17702
17835
|
)
|
|
17703
17836
|
},
|
|
@@ -21261,7 +21394,7 @@ function isValidShiftId(shiftId) {
|
|
|
21261
21394
|
}
|
|
21262
21395
|
|
|
21263
21396
|
// src/lib/api/s3-clips-parser.ts
|
|
21264
|
-
function parseS3Uri(s3Uri) {
|
|
21397
|
+
function parseS3Uri(s3Uri, sopCategories) {
|
|
21265
21398
|
const path = new URL(s3Uri).pathname;
|
|
21266
21399
|
const parts = path.split("/").filter((p) => p);
|
|
21267
21400
|
console.log("S3 URI:", s3Uri);
|
|
@@ -21301,6 +21434,27 @@ function parseS3Uri(s3Uri) {
|
|
|
21301
21434
|
let description = "Analysis Clip";
|
|
21302
21435
|
const normalizedViolationType = violationType.toLowerCase().trim();
|
|
21303
21436
|
console.log(`Parsing violation type: "${violationType}" (normalized: "${normalizedViolationType}") from path: ${s3Uri}`);
|
|
21437
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
21438
|
+
const matchedCategory = sopCategories.find((category) => {
|
|
21439
|
+
const categoryId = category.id.toLowerCase();
|
|
21440
|
+
const s3FolderName = (category.s3FolderName || category.id).toLowerCase();
|
|
21441
|
+
return categoryId === normalizedViolationType || s3FolderName === normalizedViolationType || // Also check for partial matches for flexibility
|
|
21442
|
+
normalizedViolationType.includes(categoryId) || normalizedViolationType.includes(s3FolderName);
|
|
21443
|
+
});
|
|
21444
|
+
if (matchedCategory) {
|
|
21445
|
+
type = matchedCategory.id;
|
|
21446
|
+
description = matchedCategory.description || matchedCategory.label;
|
|
21447
|
+
if (matchedCategory.color.includes("red")) {
|
|
21448
|
+
severity = "high";
|
|
21449
|
+
} else if (matchedCategory.color.includes("yellow") || matchedCategory.color.includes("orange")) {
|
|
21450
|
+
severity = "medium";
|
|
21451
|
+
} else {
|
|
21452
|
+
severity = "low";
|
|
21453
|
+
}
|
|
21454
|
+
console.log(`Matched SOP category: ${matchedCategory.id} for violation type: ${violationType}`);
|
|
21455
|
+
return { timestamp, severity, description, type, originalUri: s3Uri };
|
|
21456
|
+
}
|
|
21457
|
+
}
|
|
21304
21458
|
switch (normalizedViolationType) {
|
|
21305
21459
|
case "idle_time":
|
|
21306
21460
|
case "idle":
|
|
@@ -21540,11 +21694,23 @@ var S3ClipsService = class {
|
|
|
21540
21694
|
const key = url.pathname.startsWith("/") ? url.pathname.substring(1) : url.pathname;
|
|
21541
21695
|
return `${this.config.s3Config.cloudFrontDomain}/${key}`;
|
|
21542
21696
|
}
|
|
21697
|
+
/**
|
|
21698
|
+
* Gets SOP categories for a specific workspace
|
|
21699
|
+
*/
|
|
21700
|
+
getSOPCategories(workspaceId) {
|
|
21701
|
+
const sopConfig = this.config.s3Config?.sopCategories;
|
|
21702
|
+
if (!sopConfig) return void 0;
|
|
21703
|
+
if (sopConfig.workspaceOverrides && sopConfig.workspaceOverrides[workspaceId]) {
|
|
21704
|
+
return sopConfig.workspaceOverrides[workspaceId];
|
|
21705
|
+
}
|
|
21706
|
+
return sopConfig.default;
|
|
21707
|
+
}
|
|
21543
21708
|
/**
|
|
21544
21709
|
* Processes a single video completely
|
|
21545
21710
|
*/
|
|
21546
21711
|
async processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime, includeMetadata = false) {
|
|
21547
|
-
const
|
|
21712
|
+
const sopCategories = this.getSOPCategories(workspaceId);
|
|
21713
|
+
const parsedInfo = parseS3Uri(uri, sopCategories);
|
|
21548
21714
|
if (!parsedInfo) {
|
|
21549
21715
|
console.warn(`Skipping URI due to parsing failure: ${uri}`);
|
|
21550
21716
|
return null;
|
|
@@ -21577,27 +21743,32 @@ var S3ClipsService = class {
|
|
|
21577
21743
|
async getVideoSummary(workspaceId, date, shiftId) {
|
|
21578
21744
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId });
|
|
21579
21745
|
console.log(`S3ClipsService getVideoSummary: Processing ${s3Uris.length} total URIs for accurate category counts`);
|
|
21580
|
-
const
|
|
21581
|
-
|
|
21582
|
-
|
|
21583
|
-
|
|
21584
|
-
|
|
21585
|
-
|
|
21586
|
-
|
|
21587
|
-
|
|
21588
|
-
|
|
21589
|
-
|
|
21590
|
-
|
|
21591
|
-
|
|
21592
|
-
|
|
21593
|
-
|
|
21594
|
-
|
|
21595
|
-
|
|
21596
|
-
|
|
21597
|
-
|
|
21598
|
-
|
|
21746
|
+
const sopCategories = this.getSOPCategories(workspaceId);
|
|
21747
|
+
const counts = { total: 0 };
|
|
21748
|
+
const samples = {};
|
|
21749
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
21750
|
+
sopCategories.forEach((category) => {
|
|
21751
|
+
counts[category.id] = 0;
|
|
21752
|
+
samples[category.id] = null;
|
|
21753
|
+
});
|
|
21754
|
+
} else {
|
|
21755
|
+
counts.best_cycle_time = 0;
|
|
21756
|
+
counts.worst_cycle_time = 0;
|
|
21757
|
+
counts.bottleneck = 0;
|
|
21758
|
+
counts.low_value = 0;
|
|
21759
|
+
counts.long_cycle_time = 0;
|
|
21760
|
+
counts.missing_quality_check = 0;
|
|
21761
|
+
counts.cycle_completions = 0;
|
|
21762
|
+
samples.best_cycle_time = null;
|
|
21763
|
+
samples.worst_cycle_time = null;
|
|
21764
|
+
samples.bottleneck = null;
|
|
21765
|
+
samples.low_value = null;
|
|
21766
|
+
samples.long_cycle_time = null;
|
|
21767
|
+
samples.missing_quality_check = null;
|
|
21768
|
+
samples.cycle_completions = null;
|
|
21769
|
+
}
|
|
21599
21770
|
for (const uri of s3Uris) {
|
|
21600
|
-
const parsedInfo = parseS3Uri(uri);
|
|
21771
|
+
const parsedInfo = parseS3Uri(uri, sopCategories);
|
|
21601
21772
|
if (parsedInfo) {
|
|
21602
21773
|
const { type } = parsedInfo;
|
|
21603
21774
|
counts[type] = (counts[type] || 0) + 1;
|
|
@@ -21659,7 +21830,7 @@ var S3ClipsService = class {
|
|
|
21659
21830
|
}
|
|
21660
21831
|
return summary;
|
|
21661
21832
|
}
|
|
21662
|
-
const limitPerCategory = limit ? Math.min(Math.max(limit, 1),
|
|
21833
|
+
const limitPerCategory = limit ? Math.min(Math.max(limit, 1), 1e3) : 30;
|
|
21663
21834
|
const shouldFetchAll = category === "missing_quality_check" || category === "low_value";
|
|
21664
21835
|
const initialFetchLimit = shouldFetchAll ? void 0 : category ? limitPerCategory * 3 : void 0;
|
|
21665
21836
|
const s3Uris = await this.listS3Clips({ workspaceId, date, shiftId, maxKeys: initialFetchLimit });
|
|
@@ -21810,6 +21981,14 @@ var BottlenecksContent = ({
|
|
|
21810
21981
|
className
|
|
21811
21982
|
}) => {
|
|
21812
21983
|
const dashboardConfig = useDashboardConfig();
|
|
21984
|
+
const sopCategories = React14__namespace.default.useMemo(() => {
|
|
21985
|
+
const sopConfig = dashboardConfig?.s3Config?.sopCategories;
|
|
21986
|
+
if (!sopConfig) return null;
|
|
21987
|
+
if (sopConfig.workspaceOverrides && sopConfig.workspaceOverrides[workspaceId]) {
|
|
21988
|
+
return sopConfig.workspaceOverrides[workspaceId];
|
|
21989
|
+
}
|
|
21990
|
+
return sopConfig.default;
|
|
21991
|
+
}, [dashboardConfig, workspaceId]);
|
|
21813
21992
|
const videoRef = React14.useRef(null);
|
|
21814
21993
|
const fullscreenContainerRef = React14.useRef(null);
|
|
21815
21994
|
const timestampFilterRef = React14.useRef(null);
|
|
@@ -21818,7 +21997,9 @@ var BottlenecksContent = ({
|
|
|
21818
21997
|
const [duration, setDuration] = React14.useState(0);
|
|
21819
21998
|
const [isFullscreen, setIsFullscreen] = React14.useState(false);
|
|
21820
21999
|
const [currentIndex, setCurrentIndex] = React14.useState(0);
|
|
21821
|
-
const [activeFilter, setActiveFilter] = React14.useState(
|
|
22000
|
+
const [activeFilter, setActiveFilter] = React14.useState(
|
|
22001
|
+
sopCategories && sopCategories.length > 0 ? sopCategories[0].id : "low_value"
|
|
22002
|
+
);
|
|
21822
22003
|
const [allVideos, setAllVideos] = React14.useState([]);
|
|
21823
22004
|
const [isLoading, setIsLoading] = React14.useState(true);
|
|
21824
22005
|
const [error, setError] = React14.useState(null);
|
|
@@ -21930,27 +22111,41 @@ var BottlenecksContent = ({
|
|
|
21930
22111
|
let filtered = [];
|
|
21931
22112
|
if (activeFilter === "all") {
|
|
21932
22113
|
filtered = [...allVideos];
|
|
21933
|
-
} else if (activeFilter === "low_value") {
|
|
21934
|
-
filtered = allVideos.filter((video) => video.type === "low_value");
|
|
21935
|
-
} else if (activeFilter === "sop_deviations") {
|
|
21936
|
-
filtered = allVideos.filter((video) => video.type === "missing_quality_check");
|
|
21937
|
-
} else if (activeFilter === "best_cycle_time") {
|
|
21938
|
-
filtered = allVideos.filter((video) => video.type === "best_cycle_time");
|
|
21939
|
-
} else if (activeFilter === "worst_cycle_time") {
|
|
21940
|
-
filtered = allVideos.filter((video) => video.type === "worst_cycle_time");
|
|
21941
|
-
} else if (activeFilter === "cycle_completions") {
|
|
21942
|
-
filtered = allVideos.filter((video) => video.type === "cycle_completions");
|
|
21943
|
-
} else if (activeFilter === "long_cycle_time") {
|
|
21944
|
-
filtered = allVideos.filter(
|
|
21945
|
-
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
21946
|
-
);
|
|
21947
22114
|
} else {
|
|
21948
|
-
|
|
22115
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
22116
|
+
const selectedCategory = sopCategories.find((cat) => cat.id === activeFilter);
|
|
22117
|
+
if (selectedCategory) {
|
|
22118
|
+
filtered = allVideos.filter((video) => video.type === selectedCategory.id);
|
|
22119
|
+
if (selectedCategory.id === "long_cycle_time") {
|
|
22120
|
+
filtered = allVideos.filter(
|
|
22121
|
+
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22122
|
+
);
|
|
22123
|
+
}
|
|
22124
|
+
}
|
|
22125
|
+
} else {
|
|
22126
|
+
if (activeFilter === "low_value") {
|
|
22127
|
+
filtered = allVideos.filter((video) => video.type === "low_value");
|
|
22128
|
+
} else if (activeFilter === "sop_deviations") {
|
|
22129
|
+
filtered = allVideos.filter((video) => video.type === "missing_quality_check");
|
|
22130
|
+
} else if (activeFilter === "best_cycle_time") {
|
|
22131
|
+
filtered = allVideos.filter((video) => video.type === "best_cycle_time");
|
|
22132
|
+
} else if (activeFilter === "worst_cycle_time") {
|
|
22133
|
+
filtered = allVideos.filter((video) => video.type === "worst_cycle_time");
|
|
22134
|
+
} else if (activeFilter === "cycle_completions") {
|
|
22135
|
+
filtered = allVideos.filter((video) => video.type === "cycle_completions");
|
|
22136
|
+
} else if (activeFilter === "long_cycle_time") {
|
|
22137
|
+
filtered = allVideos.filter(
|
|
22138
|
+
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22139
|
+
);
|
|
22140
|
+
} else {
|
|
22141
|
+
filtered = allVideos.filter((video) => video.type === "bottleneck" && video.severity === activeFilter);
|
|
22142
|
+
}
|
|
22143
|
+
}
|
|
21949
22144
|
}
|
|
21950
22145
|
return filtered.sort((a, b) => {
|
|
21951
22146
|
return new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime();
|
|
21952
22147
|
});
|
|
21953
|
-
}, [activeFilter, allVideos]);
|
|
22148
|
+
}, [activeFilter, allVideos, sopCategories]);
|
|
21954
22149
|
React14.useEffect(() => {
|
|
21955
22150
|
if (filteredVideos.length === 0) return;
|
|
21956
22151
|
const upcoming = [];
|
|
@@ -22224,35 +22419,34 @@ var BottlenecksContent = ({
|
|
|
22224
22419
|
}
|
|
22225
22420
|
};
|
|
22226
22421
|
const clipCounts = React14.useMemo(() => {
|
|
22227
|
-
if (!allVideos) return {
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
22231
|
-
|
|
22232
|
-
|
|
22233
|
-
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
}
|
|
22240
|
-
|
|
22241
|
-
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
|
|
22245
|
-
|
|
22246
|
-
|
|
22247
|
-
|
|
22248
|
-
|
|
22249
|
-
longCycleTimes: allVideos.filter(
|
|
22422
|
+
if (!allVideos) return {};
|
|
22423
|
+
const counts = { total: allVideos.length };
|
|
22424
|
+
if (sopCategories && sopCategories.length > 0) {
|
|
22425
|
+
sopCategories.forEach((category) => {
|
|
22426
|
+
if (category.id === "long_cycle_time") {
|
|
22427
|
+
counts[category.id] = allVideos.filter(
|
|
22428
|
+
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22429
|
+
).length;
|
|
22430
|
+
} else {
|
|
22431
|
+
counts[category.id] = allVideos.filter((video) => video.type === category.id).length;
|
|
22432
|
+
}
|
|
22433
|
+
});
|
|
22434
|
+
} else {
|
|
22435
|
+
counts.bottlenecks = allVideos.filter((video) => video.type === "bottleneck").length;
|
|
22436
|
+
counts.lowValue = allVideos.filter((video) => video.type === "low_value").length;
|
|
22437
|
+
counts.highSeverity = allVideos.filter((video) => video.severity === "high" && video.type === "bottleneck").length;
|
|
22438
|
+
counts.mediumSeverity = allVideos.filter((video) => video.severity === "medium" && video.type === "bottleneck").length;
|
|
22439
|
+
counts.lowSeverity = allVideos.filter((video) => video.severity === "low" && video.type === "bottleneck").length;
|
|
22440
|
+
counts.sopDeviations = allVideos.filter((video) => video.type === "missing_quality_check").length;
|
|
22441
|
+
counts.bestCycleTimes = allVideos.filter((video) => video.type === "best_cycle_time").length;
|
|
22442
|
+
counts.worstCycleTimes = allVideos.filter((video) => video.type === "worst_cycle_time").length;
|
|
22443
|
+
counts.longCycleTimes = allVideos.filter(
|
|
22250
22444
|
(video) => video.type === "bottleneck" && video.description.toLowerCase().includes("cycle time")
|
|
22251
|
-
).length
|
|
22252
|
-
cycleCompletions
|
|
22253
|
-
|
|
22254
|
-
|
|
22255
|
-
}, [allVideos]);
|
|
22445
|
+
).length;
|
|
22446
|
+
counts.cycleCompletions = allVideos.filter((video) => video.type === "cycle_completions").length;
|
|
22447
|
+
}
|
|
22448
|
+
return counts;
|
|
22449
|
+
}, [allVideos, sopCategories]);
|
|
22256
22450
|
const currentVideo = React14.useMemo(() => {
|
|
22257
22451
|
if (!filteredVideos || filteredVideos.length === 0 || currentIndex >= filteredVideos.length) {
|
|
22258
22452
|
return null;
|
|
@@ -22277,6 +22471,19 @@ var BottlenecksContent = ({
|
|
|
22277
22471
|
return "Bottleneck";
|
|
22278
22472
|
}
|
|
22279
22473
|
};
|
|
22474
|
+
const getColorClasses = (color2) => {
|
|
22475
|
+
const colorMap = {
|
|
22476
|
+
purple: { text: "text-purple-500", bg: "bg-purple-500", dot: "bg-purple-500" },
|
|
22477
|
+
green: { text: "text-green-600", bg: "bg-green-600", dot: "bg-green-600" },
|
|
22478
|
+
red: { text: "text-red-700", bg: "bg-red-700", dot: "bg-red-700" },
|
|
22479
|
+
"red-dark": { text: "text-red-500", bg: "bg-red-500", dot: "bg-red-500" },
|
|
22480
|
+
blue: { text: "text-blue-600", bg: "bg-blue-600", dot: "bg-blue-600" },
|
|
22481
|
+
orange: { text: "text-orange-600", bg: "bg-orange-600", dot: "bg-orange-600" },
|
|
22482
|
+
yellow: { text: "text-yellow-600", bg: "bg-yellow-600", dot: "bg-yellow-600" },
|
|
22483
|
+
gray: { text: "text-gray-600", bg: "bg-gray-600", dot: "bg-gray-600" }
|
|
22484
|
+
};
|
|
22485
|
+
return colorMap[color2] || colorMap.gray;
|
|
22486
|
+
};
|
|
22280
22487
|
const formatTimeOnly = (time2) => {
|
|
22281
22488
|
if (!time2) return "";
|
|
22282
22489
|
try {
|
|
@@ -22306,162 +22513,62 @@ var BottlenecksContent = ({
|
|
|
22306
22513
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 max-w-md", children: error })
|
|
22307
22514
|
] });
|
|
22308
22515
|
}
|
|
22516
|
+
const categoriesToShow = sopCategories && sopCategories.length > 0 ? sopCategories : [
|
|
22517
|
+
// Default hardcoded categories if no configuration
|
|
22518
|
+
{ id: "low_value", label: "Idle Moments", color: "purple", subtitle: "Idle time detected" },
|
|
22519
|
+
{ id: "best_cycle_time", label: "Best Cycle Time", color: "green", subtitle: "Fastest cycle today" },
|
|
22520
|
+
{ id: "worst_cycle_time", label: "Worst Cycle Time", color: "red", subtitle: "Slowest cycle today" },
|
|
22521
|
+
{ id: "long_cycle_time", label: "Long Cycle Time", color: "red-dark", subtitle: "Above standard cycle times" },
|
|
22522
|
+
{ id: "cycle_completions", label: "Cycle Completions", color: "blue", subtitle: "Completed production cycles" }
|
|
22523
|
+
];
|
|
22309
22524
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-1.5 sm:p-2 lg:p-4 h-[calc(100vh-12rem)]", children: [
|
|
22310
|
-
/* @__PURE__ */ jsxRuntime.
|
|
22311
|
-
|
|
22312
|
-
|
|
22313
|
-
|
|
22314
|
-
onClick: () => {
|
|
22315
|
-
setActiveFilter("low_value");
|
|
22316
|
-
trackCoreEvent("Idle Moments Filter Clicked", {
|
|
22317
|
-
workspaceId,
|
|
22318
|
-
workspaceName,
|
|
22319
|
-
date,
|
|
22320
|
-
filterType: "low_value",
|
|
22321
|
-
clipCount: clipCounts.lowValue
|
|
22322
|
-
});
|
|
22323
|
-
},
|
|
22324
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "low_value" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22325
|
-
"aria-label": `Filter by Idle Moments (${clipCounts.lowValue} clips)`,
|
|
22326
|
-
role: "button",
|
|
22327
|
-
tabIndex: 0,
|
|
22328
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("low_value"),
|
|
22329
|
-
children: [
|
|
22330
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "low_value" ? "text-blue-600" : ""}`, children: "Idle Moments" }) }),
|
|
22331
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22332
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-purple-500", children: clipCounts.lowValue }),
|
|
22333
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22334
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-purple-500 mr-1.5" }),
|
|
22335
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Idle time detected" })
|
|
22336
|
-
] })
|
|
22337
|
-
] }) })
|
|
22338
|
-
]
|
|
22339
|
-
}
|
|
22340
|
-
),
|
|
22341
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22525
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `grid grid-cols-1 sm:grid-cols-2 ${categoriesToShow.length <= 5 ? "lg:grid-cols-5" : "lg:grid-cols-6"} gap-3 mb-4`, children: categoriesToShow.map((category) => {
|
|
22526
|
+
const colorClasses = getColorClasses(category.color);
|
|
22527
|
+
const count = clipCounts[category.id] || 0;
|
|
22528
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
22342
22529
|
Card2,
|
|
22343
22530
|
{
|
|
22344
22531
|
onClick: () => {
|
|
22345
|
-
setActiveFilter(
|
|
22346
|
-
trackCoreEvent(
|
|
22532
|
+
setActiveFilter(category.id);
|
|
22533
|
+
trackCoreEvent(`${category.label} Filter Clicked`, {
|
|
22347
22534
|
workspaceId,
|
|
22348
22535
|
workspaceName,
|
|
22349
22536
|
date,
|
|
22350
|
-
filterType:
|
|
22351
|
-
clipCount:
|
|
22537
|
+
filterType: category.id,
|
|
22538
|
+
clipCount: count
|
|
22352
22539
|
});
|
|
22353
22540
|
},
|
|
22354
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter ===
|
|
22355
|
-
"aria-label": `Filter by
|
|
22541
|
+
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === category.id ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22542
|
+
"aria-label": `Filter by ${category.label} (${count} clips)`,
|
|
22356
22543
|
role: "button",
|
|
22357
22544
|
tabIndex: 0,
|
|
22358
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter(
|
|
22545
|
+
onKeyDown: (e) => e.key === "Enter" && setActiveFilter(category.id),
|
|
22359
22546
|
children: [
|
|
22360
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter ===
|
|
22547
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === category.id ? "text-blue-600" : ""}`, children: category.label }) }),
|
|
22361
22548
|
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22362
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className:
|
|
22549
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-3xl font-bold ${colorClasses.text}`, children: count }),
|
|
22363
22550
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22364
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className:
|
|
22365
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
22551
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `h-2 w-2 rounded-full ${colorClasses.dot} mr-1.5` }),
|
|
22552
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: category.subtitle || category.description || category.label })
|
|
22366
22553
|
] })
|
|
22367
22554
|
] }) })
|
|
22368
22555
|
]
|
|
22369
|
-
}
|
|
22370
|
-
|
|
22371
|
-
|
|
22372
|
-
|
|
22373
|
-
{
|
|
22374
|
-
onClick: () => {
|
|
22375
|
-
setActiveFilter("worst_cycle_time");
|
|
22376
|
-
trackCoreEvent("Worst Cycle Time Filter Clicked", {
|
|
22377
|
-
workspaceId,
|
|
22378
|
-
workspaceName,
|
|
22379
|
-
date,
|
|
22380
|
-
filterType: "worst_cycle_time",
|
|
22381
|
-
clipCount: clipCounts.worstCycleTimes
|
|
22382
|
-
});
|
|
22383
|
-
},
|
|
22384
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "worst_cycle_time" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22385
|
-
"aria-label": `Filter by Worst Cycle Time (${clipCounts.worstCycleTimes} clips)`,
|
|
22386
|
-
role: "button",
|
|
22387
|
-
tabIndex: 0,
|
|
22388
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("worst_cycle_time"),
|
|
22389
|
-
children: [
|
|
22390
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "worst_cycle_time" ? "text-blue-600" : ""}`, children: "Worst Cycle Time" }) }),
|
|
22391
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22392
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-red-700", children: clipCounts.worstCycleTimes }),
|
|
22393
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22394
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-red-700 mr-1.5" }),
|
|
22395
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Slowest cycle today" })
|
|
22396
|
-
] })
|
|
22397
|
-
] }) })
|
|
22398
|
-
]
|
|
22399
|
-
}
|
|
22400
|
-
),
|
|
22401
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22402
|
-
Card2,
|
|
22403
|
-
{
|
|
22404
|
-
onClick: () => {
|
|
22405
|
-
setActiveFilter("long_cycle_time");
|
|
22406
|
-
trackCoreEvent("Long Cycle Time Filter Clicked", {
|
|
22407
|
-
workspaceId,
|
|
22408
|
-
workspaceName,
|
|
22409
|
-
date,
|
|
22410
|
-
filterType: "long_cycle_time",
|
|
22411
|
-
clipCount: clipCounts.longCycleTimes
|
|
22412
|
-
});
|
|
22413
|
-
},
|
|
22414
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "long_cycle_time" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22415
|
-
"aria-label": `Filter by Long Cycle Time Bottlenecks (${clipCounts.longCycleTimes} clips)`,
|
|
22416
|
-
role: "button",
|
|
22417
|
-
tabIndex: 0,
|
|
22418
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("long_cycle_time"),
|
|
22419
|
-
children: [
|
|
22420
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "long_cycle_time" ? "text-blue-600" : ""}`, children: "Long Cycle Time" }) }),
|
|
22421
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22422
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-red-500", children: clipCounts.longCycleTimes }),
|
|
22423
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22424
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-red-500 mr-1.5" }),
|
|
22425
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Above standard cycle times" })
|
|
22426
|
-
] })
|
|
22427
|
-
] }) })
|
|
22428
|
-
]
|
|
22429
|
-
}
|
|
22430
|
-
),
|
|
22431
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
22432
|
-
Card2,
|
|
22433
|
-
{
|
|
22434
|
-
onClick: () => {
|
|
22435
|
-
setActiveFilter("cycle_completions");
|
|
22436
|
-
trackCoreEvent("Cycle Completions Filter Clicked", {
|
|
22437
|
-
workspaceId,
|
|
22438
|
-
workspaceName,
|
|
22439
|
-
date,
|
|
22440
|
-
filterType: "cycle_completions",
|
|
22441
|
-
clipCount: clipCounts.cycleCompletions
|
|
22442
|
-
});
|
|
22443
|
-
},
|
|
22444
|
-
className: `bg-white shadow-sm cursor-pointer transition-all duration-200 hover:bg-gray-50 ${activeFilter === "cycle_completions" ? "bg-blue-50 shadow-md ring-1 ring-blue-200" : ""}`,
|
|
22445
|
-
"aria-label": `Filter by Cycle Completions (${clipCounts.cycleCompletions} clips)`,
|
|
22446
|
-
role: "button",
|
|
22447
|
-
tabIndex: 0,
|
|
22448
|
-
onKeyDown: (e) => e.key === "Enter" && setActiveFilter("cycle_completions"),
|
|
22449
|
-
children: [
|
|
22450
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: `text-lg ${activeFilter === "cycle_completions" ? "text-blue-600" : ""}`, children: "Cycle Completions" }) }),
|
|
22451
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col justify-center", children: [
|
|
22452
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-3xl font-bold text-blue-600", children: clipCounts.cycleCompletions }),
|
|
22453
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center text-sm text-gray-500 mt-1", children: [
|
|
22454
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2 w-2 rounded-full bg-blue-600 mr-1.5" }),
|
|
22455
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Completed production cycles" })
|
|
22456
|
-
] })
|
|
22457
|
-
] }) })
|
|
22458
|
-
]
|
|
22459
|
-
}
|
|
22460
|
-
)
|
|
22461
|
-
] }),
|
|
22556
|
+
},
|
|
22557
|
+
category.id
|
|
22558
|
+
);
|
|
22559
|
+
}) }),
|
|
22462
22560
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm overflow-hidden", style: { height: "calc(100% - 8.5rem)" }, children: [
|
|
22463
22561
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
|
|
22464
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-800", children:
|
|
22562
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-800", children: (() => {
|
|
22563
|
+
if (activeFilter === "all") {
|
|
22564
|
+
return `All Clips (${clipCounts.total || 0})`;
|
|
22565
|
+
}
|
|
22566
|
+
const activeCategory = categoriesToShow.find((cat) => cat.id === activeFilter);
|
|
22567
|
+
if (activeCategory) {
|
|
22568
|
+
return `${activeCategory.label} (${clipCounts[activeCategory.id] || 0})`;
|
|
22569
|
+
}
|
|
22570
|
+
return activeFilter === "low_value" ? `Idle Moments (${clipCounts.lowValue || 0})` : activeFilter === "best_cycle_time" ? `Best Cycle Time (${clipCounts.bestCycleTimes || 0})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Time (${clipCounts.worstCycleTimes || 0})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes || 0})` : activeFilter === "cycle_completions" ? `Cycle Completions (${clipCounts.cycleCompletions || 0})` : `All Clips (${clipCounts.total || 0})`;
|
|
22571
|
+
})() }),
|
|
22465
22572
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
22466
22573
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: timestampFilterRef, children: [
|
|
22467
22574
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -23501,7 +23608,7 @@ var KPISection = React14.memo(({
|
|
|
23501
23608
|
});
|
|
23502
23609
|
KPISection.displayName = "KPISection";
|
|
23503
23610
|
var ISTTimer2 = ISTTimer_default;
|
|
23504
|
-
var DashboardHeader = React14.memo(({ lineTitle, className = "" }) => {
|
|
23611
|
+
var DashboardHeader = React14.memo(({ lineTitle, className = "", headerControls }) => {
|
|
23505
23612
|
const getShiftName = () => {
|
|
23506
23613
|
const now2 = /* @__PURE__ */ new Date();
|
|
23507
23614
|
const currentHour = now2.getHours();
|
|
@@ -23515,30 +23622,33 @@ var DashboardHeader = React14.memo(({ lineTitle, className = "" }) => {
|
|
|
23515
23622
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" }) });
|
|
23516
23623
|
}
|
|
23517
23624
|
};
|
|
23518
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-
|
|
23519
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
23520
|
-
/* @__PURE__ */ jsxRuntime.
|
|
23521
|
-
|
|
23522
|
-
|
|
23523
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 inline-flex items-center gap-3", children: [
|
|
23524
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-medium text-gray-600", children: [
|
|
23525
|
-
/* @__PURE__ */ jsxRuntime.jsx(ISTTimer2, {}),
|
|
23526
|
-
" IST"
|
|
23625
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-row items-center justify-between w-full ${className}`, children: [
|
|
23626
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
23627
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2 md:gap-3", children: [
|
|
23628
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-base sm:text-xl md:text-2xl lg:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: lineTitle }),
|
|
23629
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 w-1 sm:h-1.5 sm:w-1.5 md:h-2 md:w-2 rounded-full bg-green-500 animate-pulse ring-1 sm:ring-2 ring-green-500/30 ring-offset-1" })
|
|
23527
23630
|
] }),
|
|
23528
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-
|
|
23529
|
-
/* @__PURE__ */ jsxRuntime.
|
|
23530
|
-
|
|
23531
|
-
|
|
23532
|
-
|
|
23631
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 inline-flex items-center gap-3", children: [
|
|
23632
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm font-medium text-gray-600", children: [
|
|
23633
|
+
/* @__PURE__ */ jsxRuntime.jsx(ISTTimer2, {}),
|
|
23634
|
+
" IST"
|
|
23635
|
+
] }),
|
|
23636
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1", children: [
|
|
23637
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-600", children: getShiftIcon() }),
|
|
23638
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-medium text-gray-600", children: [
|
|
23639
|
+
getShiftName(),
|
|
23640
|
+
" Shift"
|
|
23641
|
+
] })
|
|
23533
23642
|
] })
|
|
23534
23643
|
] })
|
|
23535
|
-
] })
|
|
23644
|
+
] }),
|
|
23645
|
+
headerControls && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4", children: headerControls })
|
|
23536
23646
|
] });
|
|
23537
23647
|
});
|
|
23538
23648
|
DashboardHeader.displayName = "DashboardHeader";
|
|
23539
|
-
var NoWorkspaceData = React14.memo(({ className = "" }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-full items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-white p-4 shadow-md", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2 text-gray-500", children: [
|
|
23649
|
+
var NoWorkspaceData = React14.memo(({ message = "No workspace data available", className = "" }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex h-full items-center justify-center ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg bg-white p-4 shadow-md", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2 text-gray-500", children: [
|
|
23540
23650
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", className: "h-5 w-5", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z", clipRule: "evenodd" }) }),
|
|
23541
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children:
|
|
23651
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: message })
|
|
23542
23652
|
] }) }) }));
|
|
23543
23653
|
NoWorkspaceData.displayName = "NoWorkspaceData";
|
|
23544
23654
|
var WorkspaceMonthlyDataFetcher = ({
|
|
@@ -23880,15 +23990,14 @@ var SideNavBar = React14.memo(({
|
|
|
23880
23990
|
}
|
|
23881
23991
|
}
|
|
23882
23992
|
}), [navigate, lineId]);
|
|
23883
|
-
const handleLeaderboardClick = React14.useCallback(() => navigate(`/leaderboard
|
|
23993
|
+
const handleLeaderboardClick = React14.useCallback(() => navigate(`/leaderboard`, {
|
|
23884
23994
|
trackingEvent: {
|
|
23885
23995
|
name: "Leaderboard Page Clicked",
|
|
23886
23996
|
properties: {
|
|
23887
|
-
source: "side_nav"
|
|
23888
|
-
line_id: lineId
|
|
23997
|
+
source: "side_nav"
|
|
23889
23998
|
}
|
|
23890
23999
|
}
|
|
23891
|
-
}), [navigate
|
|
24000
|
+
}), [navigate]);
|
|
23892
24001
|
const handleKPIsClick = React14.useCallback(() => navigate(`/kpis`, {
|
|
23893
24002
|
trackingEvent: {
|
|
23894
24003
|
name: "KPI Page Clicked",
|
|
@@ -24835,14 +24944,6 @@ var AIAgentView = () => {
|
|
|
24835
24944
|
return newMap;
|
|
24836
24945
|
});
|
|
24837
24946
|
},
|
|
24838
|
-
onReasoning: (text) => {
|
|
24839
|
-
setStreamingStates((prev) => {
|
|
24840
|
-
const newMap = new Map(prev);
|
|
24841
|
-
const current = newMap.get(currentThreadId) || { message: "", reasoning: "" };
|
|
24842
|
-
newMap.set(currentThreadId, { ...current, reasoning: current.reasoning + text });
|
|
24843
|
-
return newMap;
|
|
24844
|
-
});
|
|
24845
|
-
},
|
|
24846
24947
|
onComplete: async (messageId) => {
|
|
24847
24948
|
if (currentThreadId && !currentThreadId.startsWith("temp-")) {
|
|
24848
24949
|
const updatedMessages = await getAllThreadMessages(currentThreadId);
|
|
@@ -27220,8 +27321,8 @@ var LoadingOverlayCmp = LoadingOverlay_default;
|
|
|
27220
27321
|
function HomeView({
|
|
27221
27322
|
defaultLineId,
|
|
27222
27323
|
factoryViewId,
|
|
27223
|
-
|
|
27224
|
-
|
|
27324
|
+
lineIds: allLineIds = [],
|
|
27325
|
+
// Default to empty array
|
|
27225
27326
|
lineNames,
|
|
27226
27327
|
videoSources = {
|
|
27227
27328
|
workspaceHlsUrls: {},
|
|
@@ -27230,14 +27331,21 @@ function HomeView({
|
|
|
27230
27331
|
factoryName = "Simba Beer - Line 1"
|
|
27231
27332
|
}) {
|
|
27232
27333
|
const [isHydrated, setIsHydrated] = React14.useState(false);
|
|
27233
|
-
const
|
|
27334
|
+
const availableLineIds = React14.useMemo(() => [factoryViewId, ...allLineIds], [factoryViewId, allLineIds]);
|
|
27335
|
+
const [selectedLineId, setSelectedLineId] = React14.useState(factoryViewId);
|
|
27234
27336
|
const [isChangingFilter, setIsChangingFilter] = React14.useState(false);
|
|
27235
27337
|
const [errorMessage, setErrorMessage] = React14.useState(null);
|
|
27236
27338
|
const [displayNamesInitialized, setDisplayNamesInitialized] = React14.useState(false);
|
|
27237
27339
|
React14.useEffect(() => {
|
|
27238
27340
|
const initDisplayNames = async () => {
|
|
27239
27341
|
try {
|
|
27240
|
-
|
|
27342
|
+
if (selectedLineId === factoryViewId) {
|
|
27343
|
+
for (const lineId of allLineIds) {
|
|
27344
|
+
await preInitializeWorkspaceDisplayNames(lineId);
|
|
27345
|
+
}
|
|
27346
|
+
} else {
|
|
27347
|
+
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
27348
|
+
}
|
|
27241
27349
|
setDisplayNamesInitialized(true);
|
|
27242
27350
|
} catch (error) {
|
|
27243
27351
|
console.error("Failed to pre-initialize workspace display names:", error);
|
|
@@ -27245,7 +27353,7 @@ function HomeView({
|
|
|
27245
27353
|
}
|
|
27246
27354
|
};
|
|
27247
27355
|
initDisplayNames();
|
|
27248
|
-
}, [selectedLineId]);
|
|
27356
|
+
}, [selectedLineId, factoryViewId, allLineIds]);
|
|
27249
27357
|
const {
|
|
27250
27358
|
displayNames: workspaceDisplayNames,
|
|
27251
27359
|
loading: displayNamesLoading,
|
|
@@ -27311,18 +27419,29 @@ function HomeView({
|
|
|
27311
27419
|
setErrorMessage(null);
|
|
27312
27420
|
}
|
|
27313
27421
|
}, [metricsError, kpisError]);
|
|
27314
|
-
React14.useCallback((
|
|
27422
|
+
const handleLineChange = React14.useCallback((value) => {
|
|
27315
27423
|
setIsChangingFilter(true);
|
|
27316
|
-
setSelectedLineId(
|
|
27424
|
+
setSelectedLineId(value);
|
|
27317
27425
|
}, []);
|
|
27318
27426
|
React14.useEffect(() => {
|
|
27319
|
-
if (!metricsLoading && !kpisLoading && isChangingFilter
|
|
27320
|
-
|
|
27427
|
+
if (!metricsLoading && !kpisLoading && isChangingFilter) {
|
|
27428
|
+
if (workspaceMetrics.length > 0 || selectedLineId === factoryViewId) {
|
|
27429
|
+
setIsChangingFilter(false);
|
|
27430
|
+
}
|
|
27321
27431
|
}
|
|
27322
|
-
}, [metricsLoading, kpisLoading, workspaceMetrics, isChangingFilter]);
|
|
27432
|
+
}, [metricsLoading, kpisLoading, workspaceMetrics, isChangingFilter, selectedLineId, factoryViewId]);
|
|
27323
27433
|
const lineTitle = React14.useMemo(() => {
|
|
27324
27434
|
return factoryName;
|
|
27325
27435
|
}, [factoryName]);
|
|
27436
|
+
const lineSelectorComponent = React14.useMemo(() => {
|
|
27437
|
+
if (allLineIds.length <= 1) {
|
|
27438
|
+
return null;
|
|
27439
|
+
}
|
|
27440
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Select, { onValueChange: handleLineChange, defaultValue: selectedLineId, children: [
|
|
27441
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { className: "w-full sm:w-[200px] bg-white border border-gray-200 shadow-sm rounded-md h-9 text-sm", children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: "Select a line" }) }),
|
|
27442
|
+
/* @__PURE__ */ jsxRuntime.jsx(SelectContent, { className: "z-50 bg-white shadow-lg border border-gray-200 rounded-md", children: availableLineIds.map((id3) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: id3, children: lineNames[id3] || (id3 === factoryViewId ? "All Lines" : `Line ${id3.substring(0, 4)}`) }, id3)) })
|
|
27443
|
+
] });
|
|
27444
|
+
}, [availableLineIds, handleLineChange, selectedLineId, lineNames, factoryViewId, allLineIds.length]);
|
|
27326
27445
|
const isLoading = !isHydrated || metricsLoading || kpisLoading || isChangingFilter || displayNamesLoading || !displayNamesInitialized;
|
|
27327
27446
|
if (isLoading) {
|
|
27328
27447
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-screen bg-slate-50", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingPageCmp, { message: "Loading dashboard..." }) });
|
|
@@ -27336,7 +27455,7 @@ function HomeView({
|
|
|
27336
27455
|
] })
|
|
27337
27456
|
] }) }) });
|
|
27338
27457
|
}
|
|
27339
|
-
if ((metricsLoading || kpisLoading) && (!workspaceMetrics || workspaceMetrics.length === 0)) {
|
|
27458
|
+
if ((metricsLoading || kpisLoading) && (!workspaceMetrics || workspaceMetrics.length === 0) && selectedLineId !== factoryViewId) {
|
|
27340
27459
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-screen bg-slate-50", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingPageCmp, { message: "Loading metrics..." }) });
|
|
27341
27460
|
}
|
|
27342
27461
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -27347,28 +27466,36 @@ function HomeView({
|
|
|
27347
27466
|
animate: { opacity: 1 },
|
|
27348
27467
|
children: [
|
|
27349
27468
|
/* @__PURE__ */ jsxRuntime.jsx(LoadingOverlayCmp, { isVisible: isChangingFilter, message: "Loading new metrics..." }),
|
|
27350
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
27351
|
-
/* @__PURE__ */ jsxRuntime.
|
|
27352
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27353
|
-
|
|
27354
|
-
|
|
27355
|
-
|
|
27356
|
-
|
|
27357
|
-
|
|
27358
|
-
|
|
27359
|
-
|
|
27360
|
-
|
|
27361
|
-
|
|
27362
|
-
|
|
27363
|
-
|
|
27364
|
-
|
|
27365
|
-
|
|
27366
|
-
|
|
27367
|
-
|
|
27368
|
-
|
|
27369
|
-
|
|
27370
|
-
}
|
|
27371
|
-
|
|
27469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-1", children: [
|
|
27470
|
+
/* @__PURE__ */ jsxRuntime.jsxs("main", { className: "flex flex-1 flex-col", children: [
|
|
27471
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sticky top-0 z-30 sm:static bg-white shadow-sm border-b border-gray-200/80", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col sm:flex-row sm:items-center sm:justify-between px-3 sm:px-6 lg:px-8 py-1.5 sm:py-2.5", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
27472
|
+
DashboardHeader,
|
|
27473
|
+
{
|
|
27474
|
+
lineTitle,
|
|
27475
|
+
className: "w-full",
|
|
27476
|
+
headerControls: memoizedKPIs ? /* @__PURE__ */ jsxRuntime.jsx(KPISection2, { kpis: memoizedKPIs, className: "w-full sm:w-auto" }) : null
|
|
27477
|
+
}
|
|
27478
|
+
) }) }),
|
|
27479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative", children: [
|
|
27480
|
+
lineSelectorComponent && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-3 top-2 sm:right-6 sm:top-3 z-30", children: lineSelectorComponent }),
|
|
27481
|
+
memoizedWorkspaceMetrics.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full sm:h-full min-h-[calc(100vh-80px)] sm:min-h-0", children: React14__namespace.default.createElement(WorkspaceGrid, {
|
|
27482
|
+
workspaces: memoizedWorkspaceMetrics,
|
|
27483
|
+
lineNames,
|
|
27484
|
+
factoryView: factoryViewId,
|
|
27485
|
+
videoSources,
|
|
27486
|
+
className: "h-full"
|
|
27487
|
+
}) }) : /* @__PURE__ */ jsxRuntime.jsx(NoWorkspaceData, { message: "No workspace data available. Select another line or check configurations." })
|
|
27488
|
+
] })
|
|
27489
|
+
] }),
|
|
27490
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
27491
|
+
BreakNotificationPopup,
|
|
27492
|
+
{
|
|
27493
|
+
activeBreaks,
|
|
27494
|
+
lineNames,
|
|
27495
|
+
isVisible: !breaksLoading && !breaksError
|
|
27496
|
+
}
|
|
27497
|
+
)
|
|
27498
|
+
] })
|
|
27372
27499
|
]
|
|
27373
27500
|
}
|
|
27374
27501
|
);
|
|
@@ -27532,7 +27659,7 @@ var BottomSection = React14.memo(({
|
|
|
27532
27659
|
"div",
|
|
27533
27660
|
{
|
|
27534
27661
|
className: "p-1.5 hover:bg-gray-100 rounded-lg transition-colors cursor-pointer",
|
|
27535
|
-
onClick: () => handleNavigate && handleNavigate(`/leaderboard
|
|
27662
|
+
onClick: () => handleNavigate && handleNavigate(`/leaderboard`),
|
|
27536
27663
|
children: /* @__PURE__ */ jsxRuntime.jsx(outline.ArrowRightIcon, { className: "w-5 h-5 text-gray-500" })
|
|
27537
27664
|
}
|
|
27538
27665
|
)
|
|
@@ -28631,7 +28758,7 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28631
28758
|
className = ""
|
|
28632
28759
|
}) => {
|
|
28633
28760
|
const navigation = useNavigation();
|
|
28634
|
-
const [sortAscending, setSortAscending] = React14.useState(
|
|
28761
|
+
const [sortAscending, setSortAscending] = React14.useState(false);
|
|
28635
28762
|
const handleSortToggle = React14.useCallback(() => {
|
|
28636
28763
|
setSortAscending(!sortAscending);
|
|
28637
28764
|
}, [sortAscending]);
|
|
@@ -28647,13 +28774,15 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28647
28774
|
error: metricsError,
|
|
28648
28775
|
refreshMetrics
|
|
28649
28776
|
} = useRealtimeLineMetrics(realtimeMetricsParams);
|
|
28650
|
-
const memoizedLineId = React14.useMemo(() => lineId || "", [lineId]);
|
|
28651
28777
|
const {
|
|
28652
28778
|
workspaces,
|
|
28653
28779
|
loading: workspacesLoading,
|
|
28654
28780
|
error: workspacesError,
|
|
28655
28781
|
refreshWorkspaces
|
|
28656
|
-
} =
|
|
28782
|
+
} = useAllWorkspaceMetrics({
|
|
28783
|
+
initialDate: date,
|
|
28784
|
+
initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0
|
|
28785
|
+
});
|
|
28657
28786
|
const getShiftName = React14.useCallback((shiftId) => {
|
|
28658
28787
|
if (shiftId === void 0) return "Day";
|
|
28659
28788
|
return shiftId === 0 ? "Day" : "Night";
|
|
@@ -28707,7 +28836,7 @@ var LeaderboardDetailView = React14.memo(({
|
|
|
28707
28836
|
});
|
|
28708
28837
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
28709
28838
|
const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName) : "";
|
|
28710
|
-
const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard
|
|
28839
|
+
const returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
|
|
28711
28840
|
if (onWorkspaceClick) {
|
|
28712
28841
|
onWorkspaceClick(workspace, rank);
|
|
28713
28842
|
} else {
|
|
@@ -32247,6 +32376,7 @@ exports.KPIHeader = KPIHeader;
|
|
|
32247
32376
|
exports.KPISection = KPISection;
|
|
32248
32377
|
exports.KPIsOverviewView = KPIsOverviewView_default;
|
|
32249
32378
|
exports.LINE_1_UUID = LINE_1_UUID;
|
|
32379
|
+
exports.LINE_2_UUID = LINE_2_UUID;
|
|
32250
32380
|
exports.LargeOutputProgressChart = LargeOutputProgressChart;
|
|
32251
32381
|
exports.LeaderboardDetailView = LeaderboardDetailView_default;
|
|
32252
32382
|
exports.Legend = Legend6;
|
|
@@ -32396,6 +32526,7 @@ exports.trackCoreEvent = trackCoreEvent;
|
|
|
32396
32526
|
exports.trackCorePageView = trackCorePageView;
|
|
32397
32527
|
exports.updateThreadTitle = updateThreadTitle;
|
|
32398
32528
|
exports.useActiveBreaks = useActiveBreaks;
|
|
32529
|
+
exports.useAllWorkspaceMetrics = useAllWorkspaceMetrics;
|
|
32399
32530
|
exports.useAnalyticsConfig = useAnalyticsConfig;
|
|
32400
32531
|
exports.useAuth = useAuth;
|
|
32401
32532
|
exports.useAuthConfig = useAuthConfig;
|