@optifye/dashboard-core 6.9.13 → 6.9.15
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 +13 -4
- package/dist/index.d.mts +430 -238
- package/dist/index.d.ts +430 -238
- package/dist/index.js +1294 -729
- package/dist/index.mjs +1289 -730
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -96,6 +96,32 @@ function isValidPrefetchStatus(status) {
|
|
|
96
96
|
return typeof status === "string" && Object.values(PrefetchStatus).includes(status);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
// src/lib/types/calendar.ts
|
|
100
|
+
var DEFAULT_SHIFT_DATA = {
|
|
101
|
+
efficiency: 0,
|
|
102
|
+
output: 0,
|
|
103
|
+
cycleTime: 0,
|
|
104
|
+
pph: 0,
|
|
105
|
+
pphThreshold: 0,
|
|
106
|
+
idealOutput: 0,
|
|
107
|
+
rank: 0,
|
|
108
|
+
idleTime: 0,
|
|
109
|
+
hasData: false
|
|
110
|
+
};
|
|
111
|
+
var getShiftData = (day, shiftId) => {
|
|
112
|
+
const shift = day.shifts[shiftId];
|
|
113
|
+
if (shift) {
|
|
114
|
+
return { ...shift, hasData: true };
|
|
115
|
+
}
|
|
116
|
+
return { ...DEFAULT_SHIFT_DATA };
|
|
117
|
+
};
|
|
118
|
+
var hasAnyShiftData = (day) => {
|
|
119
|
+
return Object.keys(day.shifts).length > 0;
|
|
120
|
+
};
|
|
121
|
+
var getAvailableShiftIds = (day) => {
|
|
122
|
+
return Object.keys(day.shifts).map(Number).sort((a, b) => a - b);
|
|
123
|
+
};
|
|
124
|
+
|
|
99
125
|
// src/components/dashboard/grid/workspace_grid_constants.ts
|
|
100
126
|
var DEFAULT_WORKSPACE_POSITIONS = [
|
|
101
127
|
// Middle top row - 7 tapping workspaces (conveyor style)
|
|
@@ -142,15 +168,21 @@ var DEFAULT_ENTITY_CONFIG = {
|
|
|
142
168
|
}
|
|
143
169
|
};
|
|
144
170
|
var DEFAULT_SHIFT_CONFIG = {
|
|
171
|
+
shifts: [
|
|
172
|
+
{ shiftId: 0, shiftName: "Day Shift", startTime: "06:00", endTime: "18:00", breaks: [], timezone: "UTC" },
|
|
173
|
+
{ shiftId: 1, shiftName: "Night Shift", startTime: "18:00", endTime: "06:00", breaks: [], timezone: "UTC" }
|
|
174
|
+
],
|
|
145
175
|
dayShift: {
|
|
146
176
|
id: 0,
|
|
147
177
|
startTime: "06:00",
|
|
148
|
-
endTime: "18:00"
|
|
178
|
+
endTime: "18:00",
|
|
179
|
+
name: "Day Shift"
|
|
149
180
|
},
|
|
150
181
|
nightShift: {
|
|
151
182
|
id: 1,
|
|
152
183
|
startTime: "18:00",
|
|
153
|
-
endTime: "06:00"
|
|
184
|
+
endTime: "06:00",
|
|
185
|
+
name: "Night Shift"
|
|
154
186
|
},
|
|
155
187
|
transitionPeriodMinutes: 15
|
|
156
188
|
};
|
|
@@ -500,70 +532,128 @@ var parseTimeToMinutes = (timeString) => {
|
|
|
500
532
|
const [hours, minutes] = timeString.split(":").map(Number);
|
|
501
533
|
return hours * 60 + minutes;
|
|
502
534
|
};
|
|
503
|
-
var
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
const
|
|
511
|
-
const
|
|
535
|
+
var normalizeShiftDefinitions = (timezone, shiftConfig) => {
|
|
536
|
+
if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
|
|
537
|
+
return {
|
|
538
|
+
shifts: shiftConfig.shifts,
|
|
539
|
+
timezone: shiftConfig.shifts[0].timezone || shiftConfig.timezone || timezone
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
const fallbackTimezone = shiftConfig?.timezone || timezone;
|
|
543
|
+
const legacyShifts = [];
|
|
544
|
+
if (shiftConfig?.dayShift) {
|
|
545
|
+
legacyShifts.push({
|
|
546
|
+
shiftId: shiftConfig.dayShift.id ?? 0,
|
|
547
|
+
shiftName: shiftConfig.dayShift.name || "Day Shift",
|
|
548
|
+
startTime: shiftConfig.dayShift.startTime || DEFAULT_DAY_SHIFT_START,
|
|
549
|
+
endTime: shiftConfig.dayShift.endTime || "18:00",
|
|
550
|
+
breaks: [],
|
|
551
|
+
timezone: fallbackTimezone
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
if (shiftConfig?.nightShift) {
|
|
555
|
+
legacyShifts.push({
|
|
556
|
+
shiftId: shiftConfig.nightShift.id ?? 1,
|
|
557
|
+
shiftName: shiftConfig.nightShift.name || "Night Shift",
|
|
558
|
+
startTime: shiftConfig.nightShift.startTime || DEFAULT_NIGHT_SHIFT_START,
|
|
559
|
+
endTime: shiftConfig.nightShift.endTime || "06:00",
|
|
560
|
+
breaks: [],
|
|
561
|
+
timezone: fallbackTimezone
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
if (legacyShifts.length === 0) {
|
|
565
|
+
legacyShifts.push(
|
|
566
|
+
{
|
|
567
|
+
shiftId: 0,
|
|
568
|
+
shiftName: "Day Shift",
|
|
569
|
+
startTime: DEFAULT_DAY_SHIFT_START,
|
|
570
|
+
endTime: "18:00",
|
|
571
|
+
breaks: [],
|
|
572
|
+
timezone: fallbackTimezone
|
|
573
|
+
},
|
|
574
|
+
{
|
|
575
|
+
shiftId: 1,
|
|
576
|
+
shiftName: "Night Shift",
|
|
577
|
+
startTime: DEFAULT_NIGHT_SHIFT_START,
|
|
578
|
+
endTime: "06:00",
|
|
579
|
+
breaks: [],
|
|
580
|
+
timezone: fallbackTimezone
|
|
581
|
+
}
|
|
582
|
+
);
|
|
583
|
+
}
|
|
584
|
+
return { shifts: legacyShifts, timezone: fallbackTimezone };
|
|
585
|
+
};
|
|
586
|
+
var determineShiftFromDefinitions = (timezone, shifts, now2 = /* @__PURE__ */ new Date()) => {
|
|
512
587
|
const zonedNow = toZonedTime(now2, timezone);
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
const
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
588
|
+
const currentMinutes = zonedNow.getHours() * 60 + zonedNow.getMinutes();
|
|
589
|
+
let chosen;
|
|
590
|
+
let operationalDate = getOperationalDate(timezone, zonedNow, shifts[0].startTime);
|
|
591
|
+
for (const shift of shifts) {
|
|
592
|
+
const start = parseTimeToMinutes(shift.startTime);
|
|
593
|
+
const endRaw = parseTimeToMinutes(shift.endTime);
|
|
594
|
+
let end = endRaw;
|
|
595
|
+
const wraps = end <= start;
|
|
596
|
+
if (wraps) end += 1440;
|
|
597
|
+
if (start <= currentMinutes && currentMinutes < end) {
|
|
598
|
+
chosen = shift;
|
|
599
|
+
operationalDate = getOperationalDate(timezone, zonedNow, shift.startTime);
|
|
600
|
+
break;
|
|
523
601
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
determinedShiftId = nightShiftId;
|
|
602
|
+
if (start <= currentMinutes + 1440 && currentMinutes + 1440 < end) {
|
|
603
|
+
chosen = shift;
|
|
604
|
+
operationalDate = getOperationalDate(timezone, zonedNow, shift.startTime);
|
|
605
|
+
break;
|
|
529
606
|
}
|
|
530
607
|
}
|
|
531
|
-
|
|
608
|
+
if (!chosen) {
|
|
609
|
+
chosen = shifts[0];
|
|
610
|
+
operationalDate = getOperationalDate(timezone, zonedNow, chosen.startTime);
|
|
611
|
+
}
|
|
612
|
+
return {
|
|
613
|
+
shiftId: chosen.shiftId,
|
|
614
|
+
shiftName: chosen.shiftName,
|
|
615
|
+
startTime: chosen.startTime,
|
|
616
|
+
endTime: chosen.endTime,
|
|
617
|
+
timezone,
|
|
618
|
+
date: operationalDate
|
|
619
|
+
};
|
|
620
|
+
};
|
|
621
|
+
var getCurrentShift = (timezone, shiftConfig, now2 = /* @__PURE__ */ new Date()) => {
|
|
622
|
+
const { shifts, timezone: effectiveTz } = normalizeShiftDefinitions(timezone, shiftConfig);
|
|
623
|
+
return determineShiftFromDefinitions(effectiveTz, shifts, now2);
|
|
532
624
|
};
|
|
533
625
|
var isTransitionPeriod = (timezone, shiftConfig, now2 = /* @__PURE__ */ new Date()) => {
|
|
534
|
-
const dayShiftStartStr = shiftConfig?.dayShift?.startTime || DEFAULT_DAY_SHIFT_START;
|
|
535
|
-
const nightShiftStartStr = shiftConfig?.nightShift?.startTime || DEFAULT_NIGHT_SHIFT_START;
|
|
536
626
|
const transitionMinutes = shiftConfig?.transitionPeriodMinutes ?? DEFAULT_TRANSITION_MINUTES;
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
const currentHour = zonedNow.getHours();
|
|
545
|
-
const currentMinutes = zonedNow.getMinutes();
|
|
546
|
-
const currentTotalMinutes = currentHour * 60 + currentMinutes;
|
|
547
|
-
return transitionTimes.some((transitionTime) => {
|
|
627
|
+
const { shifts, timezone: effectiveTz } = normalizeShiftDefinitions(timezone, shiftConfig);
|
|
628
|
+
if (!shifts.length) return false;
|
|
629
|
+
const zonedNow = toZonedTime(now2, effectiveTz);
|
|
630
|
+
const currentTotalMinutes = zonedNow.getHours() * 60 + zonedNow.getMinutes();
|
|
631
|
+
return shifts.some((shift) => {
|
|
632
|
+
const transitionTime = parseTimeToMinutes(shift.startTime);
|
|
633
|
+
if (isNaN(transitionTime)) return false;
|
|
548
634
|
const lowerBoundBefore = (transitionTime - transitionMinutes + 1440) % 1440;
|
|
549
635
|
const upperBoundBefore = transitionTime;
|
|
550
|
-
let isBefore = false;
|
|
551
|
-
if (lowerBoundBefore < upperBoundBefore) {
|
|
552
|
-
isBefore = currentTotalMinutes >= lowerBoundBefore && currentTotalMinutes < upperBoundBefore;
|
|
553
|
-
} else {
|
|
554
|
-
isBefore = currentTotalMinutes >= lowerBoundBefore || currentTotalMinutes < upperBoundBefore;
|
|
555
|
-
}
|
|
556
636
|
const lowerBoundAfter = transitionTime;
|
|
557
637
|
const upperBoundAfter = (transitionTime + transitionMinutes) % 1440;
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
} else {
|
|
562
|
-
isAfter = currentTotalMinutes >= lowerBoundAfter || currentTotalMinutes < upperBoundAfter;
|
|
563
|
-
}
|
|
564
|
-
return isBefore || isAfter;
|
|
638
|
+
const inBefore = lowerBoundBefore < upperBoundBefore ? currentTotalMinutes >= lowerBoundBefore && currentTotalMinutes < upperBoundBefore : currentTotalMinutes >= lowerBoundBefore || currentTotalMinutes < upperBoundBefore;
|
|
639
|
+
const inAfter = lowerBoundAfter < upperBoundAfter ? currentTotalMinutes >= lowerBoundAfter && currentTotalMinutes < upperBoundAfter : currentTotalMinutes >= lowerBoundAfter || currentTotalMinutes < upperBoundAfter;
|
|
640
|
+
return inBefore || inAfter;
|
|
565
641
|
});
|
|
566
642
|
};
|
|
643
|
+
var getShiftNameById = (shiftId, timezone, shiftConfig) => {
|
|
644
|
+
const { shifts } = normalizeShiftDefinitions(timezone, shiftConfig);
|
|
645
|
+
const shift = shifts.find((s) => s.shiftId === shiftId);
|
|
646
|
+
if (shift) {
|
|
647
|
+
return shift.shiftName;
|
|
648
|
+
}
|
|
649
|
+
if (shiftId === 0) return "Day Shift";
|
|
650
|
+
if (shiftId === 1) return "Night Shift";
|
|
651
|
+
return `Shift ${shiftId}`;
|
|
652
|
+
};
|
|
653
|
+
var getShortShiftName = (shiftId, timezone, shiftConfig) => {
|
|
654
|
+
const fullName = getShiftNameById(shiftId, timezone, shiftConfig);
|
|
655
|
+
return fullName.replace(/ Shift$/i, "");
|
|
656
|
+
};
|
|
567
657
|
|
|
568
658
|
// src/lib/utils/database.ts
|
|
569
659
|
var getCompanyMetricsTableName = (companyId, prefix = "workspace_performance") => {
|
|
@@ -1156,12 +1246,12 @@ var dashboardService = {
|
|
|
1156
1246
|
throw err;
|
|
1157
1247
|
}
|
|
1158
1248
|
},
|
|
1159
|
-
async getDetailedLineInfo(lineIdInput, dateProp, shiftProp) {
|
|
1249
|
+
async getDetailedLineInfo(lineIdInput, dateProp, shiftProp, providedShiftConfig) {
|
|
1160
1250
|
const supabase = _getSupabaseInstance();
|
|
1161
1251
|
const config = _getDashboardConfigInstance();
|
|
1162
1252
|
const dbConfig = config.databaseConfig ?? DEFAULT_DATABASE_CONFIG;
|
|
1163
1253
|
const entityConfig = config.entityConfig ?? DEFAULT_ENTITY_CONFIG;
|
|
1164
|
-
const shiftConfig = config.shiftConfig ?? DEFAULT_SHIFT_CONFIG;
|
|
1254
|
+
const shiftConfig = providedShiftConfig || (config.shiftConfig ?? DEFAULT_SHIFT_CONFIG);
|
|
1165
1255
|
const dateTimeConfig = config.dateTimeConfig ?? DEFAULT_DATE_TIME_CONFIG;
|
|
1166
1256
|
const workspaceConfig = config.workspaceConfig ?? DEFAULT_WORKSPACE_CONFIG;
|
|
1167
1257
|
const linesTable = getTable(dbConfig, "lines");
|
|
@@ -1248,8 +1338,8 @@ var dashboardService = {
|
|
|
1248
1338
|
underperforming_workspaces: combinedMetricsData.underperforming_workspaces,
|
|
1249
1339
|
line_threshold: combinedMetricsData.line_threshold,
|
|
1250
1340
|
threshold_pph: combinedMetricsData.threshold_pph / numLines,
|
|
1251
|
-
shift_start: metricsData?.[0]?.shift_start || shiftConfig.dayShift?.startTime || "06:00",
|
|
1252
|
-
shift_end: metricsData?.[0]?.shift_end || shiftConfig.dayShift?.endTime || "18:00",
|
|
1341
|
+
shift_start: metricsData?.[0]?.shift_start || (shiftConfig.shifts && shiftConfig.shifts.length > 0 ? shiftConfig.shifts.find((s) => s.shiftId === 0)?.startTime || shiftConfig.shifts[0].startTime : shiftConfig.dayShift?.startTime) || "06:00",
|
|
1342
|
+
shift_end: metricsData?.[0]?.shift_end || (shiftConfig.shifts && shiftConfig.shifts.length > 0 ? shiftConfig.shifts.find((s) => s.shiftId === 0)?.endTime || shiftConfig.shifts[0].endTime : shiftConfig.dayShift?.endTime) || "18:00",
|
|
1253
1343
|
last_updated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1254
1344
|
output_array: combinedMetricsData.outputArrays.length > 0 ? memoizedOutputArrayAggregation(combinedMetricsData.outputArrays) : [],
|
|
1255
1345
|
underperforming_workspace_names: combinedMetricsData.underperforming_workspace_names,
|
|
@@ -1290,8 +1380,8 @@ var dashboardService = {
|
|
|
1290
1380
|
underperforming_workspaces: metrics2?.underperforming_workspaces ?? 0,
|
|
1291
1381
|
line_threshold: metrics2?.line_threshold || 0,
|
|
1292
1382
|
threshold_pph: metrics2?.threshold_pph || 0,
|
|
1293
|
-
shift_start: metrics2?.shift_start || shiftConfig.dayShift?.startTime || "06:00",
|
|
1294
|
-
shift_end: metrics2?.shift_end || shiftConfig.dayShift?.endTime || "18:00",
|
|
1383
|
+
shift_start: metrics2?.shift_start || (shiftConfig.shifts && shiftConfig.shifts.length > 0 ? shiftConfig.shifts.find((s) => s.shiftId === 0)?.startTime || shiftConfig.shifts[0].startTime : shiftConfig.dayShift?.startTime) || "06:00",
|
|
1384
|
+
shift_end: metrics2?.shift_end || (shiftConfig.shifts && shiftConfig.shifts.length > 0 ? shiftConfig.shifts.find((s) => s.shiftId === 0)?.endTime || shiftConfig.shifts[0].endTime : shiftConfig.dayShift?.endTime) || "18:00",
|
|
1295
1385
|
last_updated: metrics2?.last_updated || (/* @__PURE__ */ new Date()).toISOString(),
|
|
1296
1386
|
output_array: metrics2?.output_array || [],
|
|
1297
1387
|
underperforming_workspace_names: metrics2?.underperforming_workspace_names || [],
|
|
@@ -1402,7 +1492,7 @@ var dashboardService = {
|
|
|
1402
1492
|
throw err;
|
|
1403
1493
|
}
|
|
1404
1494
|
},
|
|
1405
|
-
async getUnderperformingWorkspaces(lineIdInput, monthInput, yearInput) {
|
|
1495
|
+
async getUnderperformingWorkspaces(lineIdInput, monthInput, yearInput, shiftIds) {
|
|
1406
1496
|
_getSupabaseInstance();
|
|
1407
1497
|
const config = _getDashboardConfigInstance();
|
|
1408
1498
|
const entityConfig = config.entityConfig ?? DEFAULT_ENTITY_CONFIG;
|
|
@@ -1422,13 +1512,14 @@ var dashboardService = {
|
|
|
1422
1512
|
const currentDate = /* @__PURE__ */ new Date();
|
|
1423
1513
|
const currentMonth = monthInput !== void 0 ? monthInput : currentDate.getMonth();
|
|
1424
1514
|
const currentYear = yearInput !== void 0 ? yearInput : currentDate.getFullYear();
|
|
1515
|
+
const dynamicShiftIds = shiftIds || shiftConfig.shifts?.map((s) => s.shiftId) || [shiftConfig.dayShift?.id ?? 0, shiftConfig.nightShift?.id ?? 1];
|
|
1425
1516
|
const bodyPayload = {
|
|
1426
1517
|
lineId: lineIdInput === factoryViewId ? configuredLineIds : lineIdInput,
|
|
1427
1518
|
month: currentMonth,
|
|
1428
1519
|
year: currentYear,
|
|
1429
1520
|
companyId,
|
|
1430
1521
|
metricsTable,
|
|
1431
|
-
shifts:
|
|
1522
|
+
shifts: dynamicShiftIds
|
|
1432
1523
|
};
|
|
1433
1524
|
const response = await fetch(fullFunctionUrl, {
|
|
1434
1525
|
method: "POST",
|
|
@@ -2135,16 +2226,13 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2135
2226
|
this.cache.set(key, { data, timestamp: Date.now() });
|
|
2136
2227
|
}
|
|
2137
2228
|
getShiftTiming(timezone, shiftConfig) {
|
|
2138
|
-
const
|
|
2139
|
-
const
|
|
2140
|
-
const isDayShift = shiftId === dayShiftId;
|
|
2229
|
+
const currentShift = getCurrentShift(timezone, shiftConfig);
|
|
2230
|
+
const { shiftId, date, shiftName, startTime, endTime } = currentShift;
|
|
2141
2231
|
const defaultDayStart = "06:00";
|
|
2142
2232
|
const defaultDayEnd = "18:00";
|
|
2143
|
-
const
|
|
2144
|
-
const
|
|
2145
|
-
const
|
|
2146
|
-
const shiftEndStr = isDayShift ? shiftConfig?.dayShift?.endTime || defaultDayEnd : shiftConfig?.nightShift?.endTime || defaultNightEnd;
|
|
2147
|
-
const shiftLabel = isDayShift ? "Day Shift" : "Night Shift";
|
|
2233
|
+
const shiftStartStr = startTime || defaultDayStart;
|
|
2234
|
+
const shiftEndStr = endTime || defaultDayEnd;
|
|
2235
|
+
const shiftLabel = shiftName || (shiftId === 0 ? "Day Shift" : shiftId === 1 ? "Night Shift" : `Shift ${shiftId}`);
|
|
2148
2236
|
const parseTime = (value) => {
|
|
2149
2237
|
const [hourPart = "0", minutePart = "0"] = value.split(":");
|
|
2150
2238
|
const hour = Number.parseInt(hourPart, 10);
|
|
@@ -2219,6 +2307,13 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2219
2307
|
async getWorkspaceHealthStatus(options = {}) {
|
|
2220
2308
|
const supabase = _getSupabaseInstance();
|
|
2221
2309
|
if (!supabase) throw new Error("Supabase client not initialized");
|
|
2310
|
+
const dashboardConfig = _getDashboardConfigInstance();
|
|
2311
|
+
if (!options.shiftConfig) {
|
|
2312
|
+
console.warn("[workspaceHealthService.getWorkspaceHealthStatus] \u26A0\uFE0F No shiftConfig passed! Falling back to static config. This may cause incorrect shift_id queries.");
|
|
2313
|
+
}
|
|
2314
|
+
const shiftConfig = options.shiftConfig || dashboardConfig?.shiftConfig;
|
|
2315
|
+
const defaultTimezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
|
|
2316
|
+
const timezone = options.timezone || shiftConfig?.timezone || defaultTimezone;
|
|
2222
2317
|
let query = supabase.from("workspace_health_status").select("*").order("workspace_display_name", { ascending: true });
|
|
2223
2318
|
if (options.lineId) {
|
|
2224
2319
|
query = query.eq("line_id", options.lineId);
|
|
@@ -2236,7 +2331,7 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2236
2331
|
let uptimeMap = /* @__PURE__ */ new Map();
|
|
2237
2332
|
if (companyId) {
|
|
2238
2333
|
try {
|
|
2239
|
-
uptimeMap = await this.calculateWorkspaceUptime(companyId);
|
|
2334
|
+
uptimeMap = await this.calculateWorkspaceUptime(companyId, shiftConfig, timezone);
|
|
2240
2335
|
} catch (error2) {
|
|
2241
2336
|
console.error("Error calculating uptime:", error2);
|
|
2242
2337
|
}
|
|
@@ -2314,7 +2409,7 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2314
2409
|
}
|
|
2315
2410
|
return filteredData;
|
|
2316
2411
|
}
|
|
2317
|
-
async getWorkspaceUptimeTimeline(workspaceId, companyId) {
|
|
2412
|
+
async getWorkspaceUptimeTimeline(workspaceId, companyId, passedShiftConfig, passedTimezone) {
|
|
2318
2413
|
if (!workspaceId) {
|
|
2319
2414
|
throw new Error("workspaceId is required to fetch uptime timeline");
|
|
2320
2415
|
}
|
|
@@ -2324,8 +2419,12 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2324
2419
|
const supabase = _getSupabaseInstance();
|
|
2325
2420
|
if (!supabase) throw new Error("Supabase client not initialized");
|
|
2326
2421
|
const dashboardConfig = _getDashboardConfigInstance();
|
|
2327
|
-
const
|
|
2328
|
-
|
|
2422
|
+
const defaultTimezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
|
|
2423
|
+
if (!passedShiftConfig) {
|
|
2424
|
+
console.warn("[workspaceHealthService.getWorkspaceUptimeTimeline] \u26A0\uFE0F No shiftConfig passed! Falling back to static config. This may cause incorrect shift_id queries.");
|
|
2425
|
+
}
|
|
2426
|
+
const shiftConfig = passedShiftConfig || dashboardConfig?.shiftConfig;
|
|
2427
|
+
const timezone = passedTimezone || shiftConfig?.timezone || defaultTimezone;
|
|
2329
2428
|
const {
|
|
2330
2429
|
shiftId,
|
|
2331
2430
|
shiftLabel,
|
|
@@ -2566,18 +2665,22 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2566
2665
|
clearCache() {
|
|
2567
2666
|
this.cache.clear();
|
|
2568
2667
|
}
|
|
2569
|
-
async calculateWorkspaceUptime(companyId) {
|
|
2668
|
+
async calculateWorkspaceUptime(companyId, passedShiftConfig, timezone) {
|
|
2570
2669
|
const supabase = _getSupabaseInstance();
|
|
2571
2670
|
if (!supabase) throw new Error("Supabase client not initialized");
|
|
2572
2671
|
const dashboardConfig = _getDashboardConfigInstance();
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2672
|
+
const defaultTimezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
|
|
2673
|
+
if (!passedShiftConfig) {
|
|
2674
|
+
console.warn("[workspaceHealthService.calculateWorkspaceUptime] \u26A0\uFE0F No shiftConfig passed! Falling back to static config. This may cause incorrect shift_id queries.");
|
|
2675
|
+
}
|
|
2676
|
+
const shiftConfig = passedShiftConfig || dashboardConfig?.shiftConfig;
|
|
2677
|
+
const effectiveTimezone = timezone || shiftConfig?.timezone || defaultTimezone;
|
|
2575
2678
|
const {
|
|
2576
2679
|
shiftId,
|
|
2577
2680
|
date,
|
|
2578
2681
|
shiftStartDate,
|
|
2579
2682
|
completedMinutes
|
|
2580
|
-
} = this.getShiftTiming(
|
|
2683
|
+
} = this.getShiftTiming(effectiveTimezone, shiftConfig);
|
|
2581
2684
|
const tableName = `performance_metrics_${companyId.replace(/-/g, "_")}`;
|
|
2582
2685
|
try {
|
|
2583
2686
|
const { data: queryData, error } = await supabase.from(tableName).select("workspace_id, workspace_display_name, output_hourly, output_array").eq("date", date).eq("shift_id", shiftId);
|
|
@@ -2600,7 +2703,7 @@ var WorkspaceHealthService = class _WorkspaceHealthService {
|
|
|
2600
2703
|
minuteDate,
|
|
2601
2704
|
outputHourly,
|
|
2602
2705
|
outputArray,
|
|
2603
|
-
|
|
2706
|
+
effectiveTimezone
|
|
2604
2707
|
);
|
|
2605
2708
|
if (status === "down") {
|
|
2606
2709
|
currentDownRun += 1;
|
|
@@ -4271,7 +4374,7 @@ var useAudioService = () => {
|
|
|
4271
4374
|
// src/lib/utils/dateShiftUtils.ts
|
|
4272
4375
|
function isValidShiftId(shiftId) {
|
|
4273
4376
|
const id3 = typeof shiftId === "string" ? parseInt(shiftId, 10) : shiftId;
|
|
4274
|
-
return id3
|
|
4377
|
+
return Number.isFinite(id3) && id3 >= 0;
|
|
4275
4378
|
}
|
|
4276
4379
|
var getSupabaseClient = () => {
|
|
4277
4380
|
const url = process.env.NEXT_PUBLIC_SUPABASE_URL;
|
|
@@ -6803,11 +6906,12 @@ var useMetrics = (tableName, options) => {
|
|
|
6803
6906
|
};
|
|
6804
6907
|
return { data, isLoading, error, refetch };
|
|
6805
6908
|
};
|
|
6806
|
-
var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
6909
|
+
var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId, options) => {
|
|
6807
6910
|
const entityConfig = useEntityConfig();
|
|
6808
6911
|
const databaseConfig = useDatabaseConfig();
|
|
6809
6912
|
const dateTimeConfig = useDateTimeConfig();
|
|
6810
|
-
const
|
|
6913
|
+
const staticShiftConfig = useShiftConfig();
|
|
6914
|
+
const shiftConfig = options?.shiftConfig || staticShiftConfig;
|
|
6811
6915
|
const workspaceConfig = useWorkspaceConfig();
|
|
6812
6916
|
const supabase = useSupabase();
|
|
6813
6917
|
const [metrics2, setMetrics] = useState(null);
|
|
@@ -6820,11 +6924,12 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
6820
6924
|
const companyId = entityConfig.companyId || "";
|
|
6821
6925
|
const metricsTablePrefix = getMetricsTablePrefix();
|
|
6822
6926
|
const metricsTable = `${metricsTablePrefix}_${companyId.replace(/-/g, "_")}`;
|
|
6823
|
-
const
|
|
6927
|
+
const appTimezone = useAppTimezone();
|
|
6928
|
+
const defaultTimezone = appTimezone || dateTimeConfig.defaultTimezone || "UTC";
|
|
6824
6929
|
const workspaceMetricsBaseTable = databaseConfig.tables?.workspaces ?? "workspace_metrics";
|
|
6825
6930
|
const workspaceActionsTable = databaseConfig.tables?.actions ?? "workspace_actions";
|
|
6826
6931
|
const fetchMetrics = useCallback(async () => {
|
|
6827
|
-
if (!workspaceId || isFetchingRef.current) return;
|
|
6932
|
+
if (!workspaceId || isFetchingRef.current || options?.enabled === false) return;
|
|
6828
6933
|
try {
|
|
6829
6934
|
isFetchingRef.current = true;
|
|
6830
6935
|
const currentShift = getCurrentShift(defaultTimezone, shiftConfig);
|
|
@@ -6861,6 +6966,16 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
6861
6966
|
throw new Error(`Invalid JSON response from backend. Received: ${responseText.substring(0, 100)}...`);
|
|
6862
6967
|
}
|
|
6863
6968
|
const data = backendData.metrics;
|
|
6969
|
+
if (data && options?.shiftConfig) {
|
|
6970
|
+
const dynamicShiftName = getShiftNameById(
|
|
6971
|
+
data.shift_id,
|
|
6972
|
+
appTimezone || "Asia/Kolkata",
|
|
6973
|
+
// Fallback timezone
|
|
6974
|
+
options.shiftConfig
|
|
6975
|
+
);
|
|
6976
|
+
data.shift_type = dynamicShiftName;
|
|
6977
|
+
console.log(`[useWorkspaceDetailedMetrics] Overriding shift name for ID ${data.shift_id}: ${dynamicShiftName}`);
|
|
6978
|
+
}
|
|
6864
6979
|
if (!data && !date && shiftId === void 0) {
|
|
6865
6980
|
console.log("[useWorkspaceDetailedMetrics] No data found for current date/shift, attempting to find most recent data...");
|
|
6866
6981
|
const fallbackResponse = await fetch(
|
|
@@ -7306,7 +7421,7 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
7306
7421
|
updateQueueRef.current = false;
|
|
7307
7422
|
setIsLoading(false);
|
|
7308
7423
|
}
|
|
7309
|
-
}, [supabase, workspaceId, date, shiftId, metricsTable, defaultTimezone, shiftConfig, workspaceConfig, companyId]);
|
|
7424
|
+
}, [supabase, workspaceId, date, shiftId, metricsTable, defaultTimezone, shiftConfig, workspaceConfig, companyId, options?.enabled]);
|
|
7310
7425
|
const queueUpdate = useCallback(() => {
|
|
7311
7426
|
if (!workspaceId || updateQueueRef.current) return;
|
|
7312
7427
|
updateQueueRef.current = true;
|
|
@@ -7339,7 +7454,7 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
7339
7454
|
return;
|
|
7340
7455
|
}
|
|
7341
7456
|
const channels = [];
|
|
7342
|
-
const operationalDate = date || getOperationalDate(defaultTimezone
|
|
7457
|
+
const operationalDate = date || getOperationalDate(defaultTimezone);
|
|
7343
7458
|
const currentShift = getCurrentShift(defaultTimezone, shiftConfig);
|
|
7344
7459
|
const queryShiftId = shiftId ?? currentShift.shiftId;
|
|
7345
7460
|
const metricsChannel = supabase.channel(`workspace-metrics-${workspaceId}`).on(
|
|
@@ -7438,11 +7553,170 @@ var useWorkspaceDetailedMetrics = (workspaceId, date, shiftId) => {
|
|
|
7438
7553
|
// Force refresh without cache
|
|
7439
7554
|
};
|
|
7440
7555
|
};
|
|
7556
|
+
var useLineShiftConfig = (lineId, fallbackConfig) => {
|
|
7557
|
+
const [shiftConfig, setShiftConfig] = useState(fallbackConfig || null);
|
|
7558
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
7559
|
+
const [error, setError] = useState(null);
|
|
7560
|
+
const supabase = useSupabase();
|
|
7561
|
+
useEffect(() => {
|
|
7562
|
+
if (!lineId || lineId === "factory" || lineId === "all") {
|
|
7563
|
+
setShiftConfig(fallbackConfig || null);
|
|
7564
|
+
setIsLoading(false);
|
|
7565
|
+
return;
|
|
7566
|
+
}
|
|
7567
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7568
|
+
if (!uuidRegex.test(lineId)) {
|
|
7569
|
+
console.warn(`[useShiftConfig] Invalid line ID format: ${lineId}, using fallback`);
|
|
7570
|
+
setShiftConfig(fallbackConfig || null);
|
|
7571
|
+
setIsLoading(false);
|
|
7572
|
+
return;
|
|
7573
|
+
}
|
|
7574
|
+
let mounted = true;
|
|
7575
|
+
const calculateBreakDuration2 = (startTime, endTime) => {
|
|
7576
|
+
const [sh, sm] = startTime.split(":").map(Number);
|
|
7577
|
+
const [eh, em] = endTime.split(":").map(Number);
|
|
7578
|
+
let startMinutes = sh * 60 + sm;
|
|
7579
|
+
let endMinutes = eh * 60 + em;
|
|
7580
|
+
if (endMinutes < startMinutes) {
|
|
7581
|
+
endMinutes += 24 * 60;
|
|
7582
|
+
}
|
|
7583
|
+
return endMinutes - startMinutes;
|
|
7584
|
+
};
|
|
7585
|
+
const fetchShiftConfig = async () => {
|
|
7586
|
+
try {
|
|
7587
|
+
setIsLoading(true);
|
|
7588
|
+
setError(null);
|
|
7589
|
+
console.log(`[useLineShiftConfig] \u{1F50D} Fetching shift config for line: ${lineId}`);
|
|
7590
|
+
const { data: shiftsData, error: shiftsError } = await supabase.from("line_operating_hours").select("shift_id, shift_name, start_time, end_time, breaks, timezone").eq("line_id", lineId);
|
|
7591
|
+
if (shiftsError) {
|
|
7592
|
+
console.error(`[useLineShiftConfig] \u274C Error fetching shifts:`, shiftsError);
|
|
7593
|
+
throw new Error(`Failed to fetch shift config: ${shiftsError.message}`);
|
|
7594
|
+
}
|
|
7595
|
+
if (!shiftsData || shiftsData.length === 0) {
|
|
7596
|
+
console.warn(`[useLineShiftConfig] \u26A0\uFE0F No shift config found for line ${lineId}, using fallback`);
|
|
7597
|
+
if (mounted) {
|
|
7598
|
+
setShiftConfig(fallbackConfig || null);
|
|
7599
|
+
setIsLoading(false);
|
|
7600
|
+
}
|
|
7601
|
+
return;
|
|
7602
|
+
}
|
|
7603
|
+
const stripSeconds = (timeStr) => {
|
|
7604
|
+
if (!timeStr) return timeStr;
|
|
7605
|
+
return timeStr.substring(0, 5);
|
|
7606
|
+
};
|
|
7607
|
+
const mapped = shiftsData.map((shift) => ({
|
|
7608
|
+
shiftId: shift.shift_id,
|
|
7609
|
+
shiftName: shift.shift_name || `Shift ${shift.shift_id}`,
|
|
7610
|
+
startTime: stripSeconds(shift.start_time),
|
|
7611
|
+
endTime: stripSeconds(shift.end_time),
|
|
7612
|
+
breaks: Array.isArray(shift.breaks) ? shift.breaks.map((b) => ({
|
|
7613
|
+
startTime: b.start || b.startTime || "00:00",
|
|
7614
|
+
endTime: b.end || b.endTime || "00:00",
|
|
7615
|
+
duration: calculateBreakDuration2(
|
|
7616
|
+
b.start || b.startTime || "00:00",
|
|
7617
|
+
b.end || b.endTime || "00:00"
|
|
7618
|
+
),
|
|
7619
|
+
remarks: b.remarks || b.name || ""
|
|
7620
|
+
})) : [],
|
|
7621
|
+
timezone: shift.timezone
|
|
7622
|
+
}));
|
|
7623
|
+
const day = mapped.find((s) => s.shiftId === 0);
|
|
7624
|
+
const night = mapped.find((s) => s.shiftId === 1);
|
|
7625
|
+
const config = {
|
|
7626
|
+
shifts: mapped,
|
|
7627
|
+
timezone: mapped[0]?.timezone,
|
|
7628
|
+
dayShift: day ? { id: day.shiftId, startTime: day.startTime, endTime: day.endTime, name: day.shiftName } : fallbackConfig?.dayShift,
|
|
7629
|
+
nightShift: night ? { id: night.shiftId, startTime: night.startTime, endTime: night.endTime, name: night.shiftName } : fallbackConfig?.nightShift,
|
|
7630
|
+
transitionPeriodMinutes: fallbackConfig?.transitionPeriodMinutes || 0
|
|
7631
|
+
};
|
|
7632
|
+
console.log(`[useLineShiftConfig] \u2705 Built config from DB:`, config);
|
|
7633
|
+
if (mounted) {
|
|
7634
|
+
setShiftConfig(config);
|
|
7635
|
+
setIsLoading(false);
|
|
7636
|
+
}
|
|
7637
|
+
} catch (err) {
|
|
7638
|
+
console.error("[useShiftConfig] Error fetching shift config:", err);
|
|
7639
|
+
if (mounted) {
|
|
7640
|
+
setError(err instanceof Error ? err.message : "Unknown error occurred");
|
|
7641
|
+
setShiftConfig(fallbackConfig || null);
|
|
7642
|
+
setIsLoading(false);
|
|
7643
|
+
}
|
|
7644
|
+
}
|
|
7645
|
+
};
|
|
7646
|
+
fetchShiftConfig();
|
|
7647
|
+
const subscription = supabase.channel(`shift_config_${lineId}`).on(
|
|
7648
|
+
"postgres_changes",
|
|
7649
|
+
{
|
|
7650
|
+
event: "*",
|
|
7651
|
+
// Listen to all events (INSERT, UPDATE, DELETE)
|
|
7652
|
+
schema: "public",
|
|
7653
|
+
table: "line_operating_hours",
|
|
7654
|
+
filter: `line_id=eq.${lineId}`
|
|
7655
|
+
},
|
|
7656
|
+
(payload) => {
|
|
7657
|
+
console.log("[useShiftConfig] Real-time update received:", payload);
|
|
7658
|
+
fetchShiftConfig();
|
|
7659
|
+
}
|
|
7660
|
+
).subscribe();
|
|
7661
|
+
return () => {
|
|
7662
|
+
mounted = false;
|
|
7663
|
+
subscription.unsubscribe();
|
|
7664
|
+
};
|
|
7665
|
+
}, [lineId, supabase]);
|
|
7666
|
+
return {
|
|
7667
|
+
shiftConfig,
|
|
7668
|
+
isLoading,
|
|
7669
|
+
error
|
|
7670
|
+
};
|
|
7671
|
+
};
|
|
7672
|
+
|
|
7673
|
+
// src/lib/hooks/useDynamicShiftConfig.ts
|
|
7674
|
+
var useDynamicShiftConfig = (lineId) => {
|
|
7675
|
+
const staticShiftConfig = useShiftConfig();
|
|
7676
|
+
const { shiftConfig: dbShiftConfig, isLoading, error } = useLineShiftConfig(lineId, staticShiftConfig);
|
|
7677
|
+
const result = useMemo(() => {
|
|
7678
|
+
console.log(`[useDynamicShiftConfig] \u{1F504} Computing result for lineId: ${lineId}`, {
|
|
7679
|
+
isLoading,
|
|
7680
|
+
hasDbConfig: !!dbShiftConfig,
|
|
7681
|
+
error
|
|
7682
|
+
});
|
|
7683
|
+
if (isLoading) {
|
|
7684
|
+
console.log(`[useDynamicShiftConfig] \u23F3 Still loading, returning null (DO NOT USE until loaded)`);
|
|
7685
|
+
return {
|
|
7686
|
+
shiftConfig: null,
|
|
7687
|
+
isLoading: true,
|
|
7688
|
+
error: null,
|
|
7689
|
+
isFromDatabase: false
|
|
7690
|
+
};
|
|
7691
|
+
}
|
|
7692
|
+
if (dbShiftConfig) {
|
|
7693
|
+
console.log(`[useDynamicShiftConfig] \u2705 Using DB config:`, dbShiftConfig);
|
|
7694
|
+
return {
|
|
7695
|
+
shiftConfig: dbShiftConfig,
|
|
7696
|
+
isLoading: false,
|
|
7697
|
+
error,
|
|
7698
|
+
isFromDatabase: true
|
|
7699
|
+
};
|
|
7700
|
+
}
|
|
7701
|
+
console.log(`[useDynamicShiftConfig] \u26A0\uFE0F No DB config found, falling back to static config`);
|
|
7702
|
+
return {
|
|
7703
|
+
shiftConfig: staticShiftConfig,
|
|
7704
|
+
isLoading: false,
|
|
7705
|
+
error,
|
|
7706
|
+
isFromDatabase: false
|
|
7707
|
+
};
|
|
7708
|
+
}, [dbShiftConfig, staticShiftConfig, isLoading, error, lineId]);
|
|
7709
|
+
return result;
|
|
7710
|
+
};
|
|
7711
|
+
|
|
7712
|
+
// src/lib/hooks/useLineWorkspaceMetrics.ts
|
|
7441
7713
|
var useLineWorkspaceMetrics = (lineId, options) => {
|
|
7442
7714
|
const entityConfig = useEntityConfig();
|
|
7443
7715
|
const databaseConfig = useDatabaseConfig();
|
|
7444
7716
|
const dateTimeConfig = useDateTimeConfig();
|
|
7445
|
-
const
|
|
7717
|
+
const staticShiftConfig = useShiftConfig();
|
|
7718
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
7719
|
+
const shiftConfig = dynamicShiftConfig || staticShiftConfig;
|
|
7446
7720
|
const timezone = useAppTimezone();
|
|
7447
7721
|
const supabase = useSupabase();
|
|
7448
7722
|
const [workspaces, setWorkspaces] = useState([]);
|
|
@@ -7450,12 +7724,10 @@ var useLineWorkspaceMetrics = (lineId, options) => {
|
|
|
7450
7724
|
const [error, setError] = useState(null);
|
|
7451
7725
|
const [initialized, setInitialized] = useState(false);
|
|
7452
7726
|
const queryShiftId = useMemo(() => {
|
|
7453
|
-
const
|
|
7454
|
-
|
|
7455
|
-
shiftConfig
|
|
7456
|
-
);
|
|
7727
|
+
const effectiveTimezone = timezone || dateTimeConfig.defaultTimezone || "Asia/Kolkata";
|
|
7728
|
+
const currentShift = getCurrentShift(effectiveTimezone, shiftConfig);
|
|
7457
7729
|
return options?.initialShiftId !== void 0 ? options.initialShiftId : currentShift.shiftId;
|
|
7458
|
-
}, [options?.initialShiftId, dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
7730
|
+
}, [options?.initialShiftId, timezone, dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
7459
7731
|
const queryDate = useMemo(() => {
|
|
7460
7732
|
return options?.initialDate || getOperationalDate(timezone || dateTimeConfig.defaultTimezone || "UTC");
|
|
7461
7733
|
}, [options?.initialDate, timezone, dateTimeConfig.defaultTimezone]);
|
|
@@ -7467,7 +7739,7 @@ var useLineWorkspaceMetrics = (lineId, options) => {
|
|
|
7467
7739
|
}, [entityConfig.companyId]);
|
|
7468
7740
|
const schema = databaseConfig.schema ?? "public";
|
|
7469
7741
|
const fetchWorkspaceMetrics = useCallback(async () => {
|
|
7470
|
-
if (!lineId) return;
|
|
7742
|
+
if (!lineId || options?.enabled === false || isShiftConfigLoading) return;
|
|
7471
7743
|
if (!initialized) {
|
|
7472
7744
|
setLoading(true);
|
|
7473
7745
|
}
|
|
@@ -7524,7 +7796,7 @@ var useLineWorkspaceMetrics = (lineId, options) => {
|
|
|
7524
7796
|
} finally {
|
|
7525
7797
|
setLoading(false);
|
|
7526
7798
|
}
|
|
7527
|
-
}, [lineId, queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId]);
|
|
7799
|
+
}, [lineId, queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId, options?.enabled, isShiftConfigLoading]);
|
|
7528
7800
|
useEffect(() => {
|
|
7529
7801
|
if (!initialized) {
|
|
7530
7802
|
fetchWorkspaceMetrics();
|
|
@@ -7554,25 +7826,26 @@ var useLineWorkspaceMetrics = (lineId, options) => {
|
|
|
7554
7826
|
supabase.removeChannel(channel);
|
|
7555
7827
|
}
|
|
7556
7828
|
};
|
|
7557
|
-
}, [lineId, queryDate, queryShiftId, metricsTable, fetchWorkspaceMetrics, initialized, supabase, schema]);
|
|
7829
|
+
}, [lineId, queryDate, queryShiftId, metricsTable, fetchWorkspaceMetrics, initialized, supabase, schema, isShiftConfigLoading]);
|
|
7558
7830
|
useEffect(() => {
|
|
7559
7831
|
setInitialized(false);
|
|
7560
|
-
}, [lineId, queryDate, queryShiftId]);
|
|
7832
|
+
}, [lineId, queryDate, queryShiftId, isShiftConfigLoading]);
|
|
7561
7833
|
const refreshWorkspaces = fetchWorkspaceMetrics;
|
|
7562
7834
|
return useMemo(
|
|
7563
7835
|
() => ({ workspaces, loading, error, refreshWorkspaces }),
|
|
7564
7836
|
[workspaces, loading, error, refreshWorkspaces]
|
|
7565
7837
|
);
|
|
7566
7838
|
};
|
|
7567
|
-
var useHistoricWorkspaceMetrics = (workspaceId, date, shiftId) => {
|
|
7839
|
+
var useHistoricWorkspaceMetrics = (workspaceId, date, shiftId, options) => {
|
|
7568
7840
|
const supabase = useSupabase();
|
|
7569
7841
|
const entityConfig = useEntityConfig();
|
|
7842
|
+
const timezone = useAppTimezone();
|
|
7570
7843
|
const [metrics2, setMetrics] = useState(null);
|
|
7571
7844
|
const [isLoading, setIsLoading] = useState(true);
|
|
7572
7845
|
const [error, setError] = useState(null);
|
|
7573
7846
|
const isFetchingRef = useRef(false);
|
|
7574
7847
|
const fetchMetrics = useCallback(async () => {
|
|
7575
|
-
if (!supabase || !workspaceId || !date || isFetchingRef.current) return;
|
|
7848
|
+
if (!supabase || !workspaceId || !date || isFetchingRef.current || options?.enabled === false) return;
|
|
7576
7849
|
try {
|
|
7577
7850
|
isFetchingRef.current = true;
|
|
7578
7851
|
setIsLoading(true);
|
|
@@ -7606,7 +7879,18 @@ var useHistoricWorkspaceMetrics = (workspaceId, date, shiftId) => {
|
|
|
7606
7879
|
throw new Error(`Backend API error (${response.status}): ${errorText}`);
|
|
7607
7880
|
}
|
|
7608
7881
|
const data = await response.json();
|
|
7609
|
-
|
|
7882
|
+
const fetchedMetrics = data.metrics;
|
|
7883
|
+
if (fetchedMetrics && options?.shiftConfig) {
|
|
7884
|
+
const dynamicShiftName = getShiftNameById(
|
|
7885
|
+
fetchedMetrics.shift_id,
|
|
7886
|
+
timezone || "Asia/Kolkata",
|
|
7887
|
+
// Fallback timezone
|
|
7888
|
+
options.shiftConfig
|
|
7889
|
+
);
|
|
7890
|
+
fetchedMetrics.shift_type = dynamicShiftName;
|
|
7891
|
+
console.log(`[useHistoricWorkspaceMetrics] Overriding shift name for ID ${fetchedMetrics.shift_id}: ${dynamicShiftName}`);
|
|
7892
|
+
}
|
|
7893
|
+
setMetrics(fetchedMetrics || null);
|
|
7610
7894
|
} catch (err) {
|
|
7611
7895
|
console.error("[useHistoricWorkspaceMetrics] Error fetching historic metrics:", err);
|
|
7612
7896
|
setError({ message: err.message, code: err.code || "FETCH_ERROR" });
|
|
@@ -7615,7 +7899,7 @@ var useHistoricWorkspaceMetrics = (workspaceId, date, shiftId) => {
|
|
|
7615
7899
|
setIsLoading(false);
|
|
7616
7900
|
isFetchingRef.current = false;
|
|
7617
7901
|
}
|
|
7618
|
-
}, [supabase, workspaceId, date, shiftId, entityConfig.companyId]);
|
|
7902
|
+
}, [supabase, workspaceId, date, shiftId, entityConfig.companyId, options?.shiftConfig, timezone, options?.enabled]);
|
|
7619
7903
|
useEffect(() => {
|
|
7620
7904
|
fetchMetrics();
|
|
7621
7905
|
}, [fetchMetrics]);
|
|
@@ -7630,8 +7914,11 @@ var useLineDetailedMetrics = (lineIdFromProp) => {
|
|
|
7630
7914
|
const entityConfig = useEntityConfig();
|
|
7631
7915
|
const databaseConfig = useDatabaseConfig();
|
|
7632
7916
|
const dateTimeConfig = useDateTimeConfig();
|
|
7633
|
-
const
|
|
7917
|
+
const staticShiftConfig = useShiftConfig();
|
|
7634
7918
|
const supabase = useSupabase();
|
|
7919
|
+
const lineIdForShiftConfig = lineIdFromProp === "factory" ? getConfiguredLineIds(entityConfig)[0] : lineIdFromProp;
|
|
7920
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineIdForShiftConfig);
|
|
7921
|
+
const shiftConfig = dynamicShiftConfig || staticShiftConfig;
|
|
7635
7922
|
const [lineData, setLineData] = useState(null);
|
|
7636
7923
|
const [loading, setLoading] = useState(true);
|
|
7637
7924
|
const [error, setError] = useState(null);
|
|
@@ -7670,8 +7957,10 @@ var useLineDetailedMetrics = (lineIdFromProp) => {
|
|
|
7670
7957
|
}
|
|
7671
7958
|
}, [dashboardService, lineIdToUse, defaultTimezone, shiftConfig, entityConfig]);
|
|
7672
7959
|
useEffect(() => {
|
|
7673
|
-
if (!supabase || !lineIdToUse || !entityConfig.companyId) {
|
|
7674
|
-
|
|
7960
|
+
if (!supabase || !lineIdToUse || !entityConfig.companyId || isShiftConfigLoading) {
|
|
7961
|
+
if (!isShiftConfigLoading) {
|
|
7962
|
+
setLoading(false);
|
|
7963
|
+
}
|
|
7675
7964
|
if (!entityConfig.companyId && (!error || error.code !== "SERVICE_ERROR")) {
|
|
7676
7965
|
setError({ message: "Company ID not configured for metrics subscription.", code: "CONFIG_ERROR" });
|
|
7677
7966
|
}
|
|
@@ -7736,7 +8025,7 @@ var useLineDetailedMetrics = (lineIdFromProp) => {
|
|
|
7736
8025
|
channelRef.current = null;
|
|
7737
8026
|
}
|
|
7738
8027
|
};
|
|
7739
|
-
}, [supabase, lineIdToUse, fetchData, schema, lineMetricsTable, entityConfig, defaultTimezone, shiftConfig, error]);
|
|
8028
|
+
}, [supabase, lineIdToUse, fetchData, schema, lineMetricsTable, entityConfig, defaultTimezone, shiftConfig, isShiftConfigLoading, error]);
|
|
7740
8029
|
return {
|
|
7741
8030
|
lineData,
|
|
7742
8031
|
// This now contains both metrics and line details via LineInfo type
|
|
@@ -7749,14 +8038,20 @@ var useLeaderboardMetrics = (date, shiftId, limit = 10, filter2 = "all") => {
|
|
|
7749
8038
|
const supabase = useSupabase();
|
|
7750
8039
|
const entityConfig = useEntityConfig();
|
|
7751
8040
|
const dateTimeConfig = useDateTimeConfig();
|
|
7752
|
-
const
|
|
8041
|
+
const staticShiftConfig = useShiftConfig();
|
|
8042
|
+
const firstLineId = useMemo(() => {
|
|
8043
|
+
const lineIds = getConfiguredLineIds(entityConfig);
|
|
8044
|
+
return lineIds[0];
|
|
8045
|
+
}, [entityConfig]);
|
|
8046
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(firstLineId);
|
|
8047
|
+
const shiftConfig = dynamicShiftConfig || staticShiftConfig;
|
|
7753
8048
|
const [leaderboard, setLeaderboard] = useState([]);
|
|
7754
8049
|
const [isLoading, setIsLoading] = useState(true);
|
|
7755
8050
|
const [error, setError] = useState(null);
|
|
7756
8051
|
const isFetchingRef = useRef(false);
|
|
7757
8052
|
const defaultTimezone = dateTimeConfig.defaultTimezone || "UTC";
|
|
7758
8053
|
const fetchLeaderboard = useCallback(async () => {
|
|
7759
|
-
if (!supabase || isFetchingRef.current) return;
|
|
8054
|
+
if (!supabase || isFetchingRef.current || isShiftConfigLoading) return;
|
|
7760
8055
|
try {
|
|
7761
8056
|
isFetchingRef.current = true;
|
|
7762
8057
|
setIsLoading(true);
|
|
@@ -7802,7 +8097,7 @@ var useLeaderboardMetrics = (date, shiftId, limit = 10, filter2 = "all") => {
|
|
|
7802
8097
|
setIsLoading(false);
|
|
7803
8098
|
isFetchingRef.current = false;
|
|
7804
8099
|
}
|
|
7805
|
-
}, [supabase, date, shiftId, limit, filter2, entityConfig.companyId, defaultTimezone, shiftConfig]);
|
|
8100
|
+
}, [supabase, date, shiftId, limit, filter2, entityConfig.companyId, defaultTimezone, shiftConfig, isShiftConfigLoading]);
|
|
7806
8101
|
useEffect(() => {
|
|
7807
8102
|
fetchLeaderboard();
|
|
7808
8103
|
}, [fetchLeaderboard]);
|
|
@@ -7818,8 +8113,22 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
7818
8113
|
const entityConfig = useEntityConfig();
|
|
7819
8114
|
const databaseConfig = useDatabaseConfig();
|
|
7820
8115
|
const dateTimeConfig = useDateTimeConfig();
|
|
7821
|
-
const
|
|
7822
|
-
const
|
|
8116
|
+
const isFactoryView = lineId === (entityConfig.factoryViewId || "factory");
|
|
8117
|
+
const firstLineId = useMemo(() => {
|
|
8118
|
+
const configuredLineIds = getConfiguredLineIds(entityConfig);
|
|
8119
|
+
return configuredLineIds.length > 0 ? configuredLineIds[0] : void 0;
|
|
8120
|
+
}, [entityConfig]);
|
|
8121
|
+
const lineIdForShiftConfig = isFactoryView ? firstLineId : lineId;
|
|
8122
|
+
const { shiftConfig, isLoading: shiftLoading, isFromDatabase } = useDynamicShiftConfig(lineIdForShiftConfig);
|
|
8123
|
+
console.log(`[useDashboardMetrics] \u{1F3AF} Shift config for line ${lineId}:`, {
|
|
8124
|
+
isFactoryView,
|
|
8125
|
+
lineIdForShiftConfig,
|
|
8126
|
+
firstLineId,
|
|
8127
|
+
isFromDatabase,
|
|
8128
|
+
shiftConfig: shiftConfig ? { shifts: shiftConfig.shifts?.length, timezone: shiftConfig.timezone } : null
|
|
8129
|
+
});
|
|
8130
|
+
const appTimezone = useAppTimezone();
|
|
8131
|
+
const defaultTimezone = appTimezone || dateTimeConfig?.defaultTimezone || "UTC";
|
|
7823
8132
|
const configuredLineMetricsTable = databaseConfig?.tables?.lineMetrics ?? "line_metrics";
|
|
7824
8133
|
const schema = databaseConfig?.schema ?? "public";
|
|
7825
8134
|
const supabase = useSupabase();
|
|
@@ -7845,8 +8154,8 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
7845
8154
|
const fetchAllMetrics = useCallback(async () => {
|
|
7846
8155
|
const currentLineIdToUse = lineIdRef.current;
|
|
7847
8156
|
console.log("[useDashboardMetrics] Fetching from backend API. lineId:", currentLineIdToUse);
|
|
7848
|
-
if (!currentLineIdToUse || !supabase || isFetchingRef.current || companySpecificMetricsTable.includes("unknown_company")) {
|
|
7849
|
-
if (!metrics2?.workspaceMetrics?.length && !metrics2?.lineMetrics?.length) setIsLoading(false);
|
|
8157
|
+
if (!currentLineIdToUse || !supabase || isFetchingRef.current || shiftLoading || companySpecificMetricsTable.includes("unknown_company")) {
|
|
8158
|
+
if (!metrics2?.workspaceMetrics?.length && !metrics2?.lineMetrics?.length && !shiftLoading) setIsLoading(false);
|
|
7850
8159
|
if (companySpecificMetricsTable.includes("unknown_company") && !error) {
|
|
7851
8160
|
setError({ message: "Company ID not configured for metrics table.", code: "CONFIG_ERROR" });
|
|
7852
8161
|
}
|
|
@@ -7865,7 +8174,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
7865
8174
|
if (targetLineIds.length === 0) {
|
|
7866
8175
|
throw new Error("No target line IDs available for fetching metrics.");
|
|
7867
8176
|
}
|
|
7868
|
-
const
|
|
8177
|
+
const isFactoryView2 = currentLineIdToUse === (entityConfig.factoryViewId || "factory");
|
|
7869
8178
|
const { data: { session } } = await supabase.auth.getSession();
|
|
7870
8179
|
console.log("[useDashboardMetrics] Session check:", {
|
|
7871
8180
|
hasSession: !!session,
|
|
@@ -7879,7 +8188,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
7879
8188
|
if (!apiUrl) {
|
|
7880
8189
|
throw new Error("Backend URL is not configured. Please set NEXT_PUBLIC_BACKEND_URL in your environment.");
|
|
7881
8190
|
}
|
|
7882
|
-
const lineIdsParam =
|
|
8191
|
+
const lineIdsParam = isFactoryView2 ? `line_ids=${targetLineIds.join(",")}` : `line_id=${targetLineIds[0]}`;
|
|
7883
8192
|
const url = `${apiUrl}/api/dashboard/metrics?${lineIdsParam}&date=${operationalDate}&shift_id=${currentShiftDetails.shiftId}&company_id=${entityConfig.companyId}`;
|
|
7884
8193
|
console.log("[useDashboardMetrics] Calling backend API:", {
|
|
7885
8194
|
url,
|
|
@@ -7958,8 +8267,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
7958
8267
|
metrics2?.lineMetrics?.length || 0,
|
|
7959
8268
|
companySpecificMetricsTable,
|
|
7960
8269
|
entityConfig,
|
|
8270
|
+
appTimezone,
|
|
7961
8271
|
defaultTimezone,
|
|
7962
|
-
shiftConfig
|
|
8272
|
+
shiftConfig,
|
|
8273
|
+
shiftLoading
|
|
7963
8274
|
]);
|
|
7964
8275
|
const fetchAllMetricsRef = useRef(fetchAllMetrics);
|
|
7965
8276
|
useEffect(() => {
|
|
@@ -7973,10 +8284,10 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
7973
8284
|
fetchAllMetricsRef.current();
|
|
7974
8285
|
}, [supabase]);
|
|
7975
8286
|
useEffect(() => {
|
|
7976
|
-
if (lineId && supabase) {
|
|
8287
|
+
if (lineId && supabase && !shiftLoading) {
|
|
7977
8288
|
fetchAllMetrics();
|
|
7978
8289
|
}
|
|
7979
|
-
}, [lineId, supabase, fetchAllMetrics]);
|
|
8290
|
+
}, [lineId, supabase, fetchAllMetrics, shiftLoading]);
|
|
7980
8291
|
useEffect(() => {
|
|
7981
8292
|
const currentLineIdToUse = lineIdRef.current;
|
|
7982
8293
|
if (!currentLineIdToUse || !supabase || companySpecificMetricsTable.includes("unknown_company") || !entityConfig.companyId) {
|
|
@@ -8021,7 +8332,9 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
8021
8332
|
schema,
|
|
8022
8333
|
entityConfig?.companyId,
|
|
8023
8334
|
entityConfig?.factoryViewId,
|
|
8335
|
+
appTimezone,
|
|
8024
8336
|
defaultTimezone,
|
|
8337
|
+
shiftConfig,
|
|
8025
8338
|
lineId,
|
|
8026
8339
|
userAccessibleLineIds
|
|
8027
8340
|
]);
|
|
@@ -8033,145 +8346,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
8033
8346
|
refetch: fetchAllMetrics
|
|
8034
8347
|
};
|
|
8035
8348
|
};
|
|
8036
|
-
var
|
|
8037
|
-
const [shiftConfig, setShiftConfig] = useState(fallbackConfig || null);
|
|
8038
|
-
const [isLoading, setIsLoading] = useState(true);
|
|
8039
|
-
const [error, setError] = useState(null);
|
|
8040
|
-
const supabase = useSupabase();
|
|
8041
|
-
useEffect(() => {
|
|
8042
|
-
if (!lineId || lineId === "factory" || lineId === "all") {
|
|
8043
|
-
setShiftConfig(fallbackConfig || null);
|
|
8044
|
-
setIsLoading(false);
|
|
8045
|
-
return;
|
|
8046
|
-
}
|
|
8047
|
-
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
8048
|
-
if (!uuidRegex.test(lineId)) {
|
|
8049
|
-
console.warn(`[useShiftConfig] Invalid line ID format: ${lineId}, using fallback`);
|
|
8050
|
-
setShiftConfig(fallbackConfig || null);
|
|
8051
|
-
setIsLoading(false);
|
|
8052
|
-
return;
|
|
8053
|
-
}
|
|
8054
|
-
let mounted = true;
|
|
8055
|
-
const fetchShiftConfig = async () => {
|
|
8056
|
-
try {
|
|
8057
|
-
setIsLoading(true);
|
|
8058
|
-
setError(null);
|
|
8059
|
-
console.log(`[useLineShiftConfig] \u{1F50D} Fetching shift config for line: ${lineId}`);
|
|
8060
|
-
const { data: dayShift, error: dayError } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", 0).maybeSingle();
|
|
8061
|
-
const { data: nightShift, error: nightError } = await supabase.from("line_operating_hours").select("start_time, end_time, breaks").eq("line_id", lineId).eq("shift_id", 1).maybeSingle();
|
|
8062
|
-
console.log(`[useLineShiftConfig] \u{1F4CA} Day shift data:`, dayShift);
|
|
8063
|
-
console.log(`[useLineShiftConfig] \u{1F319} Night shift data:`, nightShift);
|
|
8064
|
-
if (dayError || nightError) {
|
|
8065
|
-
console.error(`[useLineShiftConfig] \u274C Error fetching:`, { dayError, nightError });
|
|
8066
|
-
throw new Error(`Failed to fetch shift config: ${dayError?.message || nightError?.message}`);
|
|
8067
|
-
}
|
|
8068
|
-
if (!dayShift && !nightShift) {
|
|
8069
|
-
console.warn(`[useLineShiftConfig] \u26A0\uFE0F No shift config found for line ${lineId}, using fallback`);
|
|
8070
|
-
if (mounted) {
|
|
8071
|
-
setShiftConfig(fallbackConfig || null);
|
|
8072
|
-
setIsLoading(false);
|
|
8073
|
-
}
|
|
8074
|
-
return;
|
|
8075
|
-
}
|
|
8076
|
-
const stripSeconds = (timeStr) => {
|
|
8077
|
-
if (!timeStr) return timeStr;
|
|
8078
|
-
return timeStr.substring(0, 5);
|
|
8079
|
-
};
|
|
8080
|
-
const config = {
|
|
8081
|
-
dayShift: dayShift ? {
|
|
8082
|
-
id: 0,
|
|
8083
|
-
startTime: stripSeconds(dayShift.start_time),
|
|
8084
|
-
endTime: stripSeconds(dayShift.end_time)
|
|
8085
|
-
} : fallbackConfig?.dayShift || { id: 0, startTime: "06:00", endTime: "18:00" },
|
|
8086
|
-
nightShift: nightShift ? {
|
|
8087
|
-
id: 1,
|
|
8088
|
-
startTime: stripSeconds(nightShift.start_time),
|
|
8089
|
-
endTime: stripSeconds(nightShift.end_time)
|
|
8090
|
-
} : fallbackConfig?.nightShift || { id: 1, startTime: "18:00", endTime: "06:00" },
|
|
8091
|
-
transitionPeriodMinutes: fallbackConfig?.transitionPeriodMinutes || 0
|
|
8092
|
-
};
|
|
8093
|
-
console.log(`[useLineShiftConfig] \u2705 Built config from DB:`, config);
|
|
8094
|
-
if (mounted) {
|
|
8095
|
-
setShiftConfig(config);
|
|
8096
|
-
setIsLoading(false);
|
|
8097
|
-
}
|
|
8098
|
-
} catch (err) {
|
|
8099
|
-
console.error("[useShiftConfig] Error fetching shift config:", err);
|
|
8100
|
-
if (mounted) {
|
|
8101
|
-
setError(err instanceof Error ? err.message : "Unknown error occurred");
|
|
8102
|
-
setShiftConfig(fallbackConfig || null);
|
|
8103
|
-
setIsLoading(false);
|
|
8104
|
-
}
|
|
8105
|
-
}
|
|
8106
|
-
};
|
|
8107
|
-
fetchShiftConfig();
|
|
8108
|
-
const subscription = supabase.channel(`shift_config_${lineId}`).on(
|
|
8109
|
-
"postgres_changes",
|
|
8110
|
-
{
|
|
8111
|
-
event: "*",
|
|
8112
|
-
// Listen to all events (INSERT, UPDATE, DELETE)
|
|
8113
|
-
schema: "public",
|
|
8114
|
-
table: "line_operating_hours",
|
|
8115
|
-
filter: `line_id=eq.${lineId}`
|
|
8116
|
-
},
|
|
8117
|
-
(payload) => {
|
|
8118
|
-
console.log("[useShiftConfig] Real-time update received:", payload);
|
|
8119
|
-
fetchShiftConfig();
|
|
8120
|
-
}
|
|
8121
|
-
).subscribe();
|
|
8122
|
-
return () => {
|
|
8123
|
-
mounted = false;
|
|
8124
|
-
subscription.unsubscribe();
|
|
8125
|
-
};
|
|
8126
|
-
}, [lineId, supabase]);
|
|
8127
|
-
return {
|
|
8128
|
-
shiftConfig,
|
|
8129
|
-
isLoading,
|
|
8130
|
-
error
|
|
8131
|
-
};
|
|
8132
|
-
};
|
|
8133
|
-
|
|
8134
|
-
// src/lib/hooks/useDynamicShiftConfig.ts
|
|
8135
|
-
var useDynamicShiftConfig = (lineId) => {
|
|
8136
|
-
const staticShiftConfig = useShiftConfig();
|
|
8137
|
-
const { shiftConfig: dbShiftConfig, isLoading, error } = useLineShiftConfig(lineId, staticShiftConfig);
|
|
8138
|
-
const result = useMemo(() => {
|
|
8139
|
-
console.log(`[useDynamicShiftConfig] \u{1F504} Computing result for lineId: ${lineId}`, {
|
|
8140
|
-
isLoading,
|
|
8141
|
-
hasDbConfig: !!dbShiftConfig,
|
|
8142
|
-
error
|
|
8143
|
-
});
|
|
8144
|
-
if (isLoading) {
|
|
8145
|
-
console.log(`[useDynamicShiftConfig] \u23F3 Still loading, using static config temporarily`);
|
|
8146
|
-
return {
|
|
8147
|
-
shiftConfig: staticShiftConfig,
|
|
8148
|
-
isLoading: true,
|
|
8149
|
-
error: null,
|
|
8150
|
-
isFromDatabase: false
|
|
8151
|
-
};
|
|
8152
|
-
}
|
|
8153
|
-
if (dbShiftConfig) {
|
|
8154
|
-
console.log(`[useDynamicShiftConfig] \u2705 Using DB config:`, dbShiftConfig);
|
|
8155
|
-
return {
|
|
8156
|
-
shiftConfig: dbShiftConfig,
|
|
8157
|
-
isLoading: false,
|
|
8158
|
-
error,
|
|
8159
|
-
isFromDatabase: true
|
|
8160
|
-
};
|
|
8161
|
-
}
|
|
8162
|
-
console.log(`[useDynamicShiftConfig] \u26A0\uFE0F Falling back to static config`);
|
|
8163
|
-
return {
|
|
8164
|
-
shiftConfig: staticShiftConfig,
|
|
8165
|
-
isLoading: false,
|
|
8166
|
-
error,
|
|
8167
|
-
isFromDatabase: false
|
|
8168
|
-
};
|
|
8169
|
-
}, [dbShiftConfig, staticShiftConfig, isLoading, error, lineId]);
|
|
8170
|
-
return result;
|
|
8171
|
-
};
|
|
8172
|
-
|
|
8173
|
-
// src/lib/hooks/useLineKPIs.ts
|
|
8174
|
-
var useLineKPIs = ({ lineId }) => {
|
|
8349
|
+
var useLineKPIs = ({ lineId, enabled }) => {
|
|
8175
8350
|
useDashboardConfig();
|
|
8176
8351
|
const entityConfig = useEntityConfig();
|
|
8177
8352
|
const isFactoryView = lineId === (entityConfig.factoryViewId || "factory");
|
|
@@ -8183,7 +8358,7 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
8183
8358
|
return configuredLineIds.length > 0 ? configuredLineIds[0] : void 0;
|
|
8184
8359
|
}, [entityConfig]);
|
|
8185
8360
|
const lineIdForShiftConfig = isFactoryView ? firstLineId : lineId;
|
|
8186
|
-
const { shiftConfig: dynamicShiftConfig, isFromDatabase } = useDynamicShiftConfig(lineIdForShiftConfig);
|
|
8361
|
+
const { shiftConfig: dynamicShiftConfig, isFromDatabase, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineIdForShiftConfig);
|
|
8187
8362
|
const shiftConfig = dynamicShiftConfig;
|
|
8188
8363
|
console.log(`[useLineKPIs] \u{1F3AF} Shift config for line ${lineId}:`, {
|
|
8189
8364
|
isFactoryView,
|
|
@@ -8204,7 +8379,8 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
8204
8379
|
const updateQueueRef = useRef(false);
|
|
8205
8380
|
const updateTimeoutRef = useRef(null);
|
|
8206
8381
|
const queueUpdateRef = useRef(void 0);
|
|
8207
|
-
const
|
|
8382
|
+
const appTimezone = useAppTimezone();
|
|
8383
|
+
const timezone = appTimezone || dateTimeConfig.defaultTimezone || "UTC";
|
|
8208
8384
|
const schema = databaseConfig.schema ?? "public";
|
|
8209
8385
|
const lineMetricsTable = databaseConfig.tables?.lineMetrics ?? "line_metrics";
|
|
8210
8386
|
const companySpecificMetricsTable = useMemo(
|
|
@@ -8216,14 +8392,14 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
8216
8392
|
}, [lineId]);
|
|
8217
8393
|
const fetchKPIs = useCallback(async () => {
|
|
8218
8394
|
const currentLineId = lineIdRef.current;
|
|
8219
|
-
if (!currentLineId || isFetchingRef.current) {
|
|
8395
|
+
if (!currentLineId || isFetchingRef.current || enabled === false || isShiftConfigLoading) {
|
|
8220
8396
|
return;
|
|
8221
8397
|
}
|
|
8222
8398
|
isFetchingRef.current = true;
|
|
8223
8399
|
setIsLoading(true);
|
|
8224
8400
|
setError(null);
|
|
8225
8401
|
try {
|
|
8226
|
-
const currentShiftDetails = getCurrentShift(
|
|
8402
|
+
const currentShiftDetails = getCurrentShift(timezone, shiftConfig ?? void 0);
|
|
8227
8403
|
const operationalDate = currentShiftDetails.date;
|
|
8228
8404
|
const { data: { session } } = await supabase.auth.getSession();
|
|
8229
8405
|
if (!session?.access_token) {
|
|
@@ -8272,7 +8448,7 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
8272
8448
|
isFetchingRef.current = false;
|
|
8273
8449
|
updateQueueRef.current = false;
|
|
8274
8450
|
}
|
|
8275
|
-
}, [
|
|
8451
|
+
}, [timezone, shiftConfig, entityConfig, supabase, enabled, isShiftConfigLoading]);
|
|
8276
8452
|
const queueUpdate = useCallback(() => {
|
|
8277
8453
|
if (updateTimeoutRef.current) {
|
|
8278
8454
|
clearTimeout(updateTimeoutRef.current);
|
|
@@ -8292,7 +8468,7 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
8292
8468
|
return;
|
|
8293
8469
|
}
|
|
8294
8470
|
fetchKPIs();
|
|
8295
|
-
const currentShiftDetails = getCurrentShift(
|
|
8471
|
+
const currentShiftDetails = getCurrentShift(timezone, shiftConfig ?? void 0);
|
|
8296
8472
|
const operationalDate = currentShiftDetails.date;
|
|
8297
8473
|
const factoryViewIdentifier = entityConfig.factoryViewId || "factory";
|
|
8298
8474
|
const targetLineIds = currentLineId === factoryViewIdentifier ? getConfiguredLineIds(entityConfig) : [currentLineId];
|
|
@@ -8345,7 +8521,7 @@ var useLineKPIs = ({ lineId }) => {
|
|
|
8345
8521
|
clearTimeout(updateTimeoutRef.current);
|
|
8346
8522
|
}
|
|
8347
8523
|
};
|
|
8348
|
-
}, [lineId, supabase, entityConfig, schema, lineMetricsTable, companySpecificMetricsTable,
|
|
8524
|
+
}, [lineId, supabase, entityConfig, schema, lineMetricsTable, companySpecificMetricsTable, timezone, shiftConfig, isShiftConfigLoading]);
|
|
8349
8525
|
return {
|
|
8350
8526
|
kpis,
|
|
8351
8527
|
isLoading,
|
|
@@ -8357,15 +8533,17 @@ var useRealtimeLineMetrics = ({
|
|
|
8357
8533
|
lineId,
|
|
8358
8534
|
date: urlDate,
|
|
8359
8535
|
shiftId: urlShiftId,
|
|
8360
|
-
onMetricsUpdate
|
|
8536
|
+
onMetricsUpdate,
|
|
8537
|
+
enabled
|
|
8361
8538
|
}) => {
|
|
8362
8539
|
const supabase = useSupabase();
|
|
8363
8540
|
const entityConfig = useEntityConfig();
|
|
8364
8541
|
useDatabaseConfig();
|
|
8365
8542
|
const dateTimeConfig = useDateTimeConfig();
|
|
8366
|
-
useShiftConfig();
|
|
8367
|
-
const
|
|
8368
|
-
const shiftConfig =
|
|
8543
|
+
const staticShiftConfig = useShiftConfig();
|
|
8544
|
+
const timezone = useAppTimezone();
|
|
8545
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
8546
|
+
const shiftConfig = dynamicShiftConfig || staticShiftConfig;
|
|
8369
8547
|
const [metrics2, setMetrics] = useState(null);
|
|
8370
8548
|
const [lineDetails, setLineDetails] = useState(null);
|
|
8371
8549
|
const [loading, setLoading] = useState(true);
|
|
@@ -8376,16 +8554,16 @@ var useRealtimeLineMetrics = ({
|
|
|
8376
8554
|
const isFetchingRef = useRef(false);
|
|
8377
8555
|
const channelsRef = useRef([]);
|
|
8378
8556
|
const fetchTimeoutRef = useRef(null);
|
|
8379
|
-
const
|
|
8557
|
+
const effectiveTimezone = timezone || dateTimeConfig.defaultTimezone || "Asia/Kolkata";
|
|
8558
|
+
const currentShift = useMemo(() => getCurrentShift(effectiveTimezone, shiftConfig), [effectiveTimezone, shiftConfig]);
|
|
8380
8559
|
const shiftId = useMemo(
|
|
8381
8560
|
() => urlShiftId !== void 0 ? urlShiftId : currentShift.shiftId,
|
|
8382
8561
|
[urlShiftId, currentShift.shiftId]
|
|
8383
8562
|
);
|
|
8384
|
-
const
|
|
8385
|
-
const date = useMemo(() => urlDate || getOperationalDate(timezone || dateTimeConfig.defaultTimezone || "UTC"), [urlDate, timezone, dateTimeConfig.defaultTimezone]);
|
|
8563
|
+
const date = useMemo(() => urlDate || getOperationalDate(effectiveTimezone), [urlDate, effectiveTimezone]);
|
|
8386
8564
|
const fetchData = useCallback(async () => {
|
|
8387
8565
|
try {
|
|
8388
|
-
if (!lineIdRef.current || isFetchingRef.current) return;
|
|
8566
|
+
if (!lineIdRef.current || isFetchingRef.current || enabled === false) return;
|
|
8389
8567
|
isFetchingRef.current = true;
|
|
8390
8568
|
if (!initialized) {
|
|
8391
8569
|
setLoading(true);
|
|
@@ -8583,7 +8761,7 @@ var useRealtimeLineMetrics = ({
|
|
|
8583
8761
|
updateQueueRef.current = false;
|
|
8584
8762
|
isFetchingRef.current = false;
|
|
8585
8763
|
}
|
|
8586
|
-
}, [supabase, date, shiftId, urlShiftId, onMetricsUpdate, entityConfig, dateTimeConfig.defaultTimezone]);
|
|
8764
|
+
}, [supabase, date, shiftId, urlShiftId, onMetricsUpdate, entityConfig, dateTimeConfig.defaultTimezone, enabled, shiftConfig]);
|
|
8587
8765
|
const queueUpdate = useCallback(() => {
|
|
8588
8766
|
console.log("[useRealtimeLineMetrics] Update queued, debouncing...");
|
|
8589
8767
|
if (fetchTimeoutRef.current) {
|
|
@@ -8665,13 +8843,27 @@ var useRealtimeLineMetrics = ({
|
|
|
8665
8843
|
});
|
|
8666
8844
|
channelsRef.current = [lineMetricsChannel, metricsChannel];
|
|
8667
8845
|
}, [supabase, queueUpdate, urlDate, shiftId, entityConfig, dateTimeConfig.defaultTimezone]);
|
|
8846
|
+
const prevShiftIdRef = useRef(void 0);
|
|
8668
8847
|
useEffect(() => {
|
|
8669
8848
|
if (!lineId) return;
|
|
8670
8849
|
lineIdRef.current = lineId;
|
|
8671
|
-
|
|
8850
|
+
const shouldFetch = !initialized && (!isShiftConfigLoading || enabled === false);
|
|
8851
|
+
const shiftIdChanged = prevShiftIdRef.current !== void 0 && prevShiftIdRef.current !== shiftId && !isShiftConfigLoading;
|
|
8852
|
+
if (shouldFetch || shiftIdChanged) {
|
|
8853
|
+
console.log("[useRealtimeLineMetrics] Fetching data:", {
|
|
8854
|
+
initialized,
|
|
8855
|
+
isShiftConfigLoading,
|
|
8856
|
+
enabled,
|
|
8857
|
+
shiftIdChanged,
|
|
8858
|
+
prevShiftId: prevShiftIdRef.current,
|
|
8859
|
+
currentShiftId: shiftId
|
|
8860
|
+
});
|
|
8672
8861
|
fetchData();
|
|
8673
8862
|
}
|
|
8674
8863
|
setupSubscriptions();
|
|
8864
|
+
if (!isShiftConfigLoading) {
|
|
8865
|
+
prevShiftIdRef.current = shiftId;
|
|
8866
|
+
}
|
|
8675
8867
|
return () => {
|
|
8676
8868
|
if (fetchTimeoutRef.current) {
|
|
8677
8869
|
clearTimeout(fetchTimeoutRef.current);
|
|
@@ -8686,7 +8878,7 @@ var useRealtimeLineMetrics = ({
|
|
|
8686
8878
|
});
|
|
8687
8879
|
}
|
|
8688
8880
|
};
|
|
8689
|
-
}, [lineId, fetchData, setupSubscriptions, initialized, supabase]);
|
|
8881
|
+
}, [lineId, fetchData, setupSubscriptions, initialized, supabase, isShiftConfigLoading, enabled, shiftId]);
|
|
8690
8882
|
useEffect(() => {
|
|
8691
8883
|
setInitialized(false);
|
|
8692
8884
|
}, [lineId, date, shiftId]);
|
|
@@ -9404,14 +9596,20 @@ var useFactoryOverviewMetrics = (date, shiftId) => {
|
|
|
9404
9596
|
const supabase = useSupabase();
|
|
9405
9597
|
const entityConfig = useEntityConfig();
|
|
9406
9598
|
const dateTimeConfig = useDateTimeConfig();
|
|
9407
|
-
const
|
|
9599
|
+
const staticShiftConfig = useShiftConfig();
|
|
9600
|
+
const firstLineId = useMemo(() => {
|
|
9601
|
+
const lineIds = getConfiguredLineIds(entityConfig);
|
|
9602
|
+
return lineIds[0];
|
|
9603
|
+
}, [entityConfig]);
|
|
9604
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(firstLineId);
|
|
9605
|
+
const shiftConfig = dynamicShiftConfig || staticShiftConfig;
|
|
9408
9606
|
const [metrics2, setMetrics] = useState(null);
|
|
9409
9607
|
const [isLoading, setIsLoading] = useState(true);
|
|
9410
9608
|
const [error, setError] = useState(null);
|
|
9411
9609
|
const isFetchingRef = useRef(false);
|
|
9412
9610
|
const defaultTimezone = dateTimeConfig.defaultTimezone || "UTC";
|
|
9413
9611
|
const fetchMetrics = useCallback(async () => {
|
|
9414
|
-
if (!supabase || isFetchingRef.current) return;
|
|
9612
|
+
if (!supabase || isFetchingRef.current || isShiftConfigLoading) return;
|
|
9415
9613
|
try {
|
|
9416
9614
|
isFetchingRef.current = true;
|
|
9417
9615
|
setIsLoading(true);
|
|
@@ -9460,7 +9658,7 @@ var useFactoryOverviewMetrics = (date, shiftId) => {
|
|
|
9460
9658
|
setIsLoading(false);
|
|
9461
9659
|
isFetchingRef.current = false;
|
|
9462
9660
|
}
|
|
9463
|
-
}, [supabase, date, shiftId, entityConfig, defaultTimezone, shiftConfig]);
|
|
9661
|
+
}, [supabase, date, shiftId, entityConfig, defaultTimezone, shiftConfig, isShiftConfigLoading]);
|
|
9464
9662
|
useEffect(() => {
|
|
9465
9663
|
fetchMetrics();
|
|
9466
9664
|
}, [fetchMetrics]);
|
|
@@ -9866,15 +10064,25 @@ var useActiveBreaks = (lineIds) => {
|
|
|
9866
10064
|
}
|
|
9867
10065
|
return { elapsedMinutes, remainingMinutes };
|
|
9868
10066
|
};
|
|
9869
|
-
const
|
|
9870
|
-
const
|
|
9871
|
-
const
|
|
9872
|
-
if (
|
|
9873
|
-
return currentMinutes >=
|
|
10067
|
+
const isTimeInShift = (startTime, endTime, currentMinutes) => {
|
|
10068
|
+
const startMinutes = parseTimeToMinutes2(startTime);
|
|
10069
|
+
const endMinutes = parseTimeToMinutes2(endTime);
|
|
10070
|
+
if (endMinutes < startMinutes) {
|
|
10071
|
+
return currentMinutes >= startMinutes || currentMinutes < endMinutes;
|
|
9874
10072
|
} else {
|
|
9875
|
-
return currentMinutes >=
|
|
10073
|
+
return currentMinutes >= startMinutes && currentMinutes < endMinutes;
|
|
9876
10074
|
}
|
|
9877
10075
|
};
|
|
10076
|
+
const findActiveShift = (shifts, currentMinutes) => {
|
|
10077
|
+
for (const shift of shifts) {
|
|
10078
|
+
const startTime = shift.start_time || "00:00";
|
|
10079
|
+
const endTime = shift.end_time || "00:00";
|
|
10080
|
+
if (isTimeInShift(startTime, endTime, currentMinutes)) {
|
|
10081
|
+
return shift;
|
|
10082
|
+
}
|
|
10083
|
+
}
|
|
10084
|
+
return null;
|
|
10085
|
+
};
|
|
9878
10086
|
const checkActiveBreaks = useCallback(async () => {
|
|
9879
10087
|
try {
|
|
9880
10088
|
setError(null);
|
|
@@ -9888,23 +10096,28 @@ var useActiveBreaks = (lineIds) => {
|
|
|
9888
10096
|
return;
|
|
9889
10097
|
}
|
|
9890
10098
|
const currentMinutes = getCurrentTimeInMinutes();
|
|
9891
|
-
const { data:
|
|
9892
|
-
|
|
9893
|
-
if (dayError || nightError) {
|
|
10099
|
+
const { data: allShifts, error: shiftsError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name, start_time, end_time, breaks").in("line_id", validLineIds).order("shift_id");
|
|
10100
|
+
if (shiftsError) {
|
|
9894
10101
|
throw new Error("Failed to fetch shift configurations");
|
|
9895
10102
|
}
|
|
9896
10103
|
const foundActiveBreaks = [];
|
|
10104
|
+
const shiftsByLine = /* @__PURE__ */ new Map();
|
|
10105
|
+
for (const shift of allShifts || []) {
|
|
10106
|
+
const lineShifts = shiftsByLine.get(shift.line_id) || [];
|
|
10107
|
+
lineShifts.push(shift);
|
|
10108
|
+
shiftsByLine.set(shift.line_id, lineShifts);
|
|
10109
|
+
}
|
|
9897
10110
|
for (const lineId of validLineIds) {
|
|
9898
|
-
const
|
|
9899
|
-
|
|
9900
|
-
|
|
9901
|
-
|
|
9902
|
-
|
|
9903
|
-
|
|
9904
|
-
|
|
9905
|
-
|
|
9906
|
-
|
|
9907
|
-
const shiftName =
|
|
10111
|
+
const lineShifts = shiftsByLine.get(lineId);
|
|
10112
|
+
if (!lineShifts || lineShifts.length === 0) continue;
|
|
10113
|
+
const activeShift = findActiveShift(lineShifts, currentMinutes);
|
|
10114
|
+
if (!activeShift) continue;
|
|
10115
|
+
const getDefaultShiftName = (shiftId) => {
|
|
10116
|
+
if (shiftId === 0) return "Day Shift";
|
|
10117
|
+
if (shiftId === 1) return "Night Shift";
|
|
10118
|
+
return `Shift ${shiftId}`;
|
|
10119
|
+
};
|
|
10120
|
+
const shiftName = activeShift.shift_name || getDefaultShiftName(activeShift.shift_id);
|
|
9908
10121
|
let breaks = [];
|
|
9909
10122
|
if (activeShift.breaks) {
|
|
9910
10123
|
if (Array.isArray(activeShift.breaks)) {
|
|
@@ -9979,8 +10192,12 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
9979
10192
|
const entityConfig = useEntityConfig();
|
|
9980
10193
|
const databaseConfig = useDatabaseConfig();
|
|
9981
10194
|
const dateTimeConfig = useDateTimeConfig();
|
|
9982
|
-
const
|
|
10195
|
+
const staticShiftConfig = useShiftConfig();
|
|
9983
10196
|
const timezone = useAppTimezone();
|
|
10197
|
+
const configuredLineIds = useMemo(() => getConfiguredLineIds(entityConfig), [entityConfig]);
|
|
10198
|
+
const representativeLineId = options?.allowedLineIds?.[0] || configuredLineIds[0];
|
|
10199
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(representativeLineId);
|
|
10200
|
+
const shiftConfig = dynamicShiftConfig || staticShiftConfig;
|
|
9984
10201
|
const supabase = useSupabase();
|
|
9985
10202
|
const [workspaces, setWorkspaces] = useState([]);
|
|
9986
10203
|
const [loading, setLoading] = useState(true);
|
|
@@ -9989,12 +10206,15 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
9989
10206
|
const fetchTimeoutRef = useRef(null);
|
|
9990
10207
|
const isFetchingRef = useRef(false);
|
|
9991
10208
|
const queryShiftId = useMemo(() => {
|
|
10209
|
+
if (options?.initialShiftId !== void 0) {
|
|
10210
|
+
return options.initialShiftId;
|
|
10211
|
+
}
|
|
9992
10212
|
const currentShift = getCurrentShift(
|
|
9993
|
-
dateTimeConfig.defaultTimezone || "Asia/Kolkata",
|
|
10213
|
+
timezone || dateTimeConfig.defaultTimezone || "Asia/Kolkata",
|
|
9994
10214
|
shiftConfig
|
|
9995
10215
|
);
|
|
9996
|
-
return
|
|
9997
|
-
}, [options?.initialShiftId, dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
10216
|
+
return currentShift.shiftId;
|
|
10217
|
+
}, [options?.initialShiftId, timezone, dateTimeConfig.defaultTimezone, shiftConfig]);
|
|
9998
10218
|
const queryDate = useMemo(() => {
|
|
9999
10219
|
return options?.initialDate || getOperationalDate(timezone || dateTimeConfig.defaultTimezone || "UTC");
|
|
10000
10220
|
}, [options?.initialDate, timezone, dateTimeConfig.defaultTimezone]);
|
|
@@ -10006,7 +10226,7 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
10006
10226
|
}, [entityConfig.companyId]);
|
|
10007
10227
|
const schema = databaseConfig.schema ?? "public";
|
|
10008
10228
|
const fetchWorkspaceMetrics = useCallback(async () => {
|
|
10009
|
-
if (isFetchingRef.current) {
|
|
10229
|
+
if (isFetchingRef.current || options?.enabled === false || isShiftConfigLoading) {
|
|
10010
10230
|
return;
|
|
10011
10231
|
}
|
|
10012
10232
|
isFetchingRef.current = true;
|
|
@@ -10016,9 +10236,9 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
10016
10236
|
setError(null);
|
|
10017
10237
|
try {
|
|
10018
10238
|
const allConfiguredLineIds = getConfiguredLineIds(entityConfig);
|
|
10019
|
-
const
|
|
10239
|
+
const configuredLineIds2 = options?.allowedLineIds ? allConfiguredLineIds.filter((id3) => options.allowedLineIds.includes(id3)) : allConfiguredLineIds;
|
|
10020
10240
|
let enabledWorkspaceIds = [];
|
|
10021
|
-
for (const lineId of
|
|
10241
|
+
for (const lineId of configuredLineIds2) {
|
|
10022
10242
|
const workspaces2 = await workspaceService.getWorkspaces(lineId);
|
|
10023
10243
|
const enabledIds = workspaces2.filter((ws) => ws.enable === true).map((ws) => ws.id);
|
|
10024
10244
|
enabledWorkspaceIds.push(...enabledIds);
|
|
@@ -10079,7 +10299,7 @@ var useAllWorkspaceMetrics = (options) => {
|
|
|
10079
10299
|
setLoading(false);
|
|
10080
10300
|
isFetchingRef.current = false;
|
|
10081
10301
|
}
|
|
10082
|
-
}, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId, entityConfig, options?.allowedLineIds]);
|
|
10302
|
+
}, [queryDate, queryShiftId, metricsTable, supabase, entityConfig.companyId, entityConfig, options?.allowedLineIds, options?.enabled, isShiftConfigLoading]);
|
|
10083
10303
|
useEffect(() => {
|
|
10084
10304
|
if (!initialized) {
|
|
10085
10305
|
fetchWorkspaceMetrics();
|
|
@@ -10558,7 +10778,7 @@ function useClipTypes() {
|
|
|
10558
10778
|
refresh: fetchClipTypes
|
|
10559
10779
|
};
|
|
10560
10780
|
}
|
|
10561
|
-
function useClipTypesWithCounts(workspaceId, date, shiftId, totalOutput) {
|
|
10781
|
+
function useClipTypesWithCounts(workspaceId, date, shiftId, totalOutput, options) {
|
|
10562
10782
|
const { clipTypes, isLoading: typesLoading, error: typesError, refresh } = useClipTypes();
|
|
10563
10783
|
const [counts, setCounts] = useState({});
|
|
10564
10784
|
const [countsLoading, setCountsLoading] = useState(false);
|
|
@@ -10570,8 +10790,13 @@ function useClipTypesWithCounts(workspaceId, date, shiftId, totalOutput) {
|
|
|
10570
10790
|
workspaceId,
|
|
10571
10791
|
date,
|
|
10572
10792
|
shiftId,
|
|
10573
|
-
shiftIdType: typeof shiftId
|
|
10793
|
+
shiftIdType: typeof shiftId,
|
|
10794
|
+
enabled: options?.enabled
|
|
10574
10795
|
});
|
|
10796
|
+
if (!options?.enabled) {
|
|
10797
|
+
console.log("[useClipTypesWithCounts] Skipping counts fetch - disabled");
|
|
10798
|
+
return;
|
|
10799
|
+
}
|
|
10575
10800
|
if (!s3Service || !workspaceId || !date || shiftId === void 0) {
|
|
10576
10801
|
console.log("[useClipTypesWithCounts] Skipping counts fetch - missing dependencies");
|
|
10577
10802
|
return;
|
|
@@ -10595,7 +10820,7 @@ function useClipTypesWithCounts(workspaceId, date, shiftId, totalOutput) {
|
|
|
10595
10820
|
}
|
|
10596
10821
|
};
|
|
10597
10822
|
fetchCounts();
|
|
10598
|
-
}, [s3Service, workspaceId, date, shiftId, totalOutput]);
|
|
10823
|
+
}, [s3Service, workspaceId, date, shiftId, totalOutput, options?.enabled]);
|
|
10599
10824
|
return {
|
|
10600
10825
|
clipTypes: clipTypes.map((type) => ({
|
|
10601
10826
|
...type,
|
|
@@ -11005,15 +11230,48 @@ var useWorkspaceUptimeTimeline = (options) => {
|
|
|
11005
11230
|
workspaceId,
|
|
11006
11231
|
companyId,
|
|
11007
11232
|
enabled = true,
|
|
11008
|
-
refreshInterval
|
|
11233
|
+
refreshInterval,
|
|
11234
|
+
lineId,
|
|
11235
|
+
shiftConfig: passedShiftConfig,
|
|
11236
|
+
timezone: passedTimezone
|
|
11009
11237
|
} = options;
|
|
11238
|
+
const { shiftConfig: dynamicShiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
11239
|
+
const appTimezone = useAppTimezone();
|
|
11240
|
+
const shiftConfigPending = !passedShiftConfig && (!lineId || isShiftConfigLoading || !dynamicShiftConfig);
|
|
11241
|
+
const effectiveShiftConfig = passedShiftConfig ?? (shiftConfigPending ? void 0 : dynamicShiftConfig);
|
|
11242
|
+
const effectiveTimezone = passedTimezone || appTimezone || effectiveShiftConfig?.timezone || "UTC";
|
|
11243
|
+
if (process.env.NODE_ENV === "development") {
|
|
11244
|
+
console.log(`[useWorkspaceUptimeTimeline] Shift config state:`, {
|
|
11245
|
+
lineId,
|
|
11246
|
+
hasPassedConfig: !!passedShiftConfig,
|
|
11247
|
+
isShiftConfigLoading,
|
|
11248
|
+
hasDynamicConfig: !!dynamicShiftConfig,
|
|
11249
|
+
shiftConfigPending,
|
|
11250
|
+
hasEffectiveConfig: !!effectiveShiftConfig
|
|
11251
|
+
});
|
|
11252
|
+
}
|
|
11010
11253
|
const [timeline, setTimeline] = useState(null);
|
|
11011
11254
|
const [loading, setLoading] = useState(false);
|
|
11012
11255
|
const [error, setError] = useState(null);
|
|
11013
11256
|
const isFetchingRef = useRef(false);
|
|
11014
11257
|
const intervalRef = useRef(null);
|
|
11258
|
+
useEffect(() => {
|
|
11259
|
+
setTimeline(null);
|
|
11260
|
+
setError(null);
|
|
11261
|
+
setLoading(enabled && Boolean(workspaceId && companyId));
|
|
11262
|
+
}, [workspaceId, companyId, lineId, enabled]);
|
|
11015
11263
|
const fetchTimeline = useCallback(async () => {
|
|
11016
11264
|
if (!enabled) return;
|
|
11265
|
+
if (shiftConfigPending) {
|
|
11266
|
+
console.log("[useWorkspaceUptimeTimeline] \u23F3 Waiting for shift config to load before fetching");
|
|
11267
|
+
setLoading(true);
|
|
11268
|
+
return;
|
|
11269
|
+
}
|
|
11270
|
+
if (!effectiveShiftConfig) {
|
|
11271
|
+
console.warn("[useWorkspaceUptimeTimeline] \u26A0\uFE0F No effective shift config available, cannot fetch");
|
|
11272
|
+
setLoading(false);
|
|
11273
|
+
return;
|
|
11274
|
+
}
|
|
11017
11275
|
if (!workspaceId || !companyId) {
|
|
11018
11276
|
setTimeline(null);
|
|
11019
11277
|
return;
|
|
@@ -11023,9 +11281,16 @@ var useWorkspaceUptimeTimeline = (options) => {
|
|
|
11023
11281
|
isFetchingRef.current = true;
|
|
11024
11282
|
setLoading(true);
|
|
11025
11283
|
setError(null);
|
|
11284
|
+
console.log("[useWorkspaceUptimeTimeline] \u{1F680} Fetching timeline with shift config:", {
|
|
11285
|
+
workspaceId,
|
|
11286
|
+
shiftId: effectiveShiftConfig?.shifts?.[0]?.shiftId,
|
|
11287
|
+
timezone: effectiveTimezone
|
|
11288
|
+
});
|
|
11026
11289
|
const data = await workspaceHealthService.getWorkspaceUptimeTimeline(
|
|
11027
11290
|
workspaceId,
|
|
11028
|
-
companyId
|
|
11291
|
+
companyId,
|
|
11292
|
+
effectiveShiftConfig,
|
|
11293
|
+
effectiveTimezone
|
|
11029
11294
|
);
|
|
11030
11295
|
setTimeline(data);
|
|
11031
11296
|
} catch (err) {
|
|
@@ -11035,7 +11300,7 @@ var useWorkspaceUptimeTimeline = (options) => {
|
|
|
11035
11300
|
setLoading(false);
|
|
11036
11301
|
isFetchingRef.current = false;
|
|
11037
11302
|
}
|
|
11038
|
-
}, [enabled, workspaceId, companyId]);
|
|
11303
|
+
}, [enabled, workspaceId, companyId, effectiveShiftConfig, effectiveTimezone, shiftConfigPending]);
|
|
11039
11304
|
useEffect(() => {
|
|
11040
11305
|
fetchTimeline();
|
|
11041
11306
|
}, [fetchTimeline]);
|
|
@@ -11054,7 +11319,7 @@ var useWorkspaceUptimeTimeline = (options) => {
|
|
|
11054
11319
|
}, [refreshInterval, enabled, fetchTimeline]);
|
|
11055
11320
|
return {
|
|
11056
11321
|
timeline,
|
|
11057
|
-
loading,
|
|
11322
|
+
loading: loading || shiftConfigPending,
|
|
11058
11323
|
error,
|
|
11059
11324
|
refetch: fetchTimeline
|
|
11060
11325
|
};
|
|
@@ -26325,26 +26590,62 @@ var VideoControls = ({
|
|
|
26325
26590
|
const [isHoveringProgressBar, setIsHoveringProgressBar] = useState(false);
|
|
26326
26591
|
const [showSpeedMenu, setShowSpeedMenu] = useState(false);
|
|
26327
26592
|
const speedMenuRef = useRef(null);
|
|
26593
|
+
const progressTrackRef = useRef(null);
|
|
26594
|
+
const activePointerIdRef = useRef(null);
|
|
26328
26595
|
const progressColor = "#4b5563";
|
|
26329
26596
|
const controlsVisible = showControls || controlsPinned;
|
|
26597
|
+
const isDraggingRef = useRef(false);
|
|
26330
26598
|
const getPercentage = (current, total) => {
|
|
26331
26599
|
if (!total || total === 0) return 0;
|
|
26332
26600
|
return Math.min(Math.max(current / total * 100, 0), 100);
|
|
26333
26601
|
};
|
|
26334
26602
|
const handleSeekChange = (e) => {
|
|
26335
|
-
const newTime = parseFloat(e.
|
|
26603
|
+
const newTime = parseFloat(e.currentTarget.value);
|
|
26336
26604
|
setDragTime(newTime);
|
|
26337
26605
|
onSeek(newTime);
|
|
26338
26606
|
};
|
|
26339
26607
|
const handleSeekStart = () => {
|
|
26340
26608
|
setIsDragging(true);
|
|
26609
|
+
isDraggingRef.current = true;
|
|
26341
26610
|
setDragTime(currentTime);
|
|
26342
26611
|
onSeekStart?.();
|
|
26343
26612
|
};
|
|
26344
26613
|
const handleSeekEnd = () => {
|
|
26345
26614
|
setIsDragging(false);
|
|
26615
|
+
isDraggingRef.current = false;
|
|
26346
26616
|
onSeekEnd?.();
|
|
26347
26617
|
};
|
|
26618
|
+
const updateTimeFromClientX = useCallback((clientX) => {
|
|
26619
|
+
if (!progressTrackRef.current) return;
|
|
26620
|
+
const rect = progressTrackRef.current.getBoundingClientRect();
|
|
26621
|
+
if (rect.width === 0 || duration === 0) return;
|
|
26622
|
+
const pct = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);
|
|
26623
|
+
const newTime = pct * duration;
|
|
26624
|
+
setDragTime(newTime);
|
|
26625
|
+
onSeek(newTime);
|
|
26626
|
+
}, [duration, onSeek]);
|
|
26627
|
+
const handlePointerDown = useCallback((e) => {
|
|
26628
|
+
if (duration === 0) return;
|
|
26629
|
+
e.preventDefault();
|
|
26630
|
+
activePointerIdRef.current = e.pointerId;
|
|
26631
|
+
handleSeekStart();
|
|
26632
|
+
updateTimeFromClientX(e.clientX);
|
|
26633
|
+
const handleMove = (ev) => {
|
|
26634
|
+
if (ev.pointerId !== activePointerIdRef.current) return;
|
|
26635
|
+
updateTimeFromClientX(ev.clientX);
|
|
26636
|
+
};
|
|
26637
|
+
const handleUp = (ev) => {
|
|
26638
|
+
if (ev.pointerId !== activePointerIdRef.current) return;
|
|
26639
|
+
activePointerIdRef.current = null;
|
|
26640
|
+
window.removeEventListener("pointermove", handleMove);
|
|
26641
|
+
window.removeEventListener("pointerup", handleUp);
|
|
26642
|
+
window.removeEventListener("pointercancel", handleUp);
|
|
26643
|
+
handleSeekEnd();
|
|
26644
|
+
};
|
|
26645
|
+
window.addEventListener("pointermove", handleMove);
|
|
26646
|
+
window.addEventListener("pointerup", handleUp);
|
|
26647
|
+
window.addEventListener("pointercancel", handleUp);
|
|
26648
|
+
}, [duration, handleSeekStart, handleSeekEnd, updateTimeFromClientX]);
|
|
26348
26649
|
useEffect(() => {
|
|
26349
26650
|
const handleClickOutside = (event) => {
|
|
26350
26651
|
if (speedMenuRef.current && !speedMenuRef.current.contains(event.target)) {
|
|
@@ -26356,6 +26657,21 @@ var VideoControls = ({
|
|
|
26356
26657
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
26357
26658
|
};
|
|
26358
26659
|
}, []);
|
|
26660
|
+
useEffect(() => {
|
|
26661
|
+
const cancelDrag = () => {
|
|
26662
|
+
if (isDraggingRef.current) {
|
|
26663
|
+
handleSeekEnd();
|
|
26664
|
+
}
|
|
26665
|
+
};
|
|
26666
|
+
window.addEventListener("mouseup", cancelDrag);
|
|
26667
|
+
window.addEventListener("touchend", cancelDrag);
|
|
26668
|
+
window.addEventListener("touchcancel", cancelDrag);
|
|
26669
|
+
return () => {
|
|
26670
|
+
window.removeEventListener("mouseup", cancelDrag);
|
|
26671
|
+
window.removeEventListener("touchend", cancelDrag);
|
|
26672
|
+
window.removeEventListener("touchcancel", cancelDrag);
|
|
26673
|
+
};
|
|
26674
|
+
}, []);
|
|
26359
26675
|
const displayTime = isDragging ? dragTime : currentTime;
|
|
26360
26676
|
const progressPercent = getPercentage(displayTime, duration);
|
|
26361
26677
|
const bufferedPercent = getPercentage(buffered, duration);
|
|
@@ -26368,11 +26684,13 @@ var VideoControls = ({
|
|
|
26368
26684
|
/* @__PURE__ */ jsxs(
|
|
26369
26685
|
"div",
|
|
26370
26686
|
{
|
|
26687
|
+
ref: progressTrackRef,
|
|
26371
26688
|
className: "relative h-1 mb-4 group cursor-pointer",
|
|
26372
26689
|
onMouseEnter: () => setIsHoveringProgressBar(true),
|
|
26373
26690
|
onMouseLeave: () => setIsHoveringProgressBar(false),
|
|
26691
|
+
onPointerDown: handlePointerDown,
|
|
26374
26692
|
children: [
|
|
26375
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -top-
|
|
26693
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -top-4 -bottom-4 left-0 right-0 z-20" }),
|
|
26376
26694
|
/* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 bottom-0 bg-white/20 rounded-full overflow-hidden z-0", children: /* @__PURE__ */ jsx(
|
|
26377
26695
|
"div",
|
|
26378
26696
|
{
|
|
@@ -26403,11 +26721,13 @@ var VideoControls = ({
|
|
|
26403
26721
|
step: "0.1",
|
|
26404
26722
|
value: displayTime,
|
|
26405
26723
|
onChange: handleSeekChange,
|
|
26724
|
+
onInput: handleSeekChange,
|
|
26406
26725
|
onMouseDown: handleSeekStart,
|
|
26407
26726
|
onMouseUp: handleSeekEnd,
|
|
26408
26727
|
onTouchStart: handleSeekStart,
|
|
26409
26728
|
onTouchEnd: handleSeekEnd,
|
|
26410
|
-
|
|
26729
|
+
onPointerDown: handlePointerDown,
|
|
26730
|
+
className: "absolute left-0 right-0 top-[-12px] bottom-[-12px] w-full h-auto opacity-0 cursor-pointer z-30 margin-0 padding-0"
|
|
26411
26731
|
}
|
|
26412
26732
|
)
|
|
26413
26733
|
]
|
|
@@ -26630,6 +26950,7 @@ var HlsVideoPlayer = forwardRef(({
|
|
|
26630
26950
|
const [buffered, setBuffered] = useState(0);
|
|
26631
26951
|
const [playbackRate, setPlaybackRate] = useState(1);
|
|
26632
26952
|
const userSeekingRef = useRef(false);
|
|
26953
|
+
const wasPlayingRef = useRef(false);
|
|
26633
26954
|
const controlsTimeoutRef = useRef(null);
|
|
26634
26955
|
const eventCallbacksRef = useRef({
|
|
26635
26956
|
onReady,
|
|
@@ -26872,10 +27193,6 @@ var HlsVideoPlayer = forwardRef(({
|
|
|
26872
27193
|
eventCallbacksRef.current.onPlay?.(player);
|
|
26873
27194
|
};
|
|
26874
27195
|
const handlePause = () => {
|
|
26875
|
-
if (userSeekingRef.current && videoRef.current) {
|
|
26876
|
-
videoRef.current.play().catch((err) => console.warn("Auto-resume after seek pause failed:", err));
|
|
26877
|
-
return;
|
|
26878
|
-
}
|
|
26879
27196
|
setIsPlaying(false);
|
|
26880
27197
|
eventCallbacksRef.current.onPause?.(player);
|
|
26881
27198
|
};
|
|
@@ -27089,14 +27406,17 @@ var HlsVideoPlayer = forwardRef(({
|
|
|
27089
27406
|
const handleSeek = useCallback((time2) => {
|
|
27090
27407
|
if (videoRef.current) {
|
|
27091
27408
|
videoRef.current.currentTime = time2;
|
|
27092
|
-
videoRef.current.play().catch((err) => console.warn("Resume playback failed during seek:", err));
|
|
27093
27409
|
}
|
|
27094
27410
|
}, []);
|
|
27095
27411
|
const handleSeekStart = useCallback(() => {
|
|
27412
|
+
wasPlayingRef.current = !videoRef.current?.paused;
|
|
27413
|
+
if (videoRef.current && !videoRef.current.paused) {
|
|
27414
|
+
videoRef.current.pause();
|
|
27415
|
+
}
|
|
27096
27416
|
userSeekingRef.current = true;
|
|
27097
27417
|
}, []);
|
|
27098
27418
|
const handleSeekEnd = useCallback(() => {
|
|
27099
|
-
if (videoRef.current) {
|
|
27419
|
+
if (videoRef.current && wasPlayingRef.current) {
|
|
27100
27420
|
videoRef.current.play().catch((err) => console.warn("Resume playback failed after seek:", err));
|
|
27101
27421
|
}
|
|
27102
27422
|
}, []);
|
|
@@ -27238,6 +27558,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
27238
27558
|
const [playbackRate, setPlaybackRate] = useState(1);
|
|
27239
27559
|
const controlsTimeoutRef = useRef(null);
|
|
27240
27560
|
const userSeekingRef = useRef(false);
|
|
27561
|
+
const wasPlayingRef = useRef(false);
|
|
27241
27562
|
const [controlsPinned, setControlsPinned] = useState(false);
|
|
27242
27563
|
const stopCanvasRendering = useCallback(() => {
|
|
27243
27564
|
if (animationFrameRef.current) {
|
|
@@ -27377,7 +27698,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
27377
27698
|
}, [crop, renderFrameToCanvas, onPlayProp]);
|
|
27378
27699
|
const handleVideoPause = useCallback((player) => {
|
|
27379
27700
|
console.log("[CroppedHlsVideoPlayer] Video paused, stopping canvas rendering (keeping last frame)");
|
|
27380
|
-
if (userSeekingRef.current && hiddenVideoRef.current) {
|
|
27701
|
+
if (userSeekingRef.current && wasPlayingRef.current && hiddenVideoRef.current) {
|
|
27381
27702
|
hiddenVideoRef.current.play()?.catch(() => {
|
|
27382
27703
|
});
|
|
27383
27704
|
return;
|
|
@@ -27394,6 +27715,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
27394
27715
|
setIsProcessing(false);
|
|
27395
27716
|
setIsPlaying(false);
|
|
27396
27717
|
userSeekingRef.current = false;
|
|
27718
|
+
wasPlayingRef.current = false;
|
|
27397
27719
|
onEndedProp?.(player);
|
|
27398
27720
|
}, [stopCanvasRendering, onEndedProp]);
|
|
27399
27721
|
const handleSeeking = useCallback((player) => {
|
|
@@ -27409,6 +27731,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
27409
27731
|
hiddenVideoRef.current?.play()?.catch(() => {
|
|
27410
27732
|
});
|
|
27411
27733
|
userSeekingRef.current = false;
|
|
27734
|
+
wasPlayingRef.current = false;
|
|
27412
27735
|
if (crop) {
|
|
27413
27736
|
renderFrameToCanvas();
|
|
27414
27737
|
}
|
|
@@ -27505,20 +27828,34 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
27505
27828
|
const handleSeek = useCallback((time2) => {
|
|
27506
27829
|
if (hiddenVideoRef.current) {
|
|
27507
27830
|
hiddenVideoRef.current.currentTime(time2);
|
|
27508
|
-
hiddenVideoRef.current.play()?.catch(() => {
|
|
27509
|
-
});
|
|
27510
27831
|
setTimeout(() => renderFrameToCanvas(), 50);
|
|
27832
|
+
userSeekingRef.current = true;
|
|
27511
27833
|
}
|
|
27512
27834
|
}, [renderFrameToCanvas]);
|
|
27513
27835
|
const handleSeekStart = useCallback(() => {
|
|
27836
|
+
const videoPaused = hiddenVideoRef.current?.video?.paused ?? hiddenVideoRef.current?.paused();
|
|
27837
|
+
wasPlayingRef.current = videoPaused === false;
|
|
27838
|
+
if (hiddenVideoRef.current && videoPaused === false) {
|
|
27839
|
+
hiddenVideoRef.current.pause();
|
|
27840
|
+
}
|
|
27514
27841
|
userSeekingRef.current = true;
|
|
27515
27842
|
}, []);
|
|
27516
27843
|
const handleSeekEnd = useCallback(() => {
|
|
27517
|
-
|
|
27518
|
-
|
|
27844
|
+
const shouldResume = wasPlayingRef.current;
|
|
27845
|
+
userSeekingRef.current = shouldResume;
|
|
27846
|
+
if (hiddenVideoRef.current && shouldResume) {
|
|
27847
|
+
hiddenVideoRef.current.play()?.then(() => {
|
|
27848
|
+
if (crop) {
|
|
27849
|
+
setIsProcessing(true);
|
|
27850
|
+
renderFrameToCanvas();
|
|
27851
|
+
}
|
|
27852
|
+
}).catch(() => {
|
|
27519
27853
|
});
|
|
27520
27854
|
}
|
|
27521
|
-
|
|
27855
|
+
if (!shouldResume) {
|
|
27856
|
+
userSeekingRef.current = false;
|
|
27857
|
+
}
|
|
27858
|
+
}, [crop, renderFrameToCanvas]);
|
|
27522
27859
|
const handlePlaybackRateChange = useCallback((rate) => {
|
|
27523
27860
|
if (hiddenVideoRef.current) {
|
|
27524
27861
|
hiddenVideoRef.current.playbackRate(rate);
|
|
@@ -29809,6 +30146,7 @@ var BottlenecksContent = ({
|
|
|
29809
30146
|
workspaceId,
|
|
29810
30147
|
workspaceName,
|
|
29811
30148
|
date,
|
|
30149
|
+
lineId,
|
|
29812
30150
|
shift,
|
|
29813
30151
|
className,
|
|
29814
30152
|
totalOutput,
|
|
@@ -29819,27 +30157,36 @@ var BottlenecksContent = ({
|
|
|
29819
30157
|
console.log("\u{1F3AB} [BottlenecksContent] Rendered with ticketId:", ticketId || "NONE", "workspaceId:", workspaceId, "date:", date, "shift:", shift);
|
|
29820
30158
|
const dashboardConfig = useDashboardConfig();
|
|
29821
30159
|
const timezone = useAppTimezone();
|
|
29822
|
-
const { shiftConfig } = useDynamicShiftConfig(
|
|
29823
|
-
const effectiveShift = useMemo(() => {
|
|
29824
|
-
if (shift !== void 0 && shift !== null) {
|
|
30160
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
30161
|
+
const { effectiveShift, effectiveDate } = useMemo(() => {
|
|
30162
|
+
if (shift !== void 0 && shift !== null && date) {
|
|
29825
30163
|
const shiftStr = shift.toString();
|
|
29826
|
-
console.log(`[BottlenecksContent] Using
|
|
29827
|
-
return shiftStr;
|
|
30164
|
+
console.log(`[BottlenecksContent] Using explicit date/shift: ${date}, shift ${shiftStr}`);
|
|
30165
|
+
return { effectiveShift: shiftStr, effectiveDate: date };
|
|
29828
30166
|
}
|
|
29829
|
-
if (
|
|
29830
|
-
console.log(
|
|
29831
|
-
return
|
|
29832
|
-
}
|
|
29833
|
-
|
|
29834
|
-
|
|
29835
|
-
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
);
|
|
29839
|
-
|
|
29840
|
-
|
|
30167
|
+
if ((shift === void 0 || shift === null) && isShiftConfigLoading) {
|
|
30168
|
+
console.log("[BottlenecksContent] Waiting for shift config before determining effective date/shift");
|
|
30169
|
+
return { effectiveShift: null, effectiveDate: null };
|
|
30170
|
+
}
|
|
30171
|
+
const currentShift = getCurrentShift(
|
|
30172
|
+
timezone,
|
|
30173
|
+
shiftConfig
|
|
30174
|
+
);
|
|
30175
|
+
if (shift !== void 0 && shift !== null) {
|
|
30176
|
+
const shiftStr = shift.toString();
|
|
30177
|
+
return {
|
|
30178
|
+
effectiveShift: shiftStr,
|
|
30179
|
+
effectiveDate: date || currentShift.date
|
|
30180
|
+
};
|
|
29841
30181
|
}
|
|
29842
|
-
|
|
30182
|
+
return {
|
|
30183
|
+
effectiveShift: currentShift.shiftId.toString(),
|
|
30184
|
+
effectiveDate: date || currentShift.date
|
|
30185
|
+
};
|
|
30186
|
+
}, [shift, date, timezone, shiftConfig, isShiftConfigLoading]);
|
|
30187
|
+
const isEffectiveShiftReady = Boolean(effectiveShift && effectiveDate);
|
|
30188
|
+
const effectiveDateString = effectiveDate || "";
|
|
30189
|
+
const effectiveShiftId = effectiveShift ?? "";
|
|
29843
30190
|
const { crop: workspaceCrop} = useWorkspaceCrop(workspaceId);
|
|
29844
30191
|
const { metrics: workspaceMetrics } = useWorkspaceDetailedMetrics(
|
|
29845
30192
|
workspaceId,
|
|
@@ -29925,9 +30272,9 @@ var BottlenecksContent = ({
|
|
|
29925
30272
|
clearNotification
|
|
29926
30273
|
} = useClipsRealtimeUpdates({
|
|
29927
30274
|
workspaceId,
|
|
29928
|
-
date:
|
|
29929
|
-
shiftId:
|
|
29930
|
-
enabled:
|
|
30275
|
+
date: effectiveDateString,
|
|
30276
|
+
shiftId: effectiveShiftId,
|
|
30277
|
+
enabled: isEffectiveShiftReady,
|
|
29931
30278
|
// Supabase implementation
|
|
29932
30279
|
onNewClips: (notification) => {
|
|
29933
30280
|
console.log(`[BottlenecksContent] New clips detected:`, notification);
|
|
@@ -29968,10 +30315,11 @@ var BottlenecksContent = ({
|
|
|
29968
30315
|
counts: dynamicCounts
|
|
29969
30316
|
} = useClipTypesWithCounts(
|
|
29970
30317
|
workspaceId,
|
|
29971
|
-
|
|
29972
|
-
|
|
30318
|
+
effectiveDateString,
|
|
30319
|
+
effectiveShiftId,
|
|
29973
30320
|
// Use same shift as video loading for consistency
|
|
29974
|
-
totalOutput
|
|
30321
|
+
totalOutput,
|
|
30322
|
+
{ enabled: isEffectiveShiftReady }
|
|
29975
30323
|
);
|
|
29976
30324
|
console.log("[BottlenecksContent] Clip types data:", {
|
|
29977
30325
|
clipTypes,
|
|
@@ -29980,8 +30328,8 @@ var BottlenecksContent = ({
|
|
|
29980
30328
|
clipTypesError,
|
|
29981
30329
|
dynamicCounts,
|
|
29982
30330
|
workspaceId,
|
|
29983
|
-
date:
|
|
29984
|
-
shift:
|
|
30331
|
+
date: effectiveDateString,
|
|
30332
|
+
shift: effectiveShiftId || "0"
|
|
29985
30333
|
});
|
|
29986
30334
|
useEffect(() => {
|
|
29987
30335
|
if (clipTypes.length > 0) {
|
|
@@ -30022,16 +30370,16 @@ var BottlenecksContent = ({
|
|
|
30022
30370
|
return { ...clipCounts, ...dynamicCounts };
|
|
30023
30371
|
}, [clipCounts, dynamicCounts]);
|
|
30024
30372
|
const fetchClipCounts = useCallback(async () => {
|
|
30025
|
-
if (!workspaceId || !s3ClipsService || !dashboardConfig?.s3Config || !isMountedRef.current) return;
|
|
30026
|
-
const operationKey = `fetchClipCounts:${workspaceId}:${
|
|
30373
|
+
if (!workspaceId || !s3ClipsService || !dashboardConfig?.s3Config || !isMountedRef.current || !isEffectiveShiftReady) return;
|
|
30374
|
+
const operationKey = `fetchClipCounts:${workspaceId}:${effectiveDateString}:${effectiveShiftId}`;
|
|
30027
30375
|
if (fetchInProgressRef.current.has(operationKey)) {
|
|
30028
30376
|
console.log(`[BottlenecksContent] Fetch clip counts already in progress for ${operationKey}`);
|
|
30029
30377
|
return;
|
|
30030
30378
|
}
|
|
30031
30379
|
fetchInProgressRef.current.add(operationKey);
|
|
30032
30380
|
try {
|
|
30033
|
-
const operationalDate =
|
|
30034
|
-
const shiftStr =
|
|
30381
|
+
const operationalDate = effectiveDateString;
|
|
30382
|
+
const shiftStr = effectiveShiftId;
|
|
30035
30383
|
console.log(`[BottlenecksContent] Fetching clip counts directly with params:`, {
|
|
30036
30384
|
workspaceId,
|
|
30037
30385
|
operationalDate,
|
|
@@ -30066,12 +30414,12 @@ var BottlenecksContent = ({
|
|
|
30066
30414
|
} finally {
|
|
30067
30415
|
fetchInProgressRef.current.delete(operationKey);
|
|
30068
30416
|
}
|
|
30069
|
-
}, [workspaceId,
|
|
30417
|
+
}, [workspaceId, effectiveDateString, s3ClipsService, effectiveShiftId, dashboardConfig, updateClipCounts, isEffectiveShiftReady, totalOutput]);
|
|
30070
30418
|
const loadingCategoryRef = useRef(null);
|
|
30071
30419
|
const loadFirstVideoForCategory = useCallback(async (category) => {
|
|
30072
|
-
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
30420
|
+
if (!workspaceId || !s3ClipsService || !isMountedRef.current || !isEffectiveShiftReady) return;
|
|
30073
30421
|
const targetCategory = category || activeFilterRef.current;
|
|
30074
|
-
const operationKey = `loadFirstVideo:${targetCategory}`;
|
|
30422
|
+
const operationKey = `loadFirstVideo:${targetCategory}:${effectiveDateString}:${effectiveShiftId}`;
|
|
30075
30423
|
if (loadingCategoryRef.current === targetCategory || fetchInProgressRef.current.has(operationKey)) {
|
|
30076
30424
|
console.log(`[BottlenecksContent] Load first video already in progress for ${targetCategory}`);
|
|
30077
30425
|
return;
|
|
@@ -30082,8 +30430,8 @@ var BottlenecksContent = ({
|
|
|
30082
30430
|
setError(null);
|
|
30083
30431
|
}
|
|
30084
30432
|
try {
|
|
30085
|
-
const operationalDate =
|
|
30086
|
-
const shiftStr =
|
|
30433
|
+
const operationalDate = effectiveDateString;
|
|
30434
|
+
const shiftStr = effectiveShiftId;
|
|
30087
30435
|
console.log(`[BottlenecksContent] Loading first video for category: ${targetCategory}`);
|
|
30088
30436
|
try {
|
|
30089
30437
|
const firstVideo = await s3ClipsService.getFirstClipForCategory(
|
|
@@ -30156,7 +30504,7 @@ var BottlenecksContent = ({
|
|
|
30156
30504
|
loadingCategoryRef.current = null;
|
|
30157
30505
|
fetchInProgressRef.current.delete(operationKey);
|
|
30158
30506
|
}
|
|
30159
|
-
}, [workspaceId,
|
|
30507
|
+
}, [workspaceId, effectiveDateString, s3ClipsService, mergedCounts, effectiveShiftId, isEffectiveShiftReady]);
|
|
30160
30508
|
const handleRefreshClips = useCallback(async () => {
|
|
30161
30509
|
console.log("[BottlenecksContent] Refreshing clips after new additions");
|
|
30162
30510
|
acknowledgeNewClips();
|
|
@@ -30167,10 +30515,10 @@ var BottlenecksContent = ({
|
|
|
30167
30515
|
}
|
|
30168
30516
|
}, [acknowledgeNewClips, fetchClipCounts, activeFilter, mergedCounts, loadFirstVideoForCategory, invalidateMetadataCache]);
|
|
30169
30517
|
useEffect(() => {
|
|
30170
|
-
if (s3ClipsService) {
|
|
30518
|
+
if (s3ClipsService && isEffectiveShiftReady) {
|
|
30171
30519
|
fetchClipCounts();
|
|
30172
30520
|
}
|
|
30173
|
-
}, [workspaceId,
|
|
30521
|
+
}, [workspaceId, effectiveDateString, effectiveShiftId, s3ClipsService, fetchClipCounts, isEffectiveShiftReady]);
|
|
30174
30522
|
const getAuthToken4 = useCallback(async () => {
|
|
30175
30523
|
try {
|
|
30176
30524
|
const { createClient: createClient5 } = await import('@supabase/supabase-js');
|
|
@@ -30186,7 +30534,7 @@ var BottlenecksContent = ({
|
|
|
30186
30534
|
}
|
|
30187
30535
|
}, []);
|
|
30188
30536
|
useEffect(() => {
|
|
30189
|
-
if (!triageMode || !workspaceId) return;
|
|
30537
|
+
if (!triageMode || !workspaceId || !isEffectiveShiftReady) return;
|
|
30190
30538
|
const fetchTriageClips = async () => {
|
|
30191
30539
|
setIsLoadingTriageClips(true);
|
|
30192
30540
|
try {
|
|
@@ -30205,8 +30553,8 @@ var BottlenecksContent = ({
|
|
|
30205
30553
|
body: JSON.stringify({
|
|
30206
30554
|
action: "metadata",
|
|
30207
30555
|
workspaceId,
|
|
30208
|
-
date:
|
|
30209
|
-
shift:
|
|
30556
|
+
date: effectiveDateString,
|
|
30557
|
+
shift: effectiveShiftId,
|
|
30210
30558
|
category: categoryId,
|
|
30211
30559
|
page: 1,
|
|
30212
30560
|
limit: 100
|
|
@@ -30238,7 +30586,7 @@ var BottlenecksContent = ({
|
|
|
30238
30586
|
}
|
|
30239
30587
|
};
|
|
30240
30588
|
fetchTriageClips();
|
|
30241
|
-
}, [triageMode, workspaceId,
|
|
30589
|
+
}, [triageMode, workspaceId, effectiveDateString, effectiveShiftId, getAuthToken4, isEffectiveShiftReady]);
|
|
30242
30590
|
useEffect(() => {
|
|
30243
30591
|
if (s3ClipsService && (mergedCounts[activeFilter] || 0) > 0) {
|
|
30244
30592
|
const hasVideosForCurrentFilter = allVideos.some((video) => {
|
|
@@ -30339,8 +30687,12 @@ var BottlenecksContent = ({
|
|
|
30339
30687
|
if (!workspaceId) {
|
|
30340
30688
|
return;
|
|
30341
30689
|
}
|
|
30342
|
-
|
|
30343
|
-
|
|
30690
|
+
if (!isEffectiveShiftReady) {
|
|
30691
|
+
console.log("[BottlenecksContent] Skipping metadata load - shift/date not ready");
|
|
30692
|
+
return;
|
|
30693
|
+
}
|
|
30694
|
+
const resolvedDate = effectiveDateString;
|
|
30695
|
+
const cacheKey = `${categoryId}-${resolvedDate}-${effectiveShiftId}`;
|
|
30344
30696
|
const cachedMetadata = !forceRefresh ? metadataCache[cacheKey] : void 0;
|
|
30345
30697
|
try {
|
|
30346
30698
|
if (cachedMetadata) {
|
|
@@ -30394,7 +30746,7 @@ var BottlenecksContent = ({
|
|
|
30394
30746
|
startDate: `${resolvedDate}T00:00:00Z`,
|
|
30395
30747
|
endDate: `${resolvedDate}T23:59:59Z`,
|
|
30396
30748
|
percentile: 10,
|
|
30397
|
-
shiftId:
|
|
30749
|
+
shiftId: effectiveShiftId,
|
|
30398
30750
|
limit: 100
|
|
30399
30751
|
})
|
|
30400
30752
|
});
|
|
@@ -30409,7 +30761,7 @@ var BottlenecksContent = ({
|
|
|
30409
30761
|
action: "clip-metadata",
|
|
30410
30762
|
workspaceId,
|
|
30411
30763
|
date: resolvedDate,
|
|
30412
|
-
shift:
|
|
30764
|
+
shift: effectiveShiftId,
|
|
30413
30765
|
category: categoryId,
|
|
30414
30766
|
page: 1,
|
|
30415
30767
|
limit: 1e3
|
|
@@ -30468,7 +30820,7 @@ var BottlenecksContent = ({
|
|
|
30468
30820
|
} finally {
|
|
30469
30821
|
setIsCategoryLoading(false);
|
|
30470
30822
|
}
|
|
30471
|
-
}, [workspaceId,
|
|
30823
|
+
}, [workspaceId, effectiveDateString, effectiveShiftId, isPercentileCategory, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady]);
|
|
30472
30824
|
const loadAndPlayClipById = useCallback(async (clipId, categoryId, position) => {
|
|
30473
30825
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
30474
30826
|
console.log(`[BottlenecksContent] Loading clip by ID: ${clipId}, category=${categoryId}, position=${position}`);
|
|
@@ -30533,10 +30885,10 @@ var BottlenecksContent = ({
|
|
|
30533
30885
|
}, [workspaceId, s3ClipsService, updateActiveFilter, clearLoadingState, loadCategoryMetadata]);
|
|
30534
30886
|
useCallback(async (categoryId, clipIndex) => {
|
|
30535
30887
|
console.warn("[BottlenecksContent] loadAndPlayClip is deprecated, use loadAndPlayClipById instead");
|
|
30536
|
-
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
30888
|
+
if (!workspaceId || !s3ClipsService || !isMountedRef.current || !isEffectiveShiftReady) return;
|
|
30537
30889
|
try {
|
|
30538
|
-
const operationalDate =
|
|
30539
|
-
const shiftStr =
|
|
30890
|
+
const operationalDate = effectiveDateString;
|
|
30891
|
+
const shiftStr = effectiveShiftId;
|
|
30540
30892
|
const video = await s3ClipsService.getClipByIndex(
|
|
30541
30893
|
workspaceId,
|
|
30542
30894
|
operationalDate,
|
|
@@ -30557,7 +30909,7 @@ var BottlenecksContent = ({
|
|
|
30557
30909
|
});
|
|
30558
30910
|
setIsNavigating(false);
|
|
30559
30911
|
}
|
|
30560
|
-
}, [workspaceId, s3ClipsService,
|
|
30912
|
+
}, [workspaceId, s3ClipsService, effectiveDateString, effectiveShiftId, loadAndPlayClipById, isEffectiveShiftReady]);
|
|
30561
30913
|
const handleNext = useCallback(async () => {
|
|
30562
30914
|
if (!isMountedRef.current) return;
|
|
30563
30915
|
const currentFilter = activeFilterRef.current;
|
|
@@ -31216,8 +31568,8 @@ var BottlenecksContent = ({
|
|
|
31216
31568
|
currentVideoId: currentVideo?.id,
|
|
31217
31569
|
counts: mergedCounts,
|
|
31218
31570
|
workspaceId,
|
|
31219
|
-
date:
|
|
31220
|
-
shift:
|
|
31571
|
+
date: effectiveDateString,
|
|
31572
|
+
shift: effectiveShiftId,
|
|
31221
31573
|
targetCycleTime: workspaceTargetCycleTime,
|
|
31222
31574
|
onFilterChange: (filterId) => {
|
|
31223
31575
|
updateActiveFilter(filterId);
|
|
@@ -31415,6 +31767,7 @@ var BottleneckClipsModal = ({
|
|
|
31415
31767
|
onClose,
|
|
31416
31768
|
workspaceId,
|
|
31417
31769
|
workspaceName,
|
|
31770
|
+
lineId,
|
|
31418
31771
|
date,
|
|
31419
31772
|
shift,
|
|
31420
31773
|
totalOutput,
|
|
@@ -31539,6 +31892,7 @@ var BottleneckClipsModal = ({
|
|
|
31539
31892
|
{
|
|
31540
31893
|
workspaceId,
|
|
31541
31894
|
workspaceName,
|
|
31895
|
+
lineId,
|
|
31542
31896
|
date,
|
|
31543
31897
|
shift,
|
|
31544
31898
|
totalOutput,
|
|
@@ -32485,7 +32839,7 @@ var EncouragementOverlay = ({
|
|
|
32485
32839
|
};
|
|
32486
32840
|
var ShiftDisplay = memo(({ className, variant = "default", lineId }) => {
|
|
32487
32841
|
const { dateTimeConfig } = useDashboardConfig();
|
|
32488
|
-
const { shiftConfig } = useDynamicShiftConfig(lineId);
|
|
32842
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
32489
32843
|
const getShiftInfo = () => {
|
|
32490
32844
|
const tz = dateTimeConfig?.defaultTimezone;
|
|
32491
32845
|
if (!tz || !shiftConfig || !shiftConfig.dayShift || !shiftConfig.nightShift || !shiftConfig.dayShift.startTime || !shiftConfig.nightShift.startTime) {
|
|
@@ -32513,7 +32867,13 @@ var ShiftDisplay = memo(({ className, variant = "default", lineId }) => {
|
|
|
32513
32867
|
setCurrentShiftText(getShiftInfo());
|
|
32514
32868
|
}, 1e3);
|
|
32515
32869
|
return () => clearInterval(interval);
|
|
32516
|
-
}, [dateTimeConfig?.defaultTimezone, shiftConfig]);
|
|
32870
|
+
}, [dateTimeConfig?.defaultTimezone, shiftConfig, isShiftConfigLoading]);
|
|
32871
|
+
if (isShiftConfigLoading) {
|
|
32872
|
+
return /* @__PURE__ */ jsxs("div", { className: `inline-flex items-center gap-2 bg-gray-100 rounded-lg px-3 py-1.5 ${className ?? ""}`, children: [
|
|
32873
|
+
/* @__PURE__ */ jsx("div", { className: "w-4 h-4 bg-gray-200 rounded animate-pulse" }),
|
|
32874
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-4 bg-gray-200 rounded animate-pulse" })
|
|
32875
|
+
] });
|
|
32876
|
+
}
|
|
32517
32877
|
if (!currentShiftText) {
|
|
32518
32878
|
return null;
|
|
32519
32879
|
}
|
|
@@ -32991,13 +33351,26 @@ var LinePdfExportButton = ({
|
|
|
32991
33351
|
}
|
|
32992
33352
|
);
|
|
32993
33353
|
};
|
|
33354
|
+
var DEFAULT_LINE_SHIFT_DATA = {
|
|
33355
|
+
avg_efficiency: 0,
|
|
33356
|
+
underperforming_workspaces: 0,
|
|
33357
|
+
total_workspaces: 0,
|
|
33358
|
+
hasData: false
|
|
33359
|
+
};
|
|
33360
|
+
var getLineShiftData = (day, shiftId) => {
|
|
33361
|
+
const shift = day.shifts[shiftId];
|
|
33362
|
+
if (shift) {
|
|
33363
|
+
return { ...shift, hasData: true };
|
|
33364
|
+
}
|
|
33365
|
+
return { ...DEFAULT_LINE_SHIFT_DATA };
|
|
33366
|
+
};
|
|
32994
33367
|
var WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
32995
33368
|
var LineHistoryCalendar = ({
|
|
32996
33369
|
data,
|
|
32997
33370
|
month,
|
|
32998
33371
|
year,
|
|
32999
33372
|
lineId,
|
|
33000
|
-
|
|
33373
|
+
selectedShiftId,
|
|
33001
33374
|
onDateSelect,
|
|
33002
33375
|
className = ""
|
|
33003
33376
|
}) => {
|
|
@@ -33033,8 +33406,7 @@ var LineHistoryCalendar = ({
|
|
|
33033
33406
|
} else {
|
|
33034
33407
|
calendar.push({
|
|
33035
33408
|
date: currentDate,
|
|
33036
|
-
|
|
33037
|
-
nightShift: { avg_efficiency: 0, underperforming_workspaces: 0, total_workspaces: 0, hasData: false }
|
|
33409
|
+
shifts: {}
|
|
33038
33410
|
});
|
|
33039
33411
|
}
|
|
33040
33412
|
}
|
|
@@ -33085,8 +33457,7 @@ var LineHistoryCalendar = ({
|
|
|
33085
33457
|
};
|
|
33086
33458
|
const renderDayCell = (day) => {
|
|
33087
33459
|
if (!day) return /* @__PURE__ */ jsx("div", { className: "h-full border border-gray-100 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800" });
|
|
33088
|
-
const shiftData =
|
|
33089
|
-
if (!shiftData) return /* @__PURE__ */ jsx("div", { className: "h-full border border-gray-100 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800" });
|
|
33460
|
+
const shiftData = getLineShiftData(day, selectedShiftId);
|
|
33090
33461
|
const isToday = isCurrentDate(day.date instanceof Date ? day.date : new Date(day.date));
|
|
33091
33462
|
const isFuture = isFutureDate(day.date instanceof Date ? day.date : new Date(day.date));
|
|
33092
33463
|
const hasData = hasRealData(shiftData);
|
|
@@ -33102,21 +33473,20 @@ var LineHistoryCalendar = ({
|
|
|
33102
33473
|
const month2 = String(dateObj2.getMonth() + 1).padStart(2, "0");
|
|
33103
33474
|
const dayOfMonth = String(dateObj2.getDate()).padStart(2, "0");
|
|
33104
33475
|
const date = `${year2}-${month2}-${dayOfMonth}`;
|
|
33105
|
-
const shiftId = selectedShift === "day" ? "0" : "1";
|
|
33106
33476
|
trackCoreEvent("Line Monthly History Day Clicked", {
|
|
33107
33477
|
source: "line_kpi",
|
|
33108
33478
|
line_id: lineId,
|
|
33109
33479
|
date,
|
|
33110
|
-
|
|
33480
|
+
shift_id: selectedShiftId,
|
|
33111
33481
|
efficiency: shiftData.avg_efficiency || 0,
|
|
33112
33482
|
underperforming_workspaces: shiftData.underperforming_workspaces || 0,
|
|
33113
33483
|
total_workspaces: shiftData.total_workspaces || 0
|
|
33114
33484
|
});
|
|
33115
33485
|
const returnTo = `/kpis/${lineId}?tab=monthly_history&month=${month2}&year=${year2}`;
|
|
33116
33486
|
if (onDateSelect) {
|
|
33117
|
-
onDateSelect(date,
|
|
33487
|
+
onDateSelect(date, selectedShiftId);
|
|
33118
33488
|
} else {
|
|
33119
|
-
router.navigate(`/kpis/${lineId}?date=${date}&shift=${
|
|
33489
|
+
router.navigate(`/kpis/${lineId}?date=${date}&shift=${selectedShiftId}&sourceType=lineMonthlyHistory&returnTo=${encodeURIComponent(returnTo)}`);
|
|
33120
33490
|
}
|
|
33121
33491
|
}
|
|
33122
33492
|
},
|
|
@@ -33140,14 +33510,28 @@ var LineHistoryCalendar = ({
|
|
|
33140
33510
|
] });
|
|
33141
33511
|
};
|
|
33142
33512
|
var LineHistoryCalendar_default = LineHistoryCalendar;
|
|
33513
|
+
var DEFAULT_PERFORMANCE_DATA = {
|
|
33514
|
+
avg_efficiency: 0,
|
|
33515
|
+
underperforming_workspaces: 0,
|
|
33516
|
+
total_workspaces: 0,
|
|
33517
|
+
hasData: false
|
|
33518
|
+
};
|
|
33519
|
+
var getShiftData2 = (day, shiftId) => {
|
|
33520
|
+
const shift = day.shifts[shiftId];
|
|
33521
|
+
if (shift) {
|
|
33522
|
+
return { ...shift, hasData: true };
|
|
33523
|
+
}
|
|
33524
|
+
return { ...DEFAULT_PERFORMANCE_DATA };
|
|
33525
|
+
};
|
|
33143
33526
|
var LineMonthlyHistory = ({
|
|
33144
33527
|
month,
|
|
33145
33528
|
year,
|
|
33146
33529
|
monthlyData = [],
|
|
33147
|
-
underperformingWorkspaces = {
|
|
33530
|
+
underperformingWorkspaces = {},
|
|
33148
33531
|
lineId,
|
|
33149
|
-
|
|
33532
|
+
selectedShiftId = 0,
|
|
33150
33533
|
onShiftChange,
|
|
33534
|
+
availableShifts,
|
|
33151
33535
|
onWorkspaceSelect,
|
|
33152
33536
|
onCalendarDateSelect,
|
|
33153
33537
|
onCalendarMonthChange,
|
|
@@ -33156,7 +33540,7 @@ var LineMonthlyHistory = ({
|
|
|
33156
33540
|
const navigation = useNavigation();
|
|
33157
33541
|
const averages = (monthlyData || []).reduce(
|
|
33158
33542
|
(acc, day) => {
|
|
33159
|
-
const shiftData =
|
|
33543
|
+
const shiftData = getShiftData2(day, selectedShiftId);
|
|
33160
33544
|
if (!shiftData || shiftData?.avg_efficiency < 10) {
|
|
33161
33545
|
return acc;
|
|
33162
33546
|
}
|
|
@@ -33230,28 +33614,22 @@ var LineMonthlyHistory = ({
|
|
|
33230
33614
|
line_id: lineId,
|
|
33231
33615
|
workspace_id: workspace.workspace_uuid,
|
|
33232
33616
|
workspace_name: workspace.workspace_name,
|
|
33233
|
-
|
|
33617
|
+
selected_shift_id: selectedShiftId
|
|
33234
33618
|
});
|
|
33235
33619
|
};
|
|
33236
33620
|
return /* @__PURE__ */ jsxs("div", { className: clsx("flex flex-col gap-2 min-h-0 overflow-y-auto pb-6", className), children: [
|
|
33237
|
-
/* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */
|
|
33238
|
-
|
|
33239
|
-
|
|
33240
|
-
|
|
33241
|
-
|
|
33242
|
-
|
|
33243
|
-
|
|
33244
|
-
}
|
|
33245
|
-
|
|
33246
|
-
|
|
33247
|
-
|
|
33248
|
-
|
|
33249
|
-
onClick: () => onShiftChange?.("night"),
|
|
33250
|
-
className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShift === "night" ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
|
|
33251
|
-
children: "Night Shift"
|
|
33252
|
-
}
|
|
33253
|
-
)
|
|
33254
|
-
] }) }),
|
|
33621
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsx("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: (availableShifts && availableShifts.length > 0 ? availableShifts : [
|
|
33622
|
+
{ id: 0, name: "Day Shift" },
|
|
33623
|
+
{ id: 1, name: "Night Shift" }
|
|
33624
|
+
]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsx(
|
|
33625
|
+
"button",
|
|
33626
|
+
{
|
|
33627
|
+
onClick: () => onShiftChange?.(shift.id),
|
|
33628
|
+
className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShiftId === shift.id ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
|
|
33629
|
+
children: shift.name
|
|
33630
|
+
},
|
|
33631
|
+
shift.id
|
|
33632
|
+
)) }) }),
|
|
33255
33633
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6", children: [
|
|
33256
33634
|
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
|
|
33257
33635
|
/* @__PURE__ */ jsxs("h2", { className: "text-lg font-semibold text-gray-700 mb-4 text-center", children: [
|
|
@@ -33266,7 +33644,7 @@ var LineMonthlyHistory = ({
|
|
|
33266
33644
|
month,
|
|
33267
33645
|
year,
|
|
33268
33646
|
lineId,
|
|
33269
|
-
|
|
33647
|
+
selectedShiftId,
|
|
33270
33648
|
onDateSelect: onCalendarDateSelect
|
|
33271
33649
|
}
|
|
33272
33650
|
)
|
|
@@ -33303,7 +33681,7 @@ var LineMonthlyHistory = ({
|
|
|
33303
33681
|
new Date(year, month).toLocaleString("default", { month: "long", year: "numeric" })
|
|
33304
33682
|
] }),
|
|
33305
33683
|
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
33306
|
-
(
|
|
33684
|
+
(underperformingWorkspaces[selectedShiftId] || []).map((workspace) => /* @__PURE__ */ jsx(
|
|
33307
33685
|
"button",
|
|
33308
33686
|
{
|
|
33309
33687
|
onClick: () => handleWorkspaceClick(workspace),
|
|
@@ -33325,13 +33703,33 @@ var LineMonthlyHistory = ({
|
|
|
33325
33703
|
},
|
|
33326
33704
|
workspace.workspace_uuid
|
|
33327
33705
|
)),
|
|
33328
|
-
(!underperformingWorkspaces ||
|
|
33706
|
+
(!underperformingWorkspaces || !underperformingWorkspaces[selectedShiftId]?.length) && /* @__PURE__ */ jsx("div", { className: "text-center text-gray-500 py-4", children: "No consistently underperforming workspaces found" })
|
|
33329
33707
|
] })
|
|
33330
33708
|
] })
|
|
33331
33709
|
] })
|
|
33332
33710
|
] })
|
|
33333
33711
|
] });
|
|
33334
33712
|
};
|
|
33713
|
+
var DEFAULT_PERFORMANCE_DATA2 = {
|
|
33714
|
+
avg_efficiency: 0,
|
|
33715
|
+
underperforming_workspaces: 0,
|
|
33716
|
+
total_workspaces: 0,
|
|
33717
|
+
hasData: false
|
|
33718
|
+
};
|
|
33719
|
+
var getLineShiftData2 = (day, shiftId) => {
|
|
33720
|
+
const shift = day.shifts[shiftId];
|
|
33721
|
+
if (shift) {
|
|
33722
|
+
return { ...shift, hasData: true };
|
|
33723
|
+
}
|
|
33724
|
+
return { ...DEFAULT_PERFORMANCE_DATA2 };
|
|
33725
|
+
};
|
|
33726
|
+
var getShiftDisplayName = (shiftId, availableShifts) => {
|
|
33727
|
+
const shift = availableShifts?.find((s) => s.id === shiftId);
|
|
33728
|
+
if (shift) return shift.name;
|
|
33729
|
+
if (shiftId === 0) return "Day Shift";
|
|
33730
|
+
if (shiftId === 1) return "Night Shift";
|
|
33731
|
+
return `Shift ${shiftId}`;
|
|
33732
|
+
};
|
|
33335
33733
|
var LineMonthlyPdfGenerator = ({
|
|
33336
33734
|
lineId,
|
|
33337
33735
|
lineName,
|
|
@@ -33339,7 +33737,8 @@ var LineMonthlyPdfGenerator = ({
|
|
|
33339
33737
|
underperformingWorkspaces,
|
|
33340
33738
|
selectedMonth,
|
|
33341
33739
|
selectedYear,
|
|
33342
|
-
|
|
33740
|
+
selectedShiftId,
|
|
33741
|
+
availableShifts,
|
|
33343
33742
|
className
|
|
33344
33743
|
}) => {
|
|
33345
33744
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
@@ -33351,7 +33750,7 @@ var LineMonthlyPdfGenerator = ({
|
|
|
33351
33750
|
line_name: lineName,
|
|
33352
33751
|
month: selectedMonth,
|
|
33353
33752
|
year: selectedYear,
|
|
33354
|
-
|
|
33753
|
+
shift_id: selectedShiftId
|
|
33355
33754
|
});
|
|
33356
33755
|
const doc = new jsPDF$1();
|
|
33357
33756
|
doc.setFontSize(14);
|
|
@@ -33381,7 +33780,7 @@ var LineMonthlyPdfGenerator = ({
|
|
|
33381
33780
|
year: "numeric",
|
|
33382
33781
|
timeZone: "Asia/Kolkata"
|
|
33383
33782
|
});
|
|
33384
|
-
const shiftType =
|
|
33783
|
+
const shiftType = getShiftDisplayName(selectedShiftId, availableShifts);
|
|
33385
33784
|
doc.text(`${monthName}`, 20, 55);
|
|
33386
33785
|
doc.text(`${shiftType}`, 20, 63);
|
|
33387
33786
|
const startDate = new Date(selectedYear, selectedMonth, 1);
|
|
@@ -33410,7 +33809,7 @@ var LineMonthlyPdfGenerator = ({
|
|
|
33410
33809
|
return date.getMonth() === selectedMonth && date.getFullYear() === selectedYear;
|
|
33411
33810
|
});
|
|
33412
33811
|
const validShifts = validDays.map(
|
|
33413
|
-
(day) =>
|
|
33812
|
+
(day) => getLineShiftData2(day, selectedShiftId)
|
|
33414
33813
|
).filter((shift) => shift.avg_efficiency > 0);
|
|
33415
33814
|
const monthlyMetrics = validShifts.length > 0 ? {
|
|
33416
33815
|
avgEfficiency: validShifts.reduce((sum, shift) => sum + shift.avg_efficiency, 0) / validShifts.length,
|
|
@@ -33492,8 +33891,8 @@ var LineMonthlyPdfGenerator = ({
|
|
|
33492
33891
|
const recentDays = validDays.slice(-10).reverse();
|
|
33493
33892
|
recentDays.forEach((dayData, index) => {
|
|
33494
33893
|
if (yPos > 245) return;
|
|
33495
|
-
const shift =
|
|
33496
|
-
if (shift.avg_efficiency <= 0) return;
|
|
33894
|
+
const shift = getLineShiftData2(dayData, selectedShiftId);
|
|
33895
|
+
if (shift.avg_efficiency <= 0 || !shift.hasData) return;
|
|
33497
33896
|
if (index % 2 === 0) {
|
|
33498
33897
|
doc.setFillColor(252, 252, 252);
|
|
33499
33898
|
doc.roundedRect(20, yPos - 4, 170, 7, 1, 1, "F");
|
|
@@ -33527,7 +33926,7 @@ var LineMonthlyPdfGenerator = ({
|
|
|
33527
33926
|
doc.text("No daily data available for this month", 25, 200);
|
|
33528
33927
|
doc.setTextColor(0, 0, 0);
|
|
33529
33928
|
}
|
|
33530
|
-
const poorestWorkspaces =
|
|
33929
|
+
const poorestWorkspaces = underperformingWorkspaces[selectedShiftId] || [];
|
|
33531
33930
|
if (poorestWorkspaces && poorestWorkspaces.length > 0) {
|
|
33532
33931
|
doc.addPage();
|
|
33533
33932
|
doc.setFontSize(14);
|
|
@@ -33655,6 +34054,7 @@ Underperforming Workspaces: ${lineInfo.metrics.underperforming_workspaces} / ${l
|
|
|
33655
34054
|
var LinePdfGenerator = ({
|
|
33656
34055
|
lineInfo,
|
|
33657
34056
|
workspaceData,
|
|
34057
|
+
shiftName,
|
|
33658
34058
|
className
|
|
33659
34059
|
}) => {
|
|
33660
34060
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
@@ -33706,7 +34106,8 @@ var LinePdfGenerator = ({
|
|
|
33706
34106
|
doc.text(lineInfo.line_name, 20, 30);
|
|
33707
34107
|
doc.setFontSize(14);
|
|
33708
34108
|
doc.setFont("helvetica", "normal");
|
|
33709
|
-
const
|
|
34109
|
+
const rawShiftType = shiftName || (lineInfo.shift_id === 0 ? "Day" : lineInfo.shift_id === 1 ? "Night" : `Shift ${lineInfo.shift_id}`);
|
|
34110
|
+
const shiftType = rawShiftType.toLowerCase().includes("shift") ? rawShiftType : `${rawShiftType} Shift`;
|
|
33710
34111
|
const date = new Date(lineInfo.date).toLocaleDateString("en-IN", {
|
|
33711
34112
|
weekday: "long",
|
|
33712
34113
|
day: "numeric",
|
|
@@ -34381,9 +34782,10 @@ var WorkspaceHistoryCalendar = ({
|
|
|
34381
34782
|
month,
|
|
34382
34783
|
year,
|
|
34383
34784
|
workspaceId,
|
|
34384
|
-
|
|
34785
|
+
selectedShiftId = 0,
|
|
34385
34786
|
onMonthNavigate,
|
|
34386
34787
|
onShiftChange,
|
|
34788
|
+
availableShifts,
|
|
34387
34789
|
className
|
|
34388
34790
|
}) => {
|
|
34389
34791
|
const { dateTimeConfig } = useDashboardConfig();
|
|
@@ -34448,7 +34850,7 @@ var WorkspaceHistoryCalendar = ({
|
|
|
34448
34850
|
if (compareDate > istNow) {
|
|
34449
34851
|
return [];
|
|
34450
34852
|
}
|
|
34451
|
-
const shiftData =
|
|
34853
|
+
const shiftData = getShiftData(day, selectedShiftId);
|
|
34452
34854
|
if (hasRealData(shiftData)) {
|
|
34453
34855
|
return [shiftData];
|
|
34454
34856
|
}
|
|
@@ -34465,31 +34867,32 @@ var WorkspaceHistoryCalendar = ({
|
|
|
34465
34867
|
badDaysCount: badShiftsCount,
|
|
34466
34868
|
totalDays: validShifts.length
|
|
34467
34869
|
};
|
|
34468
|
-
}, [data, month, year, configuredTimezone,
|
|
34469
|
-
const handleDayClick = useCallback((day,
|
|
34870
|
+
}, [data, month, year, configuredTimezone, selectedShiftId]);
|
|
34871
|
+
const handleDayClick = useCallback((day, shiftId) => {
|
|
34470
34872
|
if (!day || isFutureDate(day.date)) return;
|
|
34471
34873
|
const year2 = day.date.getFullYear();
|
|
34472
34874
|
const month2 = String(day.date.getMonth() + 1).padStart(2, "0");
|
|
34473
34875
|
const dayOfMonth = String(day.date.getDate()).padStart(2, "0");
|
|
34474
34876
|
const formattedDate = `${year2}-${month2}-${dayOfMonth}`;
|
|
34475
|
-
const shiftData =
|
|
34877
|
+
const shiftData = getShiftData(day, shiftId);
|
|
34476
34878
|
trackCoreEvent("Workspace Monthly History Day Clicked", {
|
|
34477
34879
|
source: "workspace_detail",
|
|
34478
34880
|
workspace_id: workspaceId,
|
|
34479
34881
|
date: formattedDate,
|
|
34882
|
+
shift_id: shiftId,
|
|
34480
34883
|
efficiency: shiftData.efficiency,
|
|
34481
34884
|
output: shiftData.output,
|
|
34482
34885
|
cycle_time: shiftData.cycleTime
|
|
34483
34886
|
});
|
|
34484
|
-
onDateSelect(formattedDate);
|
|
34887
|
+
onDateSelect(formattedDate, shiftId);
|
|
34485
34888
|
}, [workspaceId, onDateSelect]);
|
|
34486
|
-
const handleShiftChange = useCallback((
|
|
34889
|
+
const handleShiftChange = useCallback((shiftId) => {
|
|
34487
34890
|
trackCoreEvent("Workspace Calendar Shift Changed", {
|
|
34488
34891
|
workspace_id: workspaceId,
|
|
34489
|
-
|
|
34892
|
+
new_shift_id: shiftId
|
|
34490
34893
|
});
|
|
34491
34894
|
if (onShiftChange) {
|
|
34492
|
-
onShiftChange(
|
|
34895
|
+
onShiftChange(shiftId);
|
|
34493
34896
|
}
|
|
34494
34897
|
}, [workspaceId, onShiftChange]);
|
|
34495
34898
|
const isCurrentDate = useCallback((date) => {
|
|
@@ -34570,13 +34973,13 @@ var WorkspaceHistoryCalendar = ({
|
|
|
34570
34973
|
}
|
|
34571
34974
|
return /* @__PURE__ */ jsx("div", { className: `h-full border border-gray-200 rounded-lg ${bgColor} ${animationComplete ? "transition-all duration-300 ease-in-out" : ""} cursor-not-allowed opacity-60`, children: /* @__PURE__ */ jsx("div", { className: "p-1 sm:p-2", children: /* @__PURE__ */ jsx("div", { className: `text-xs sm:text-sm lg:text-base font-medium ${textColor} ${isToday ? "text-blue-500" : ""}`, children: dayNumber }) }) });
|
|
34572
34975
|
}
|
|
34573
|
-
const shiftData =
|
|
34976
|
+
const shiftData = getShiftData(day, selectedShiftId);
|
|
34574
34977
|
const hasData = hasRealData(shiftData);
|
|
34575
34978
|
return /* @__PURE__ */ jsx(
|
|
34576
34979
|
"div",
|
|
34577
34980
|
{
|
|
34578
34981
|
className: `group h-full ${animationComplete ? "transition-all duration-300 ease-in-out" : ""} ${!isFuture && hasData && animationComplete ? "cursor-pointer hover:opacity-90 hover:scale-105" : "cursor-not-allowed"}`,
|
|
34579
|
-
onClick: () => !isFuture && hasData && handleDayClick(day,
|
|
34982
|
+
onClick: () => !isFuture && hasData && handleDayClick(day, selectedShiftId),
|
|
34580
34983
|
children: /* @__PURE__ */ jsxs("div", { className: `
|
|
34581
34984
|
${getPerformanceColor(shiftData.efficiency, day.date, hasData)}
|
|
34582
34985
|
rounded-lg h-full p-1 sm:p-2 relative ${animationComplete ? "transition-all duration-300 ease-in-out" : ""} shadow-sm
|
|
@@ -34590,31 +34993,25 @@ var WorkspaceHistoryCalendar = ({
|
|
|
34590
34993
|
] })
|
|
34591
34994
|
}
|
|
34592
34995
|
);
|
|
34593
|
-
}, [
|
|
34996
|
+
}, [selectedShiftId, isCurrentDate, isFutureDate, getPerformanceColor, handleDayClick, year, month, configuredTimezone, animationComplete, hasRealData]);
|
|
34594
34997
|
return /* @__PURE__ */ jsxs("div", { className: `calendar-wrapper space-y-6 ${className || ""} ${animationComplete ? "animation-complete" : ""}`, children: [
|
|
34595
34998
|
/* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: styles } }),
|
|
34596
|
-
/* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */
|
|
34597
|
-
|
|
34598
|
-
|
|
34599
|
-
|
|
34600
|
-
|
|
34601
|
-
|
|
34602
|
-
|
|
34603
|
-
}
|
|
34604
|
-
|
|
34605
|
-
|
|
34606
|
-
|
|
34607
|
-
|
|
34608
|
-
onClick: () => handleShiftChange("night"),
|
|
34609
|
-
className: `px-4 py-2 text-sm font-medium rounded-md ${animationComplete ? "transition-all duration-200" : ""} ${selectedShift === "night" ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : `text-gray-600 ${animationComplete ? "hover:text-gray-900 hover:bg-gray-100" : ""}`}`,
|
|
34610
|
-
children: "Night Shift"
|
|
34611
|
-
}
|
|
34612
|
-
)
|
|
34613
|
-
] }) }),
|
|
34999
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsx("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: (availableShifts && availableShifts.length > 0 ? availableShifts : [
|
|
35000
|
+
{ id: 0, name: "Day Shift" },
|
|
35001
|
+
{ id: 1, name: "Night Shift" }
|
|
35002
|
+
]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsx(
|
|
35003
|
+
"button",
|
|
35004
|
+
{
|
|
35005
|
+
onClick: () => handleShiftChange(shift.id),
|
|
35006
|
+
className: `px-4 py-2 text-sm font-medium rounded-md ${animationComplete ? "transition-all duration-200" : ""} ${selectedShiftId === shift.id ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : `text-gray-600 ${animationComplete ? "hover:text-gray-900 hover:bg-gray-100" : ""}`}`,
|
|
35007
|
+
children: shift.name
|
|
35008
|
+
},
|
|
35009
|
+
shift.id
|
|
35010
|
+
)) }) }),
|
|
34614
35011
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-4 lg:gap-8", children: [
|
|
34615
35012
|
/* @__PURE__ */ jsxs("div", { className: "calendar-container bg-white rounded-xl shadow-sm border border-gray-100 p-3 sm:p-4 lg:p-6 transition-all duration-200 ease-in-out", children: [
|
|
34616
35013
|
/* @__PURE__ */ jsxs("div", { className: "mb-3 sm:mb-4 lg:mb-6", children: [
|
|
34617
|
-
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-gray-900 text-base sm:text-lg", children:
|
|
35014
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-gray-900 text-base sm:text-lg", children: (availableShifts?.find((s) => s.id === selectedShiftId)?.name || (selectedShiftId === 0 ? "Day" : selectedShiftId === 1 ? "Night" : `Shift ${selectedShiftId}`)) + "s" }),
|
|
34618
35015
|
/* @__PURE__ */ jsx("p", { className: "text-xs sm:text-sm text-gray-500 mt-1", children: "Calendar view of daily performance" })
|
|
34619
35016
|
] }),
|
|
34620
35017
|
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 sm:gap-4 lg:gap-6", children: [
|
|
@@ -34630,7 +35027,7 @@ var WorkspaceHistoryCalendar = ({
|
|
|
34630
35027
|
/* @__PURE__ */ jsxs("div", { className: "mb-3 sm:mb-4 lg:mb-6", children: [
|
|
34631
35028
|
/* @__PURE__ */ jsxs("h3", { className: "font-semibold text-gray-900 text-base sm:text-lg", children: [
|
|
34632
35029
|
"Monthly Summary - ",
|
|
34633
|
-
|
|
35030
|
+
availableShifts?.find((s) => s.id === selectedShiftId)?.name || (selectedShiftId === 0 ? "Day Shift" : selectedShiftId === 1 ? "Night Shift" : `Shift ${selectedShiftId}`)
|
|
34634
35031
|
] }),
|
|
34635
35032
|
/* @__PURE__ */ jsx("p", { className: "text-xs sm:text-sm text-gray-500 mt-1", children: "Overview of monthly performance metrics" })
|
|
34636
35033
|
] }),
|
|
@@ -34704,10 +35101,11 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34704
35101
|
month,
|
|
34705
35102
|
year,
|
|
34706
35103
|
workspaceId,
|
|
34707
|
-
|
|
35104
|
+
selectedShiftId = 0,
|
|
34708
35105
|
onDateSelect,
|
|
34709
35106
|
onMonthNavigate,
|
|
34710
35107
|
onShiftChange,
|
|
35108
|
+
availableShifts,
|
|
34711
35109
|
monthlyDataLoading = false,
|
|
34712
35110
|
className = ""
|
|
34713
35111
|
}) => {
|
|
@@ -34725,7 +35123,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34725
35123
|
const date = new Date(d.date);
|
|
34726
35124
|
return date.getDate() === day;
|
|
34727
35125
|
});
|
|
34728
|
-
const shiftData = dayData ?
|
|
35126
|
+
const shiftData = dayData ? getShiftData(dayData, selectedShiftId) : null;
|
|
34729
35127
|
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
34730
35128
|
if (idealOutput > 0) {
|
|
34731
35129
|
lastSetTarget = idealOutput;
|
|
@@ -34737,7 +35135,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34737
35135
|
const date = new Date(d.date);
|
|
34738
35136
|
return date.getDate() === day;
|
|
34739
35137
|
});
|
|
34740
|
-
const shiftData = dayData ?
|
|
35138
|
+
const shiftData = dayData ? getShiftData(dayData, selectedShiftId) : null;
|
|
34741
35139
|
const output = shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
34742
35140
|
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
34743
35141
|
if (output > maxOutput) maxOutput = output;
|
|
@@ -34759,7 +35157,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34759
35157
|
const calculatedMax = Math.max(maxOutput, lastSetTarget);
|
|
34760
35158
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
34761
35159
|
return { data: dailyData, maxOutput, lastSetTarget, yAxisMax };
|
|
34762
|
-
}, [data, month, year,
|
|
35160
|
+
}, [data, month, year, selectedShiftId]);
|
|
34763
35161
|
const yAxisTicks = useMemo(() => {
|
|
34764
35162
|
const max = chartData.yAxisMax;
|
|
34765
35163
|
const target = chartData.lastSetTarget;
|
|
@@ -34782,7 +35180,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34782
35180
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
34783
35181
|
}, [chartData.yAxisMax, chartData.lastSetTarget]);
|
|
34784
35182
|
const pieChartData = useMemo(() => {
|
|
34785
|
-
const validShifts = data.map((d) =>
|
|
35183
|
+
const validShifts = data.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
|
|
34786
35184
|
if (validShifts.length === 0) return [];
|
|
34787
35185
|
const totalIdleTime = validShifts.reduce((sum, shift) => sum + shift.idleTime, 0);
|
|
34788
35186
|
const totalShiftTime = validShifts.length * 8 * 3600;
|
|
@@ -34791,9 +35189,9 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34791
35189
|
{ name: "Productive", value: Math.round(activeTime / totalShiftTime * 100) },
|
|
34792
35190
|
{ name: "Idle", value: Math.round(totalIdleTime / totalShiftTime * 100) }
|
|
34793
35191
|
];
|
|
34794
|
-
}, [data,
|
|
35192
|
+
}, [data, selectedShiftId]);
|
|
34795
35193
|
const metrics2 = useMemo(() => {
|
|
34796
|
-
const validShifts = data.map((d) =>
|
|
35194
|
+
const validShifts = data.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
|
|
34797
35195
|
if (validShifts.length === 0) return null;
|
|
34798
35196
|
const totalEfficiency = validShifts.reduce((sum, shift) => sum + shift.efficiency, 0);
|
|
34799
35197
|
const totalCycleTime = validShifts.reduce((sum, shift) => sum + shift.cycleTime, 0);
|
|
@@ -34813,7 +35211,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34813
35211
|
totalOutput,
|
|
34814
35212
|
avgIdleTime: Math.round(totalIdleTime / validShifts.length)
|
|
34815
35213
|
};
|
|
34816
|
-
}, [data,
|
|
35214
|
+
}, [data, selectedShiftId]);
|
|
34817
35215
|
const calendarData = useMemo(() => {
|
|
34818
35216
|
const startOfMonth = new Date(year, month, 1);
|
|
34819
35217
|
const endOfMonth = new Date(year, month + 1, 0);
|
|
@@ -34840,17 +35238,17 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34840
35238
|
source: "monthly_history",
|
|
34841
35239
|
workspace_id: workspaceId,
|
|
34842
35240
|
date: formattedDate,
|
|
34843
|
-
|
|
35241
|
+
shift_id: selectedShiftId
|
|
34844
35242
|
});
|
|
34845
|
-
onDateSelect(formattedDate,
|
|
34846
|
-
}, [workspaceId,
|
|
34847
|
-
const handleShiftChange = useCallback((
|
|
35243
|
+
onDateSelect(formattedDate, selectedShiftId);
|
|
35244
|
+
}, [workspaceId, selectedShiftId, onDateSelect]);
|
|
35245
|
+
const handleShiftChange = useCallback((shiftId) => {
|
|
34848
35246
|
trackCoreEvent("Workspace Monthly History Shift Changed", {
|
|
34849
35247
|
workspace_id: workspaceId,
|
|
34850
|
-
|
|
35248
|
+
new_shift_id: shiftId
|
|
34851
35249
|
});
|
|
34852
35250
|
if (onShiftChange) {
|
|
34853
|
-
onShiftChange(
|
|
35251
|
+
onShiftChange(shiftId);
|
|
34854
35252
|
}
|
|
34855
35253
|
}, [workspaceId, onShiftChange]);
|
|
34856
35254
|
if (monthlyDataLoading) {
|
|
@@ -34863,24 +35261,18 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34863
35261
|
) });
|
|
34864
35262
|
}
|
|
34865
35263
|
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-2 min-h-0 overflow-y-auto pb-6 ${className}`, children: [
|
|
34866
|
-
/* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */
|
|
34867
|
-
|
|
34868
|
-
|
|
34869
|
-
|
|
34870
|
-
|
|
34871
|
-
|
|
34872
|
-
|
|
34873
|
-
}
|
|
34874
|
-
|
|
34875
|
-
|
|
34876
|
-
|
|
34877
|
-
|
|
34878
|
-
onClick: () => handleShiftChange("night"),
|
|
34879
|
-
className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShift === "night" ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
|
|
34880
|
-
children: "Night Shift"
|
|
34881
|
-
}
|
|
34882
|
-
)
|
|
34883
|
-
] }) }),
|
|
35264
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsx("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: (availableShifts && availableShifts.length > 0 ? availableShifts : [
|
|
35265
|
+
{ id: 0, name: "Day Shift" },
|
|
35266
|
+
{ id: 1, name: "Night Shift" }
|
|
35267
|
+
]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsx(
|
|
35268
|
+
"button",
|
|
35269
|
+
{
|
|
35270
|
+
onClick: () => handleShiftChange(shift.id),
|
|
35271
|
+
className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShiftId === shift.id ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
|
|
35272
|
+
children: shift.name
|
|
35273
|
+
},
|
|
35274
|
+
shift.id
|
|
35275
|
+
)) }) }),
|
|
34884
35276
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6", children: [
|
|
34885
35277
|
/* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
|
|
34886
35278
|
/* @__PURE__ */ jsxs("div", { className: "flex justify-center items-center mb-6 space-x-4", children: [
|
|
@@ -34944,7 +35336,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
34944
35336
|
if (!dayNumber || dayNumber > new Date(year, month + 1, 0).getDate()) {
|
|
34945
35337
|
return /* @__PURE__ */ jsx("div", { className: "aspect-square relative", children: /* @__PURE__ */ jsx("div", { className: "h-full border border-gray-100 dark:border-gray-700 rounded-lg bg-gray-50 dark:bg-gray-800" }) }, index);
|
|
34946
35338
|
}
|
|
34947
|
-
const shiftData = day ?
|
|
35339
|
+
const shiftData = day ? getShiftData(day, selectedShiftId) : null;
|
|
34948
35340
|
const hasData = shiftData ? hasRealData(shiftData) : false;
|
|
34949
35341
|
const isToday = (/* @__PURE__ */ new Date()).getDate() === dayNumber && (/* @__PURE__ */ new Date()).getMonth() === month && (/* @__PURE__ */ new Date()).getFullYear() === year;
|
|
34950
35342
|
const isFuture = new Date(year, month, dayNumber) > /* @__PURE__ */ new Date();
|
|
@@ -35271,7 +35663,8 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
|
|
|
35271
35663
|
month: "long",
|
|
35272
35664
|
timeZone: "Asia/Kolkata"
|
|
35273
35665
|
});
|
|
35274
|
-
const
|
|
35666
|
+
const rawShiftType = workspace.shift_type || (workspace.shift_id === 0 ? "Day" : workspace.shift_id === 1 ? "Night" : `Shift ${workspace.shift_id}`);
|
|
35667
|
+
const shiftType = rawShiftType.toLowerCase().includes("shift") ? rawShiftType : `${rawShiftType} Shift`;
|
|
35275
35668
|
doc.text(`${date}`, 20, 63);
|
|
35276
35669
|
doc.text(`${shiftType}`, 20, 71);
|
|
35277
35670
|
const currentTime = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-IN", {
|
|
@@ -35421,13 +35814,21 @@ var WorkspacePdfGenerator = ({ workspace, className }) => {
|
|
|
35421
35814
|
}
|
|
35422
35815
|
);
|
|
35423
35816
|
};
|
|
35817
|
+
var getShiftDisplayName2 = (shiftId, availableShifts) => {
|
|
35818
|
+
const shift = availableShifts?.find((s) => s.id === shiftId);
|
|
35819
|
+
if (shift) return shift.name;
|
|
35820
|
+
if (shiftId === 0) return "Day Shift";
|
|
35821
|
+
if (shiftId === 1) return "Night Shift";
|
|
35822
|
+
return `Shift ${shiftId}`;
|
|
35823
|
+
};
|
|
35424
35824
|
var WorkspaceMonthlyPdfGenerator = ({
|
|
35425
35825
|
workspaceId,
|
|
35426
35826
|
workspaceName,
|
|
35427
35827
|
monthlyData,
|
|
35428
35828
|
selectedMonth,
|
|
35429
35829
|
selectedYear,
|
|
35430
|
-
|
|
35830
|
+
selectedShiftId,
|
|
35831
|
+
availableShifts,
|
|
35431
35832
|
className
|
|
35432
35833
|
}) => {
|
|
35433
35834
|
const [isGenerating, setIsGenerating] = useState(false);
|
|
@@ -35439,7 +35840,7 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
35439
35840
|
workspace_name: workspaceName,
|
|
35440
35841
|
month: selectedMonth,
|
|
35441
35842
|
year: selectedYear,
|
|
35442
|
-
|
|
35843
|
+
shift_id: selectedShiftId
|
|
35443
35844
|
});
|
|
35444
35845
|
const doc = new jsPDF$1();
|
|
35445
35846
|
doc.setFontSize(14);
|
|
@@ -35473,7 +35874,7 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
35473
35874
|
year: "numeric",
|
|
35474
35875
|
timeZone: "Asia/Kolkata"
|
|
35475
35876
|
});
|
|
35476
|
-
const shiftType =
|
|
35877
|
+
const shiftType = getShiftDisplayName2(selectedShiftId, availableShifts);
|
|
35477
35878
|
doc.text(`${monthName}`, 20, 65);
|
|
35478
35879
|
doc.text(`${shiftType}`, 20, 73);
|
|
35479
35880
|
const startDate = new Date(selectedYear, selectedMonth, 1);
|
|
@@ -35502,7 +35903,7 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
35502
35903
|
return date.getMonth() === selectedMonth && date.getFullYear() === selectedYear;
|
|
35503
35904
|
});
|
|
35504
35905
|
const validShifts = validDays.map(
|
|
35505
|
-
(day) =>
|
|
35906
|
+
(day) => getShiftData(day, selectedShiftId)
|
|
35506
35907
|
).filter((shift) => shift.efficiency > 0);
|
|
35507
35908
|
const monthlyMetrics = validShifts.length > 0 ? {
|
|
35508
35909
|
avgEfficiency: validShifts.reduce((sum, shift) => sum + shift.efficiency, 0) / validShifts.length,
|
|
@@ -35590,7 +35991,7 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
35590
35991
|
const recentDays = validDays.slice(-10).reverse();
|
|
35591
35992
|
recentDays.forEach((dayData, index) => {
|
|
35592
35993
|
if (yPos > 260) return;
|
|
35593
|
-
const shift =
|
|
35994
|
+
const shift = getShiftData(dayData, selectedShiftId);
|
|
35594
35995
|
if (shift.efficiency <= 0) return;
|
|
35595
35996
|
if (index % 2 === 0) {
|
|
35596
35997
|
doc.setFillColor(252, 252, 252);
|
|
@@ -36977,19 +37378,26 @@ var HealthStatusGrid = ({
|
|
|
36977
37378
|
};
|
|
36978
37379
|
var Timer2 = Timer_default;
|
|
36979
37380
|
var DashboardHeader = memo(({ lineTitle, className = "", headerControls, lineId }) => {
|
|
36980
|
-
const { shiftConfig } = useDynamicShiftConfig(lineId);
|
|
37381
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
36981
37382
|
const timezone = useAppTimezone();
|
|
36982
37383
|
const getShiftName = () => {
|
|
36983
37384
|
const currentShift = getCurrentShift(timezone, shiftConfig);
|
|
36984
|
-
|
|
37385
|
+
const rawName = currentShift.shiftName || "Day";
|
|
37386
|
+
return rawName.toLowerCase().includes("shift") ? rawName : `${rawName} Shift`;
|
|
36985
37387
|
};
|
|
36986
37388
|
const getShiftIcon = () => {
|
|
36987
|
-
const
|
|
36988
|
-
|
|
37389
|
+
const currentShift = getCurrentShift(timezone, shiftConfig);
|
|
37390
|
+
const shiftName = (currentShift.shiftName || "").toLowerCase();
|
|
37391
|
+
if (shiftName.includes("day") || shiftName.includes("morning") || currentShift.shiftId === 0) {
|
|
36989
37392
|
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" }) });
|
|
36990
|
-
}
|
|
37393
|
+
}
|
|
37394
|
+
if (shiftName.includes("afternoon") || shiftName.includes("noon") || shiftName.includes("midday")) {
|
|
37395
|
+
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" }) });
|
|
37396
|
+
}
|
|
37397
|
+
if (shiftName.includes("night") || shiftName.includes("evening") || currentShift.shiftId === 1) {
|
|
36991
37398
|
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: "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" }) });
|
|
36992
37399
|
}
|
|
37400
|
+
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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
36993
37401
|
};
|
|
36994
37402
|
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col sm:flex-row items-start sm:items-center justify-between w-full gap-2 sm:gap-4 ${className}`, children: [
|
|
36995
37403
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
@@ -36999,13 +37407,10 @@ var DashboardHeader = memo(({ lineTitle, className = "", headerControls, lineId
|
|
|
36999
37407
|
] }),
|
|
37000
37408
|
/* @__PURE__ */ jsxs("div", { className: "mt-0.5 sm:mt-2 inline-flex flex-wrap items-center gap-1.5 sm:gap-3", children: [
|
|
37001
37409
|
/* @__PURE__ */ jsx("div", { className: "text-[10px] sm:text-xs md:text-sm font-medium text-gray-500 sm:text-gray-600 whitespace-nowrap", children: /* @__PURE__ */ jsx(Timer2, {}) }),
|
|
37002
|
-
/* @__PURE__ */
|
|
37410
|
+
/* @__PURE__ */ jsx("div", { className: "inline-flex items-center gap-0.5 sm:gap-1", children: isShiftConfigLoading ? /* @__PURE__ */ jsx("div", { className: "h-4 w-16 sm:w-20 bg-gray-200 rounded animate-pulse" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
37003
37411
|
/* @__PURE__ */ jsx("div", { className: "text-gray-500 sm:text-gray-600 scale-90 sm:scale-100", children: getShiftIcon() }),
|
|
37004
|
-
/* @__PURE__ */
|
|
37005
|
-
|
|
37006
|
-
" Shift"
|
|
37007
|
-
] })
|
|
37008
|
-
] })
|
|
37412
|
+
/* @__PURE__ */ jsx("span", { className: "text-[10px] sm:text-xs md:text-sm font-medium text-gray-500 sm:text-gray-600 whitespace-nowrap", children: getShiftName() })
|
|
37413
|
+
] }) })
|
|
37009
37414
|
] })
|
|
37010
37415
|
] }),
|
|
37011
37416
|
headerControls && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 sm:gap-3 md:gap-4 w-full sm:w-auto justify-end", children: headerControls })
|
|
@@ -42022,18 +42427,23 @@ var FactoryView = ({
|
|
|
42022
42427
|
fetchHourlyData();
|
|
42023
42428
|
}
|
|
42024
42429
|
}, [supabase, lineDataHooks, effectiveLineIds, lineNames, factoryName, timezone, shiftConfig, productIds]);
|
|
42430
|
+
const getCurrentShiftInfo = () => {
|
|
42431
|
+
return getCurrentShift(timezone, shiftConfig);
|
|
42432
|
+
};
|
|
42025
42433
|
const getShiftName = () => {
|
|
42026
|
-
const
|
|
42027
|
-
|
|
42028
|
-
return currentHour >= 6 && currentHour < 18 ? "Day" : "Night";
|
|
42434
|
+
const currentShift = getCurrentShiftInfo();
|
|
42435
|
+
return (currentShift.shiftName || "Day").replace(/ Shift$/i, "");
|
|
42029
42436
|
};
|
|
42030
42437
|
const getShiftIcon = () => {
|
|
42031
|
-
const
|
|
42032
|
-
|
|
42438
|
+
const currentShift = getCurrentShiftInfo();
|
|
42439
|
+
const shiftNameLower = (currentShift.shiftName || "").toLowerCase();
|
|
42440
|
+
if (shiftNameLower.includes("day") || shiftNameLower.includes("morning") || currentShift.shiftId === 0) {
|
|
42033
42441
|
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" }) });
|
|
42034
|
-
}
|
|
42442
|
+
}
|
|
42443
|
+
if (shiftNameLower.includes("night") || shiftNameLower.includes("evening") || currentShift.shiftId === 1) {
|
|
42035
42444
|
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: "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" }) });
|
|
42036
42445
|
}
|
|
42446
|
+
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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
42037
42447
|
};
|
|
42038
42448
|
if (loading || lineDataHooks.some((hookData) => hookData.hook.loading)) {
|
|
42039
42449
|
return /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-4", children: [
|
|
@@ -43562,8 +43972,8 @@ var KPIDetailView = ({
|
|
|
43562
43972
|
return (/* @__PURE__ */ new Date()).getFullYear();
|
|
43563
43973
|
});
|
|
43564
43974
|
const [monthlyData, setMonthlyData] = useState([]);
|
|
43565
|
-
const [underperformingWorkspaces, setUnderperformingWorkspaces] = useState({
|
|
43566
|
-
const [
|
|
43975
|
+
const [underperformingWorkspaces, setUnderperformingWorkspaces] = useState({});
|
|
43976
|
+
const [selectedShiftId, setSelectedShiftId] = useState(0);
|
|
43567
43977
|
const [showLineDataNotFound, setShowLineDataNotFound] = useState(false);
|
|
43568
43978
|
const navigation = useNavigation(navigate);
|
|
43569
43979
|
const handleNavigate = navigate || navigation.navigate;
|
|
@@ -43593,20 +44003,22 @@ var KPIDetailView = ({
|
|
|
43593
44003
|
setActiveTab("overview");
|
|
43594
44004
|
}
|
|
43595
44005
|
}, [urlDate, urlShift, urlTab]);
|
|
44006
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(lineId);
|
|
43596
44007
|
const getShiftName = useCallback((shiftId) => {
|
|
43597
|
-
return shiftId
|
|
43598
|
-
}, []);
|
|
44008
|
+
return getShiftNameById(shiftId, configuredTimezone, shiftConfig);
|
|
44009
|
+
}, [configuredTimezone, shiftConfig]);
|
|
43599
44010
|
const getShiftIcon = useCallback((shiftId) => {
|
|
43600
|
-
|
|
43601
|
-
if (shift === "Day") {
|
|
44011
|
+
if (shiftId === 0) {
|
|
43602
44012
|
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" }) });
|
|
43603
|
-
}
|
|
44013
|
+
}
|
|
44014
|
+
if (shiftId === 1) {
|
|
43604
44015
|
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: "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" }) });
|
|
43605
44016
|
}
|
|
43606
|
-
|
|
44017
|
+
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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
44018
|
+
}, []);
|
|
43607
44019
|
const getDaysDifference2 = useCallback((date) => {
|
|
43608
44020
|
const compareDate = new Date(date);
|
|
43609
|
-
const shiftStartTime =
|
|
44021
|
+
const shiftStartTime = shiftConfig?.dayShift?.startTime || shiftConfig?.shifts?.[0]?.startTime || "06:00";
|
|
43610
44022
|
const operationalTodayString = getOperationalDate(configuredTimezone, /* @__PURE__ */ new Date(), shiftStartTime);
|
|
43611
44023
|
const operationalTodayDate = new Date(operationalTodayString);
|
|
43612
44024
|
const compareDateInZone = new Date(compareDate.toLocaleString("en-US", { timeZone: configuredTimezone }));
|
|
@@ -43620,7 +44032,7 @@ var KPIDetailView = ({
|
|
|
43620
44032
|
if (diffDays < -1) return `${Math.abs(diffDays)} days ago`;
|
|
43621
44033
|
if (diffDays > 1) return `${diffDays} days ahead`;
|
|
43622
44034
|
return "Today";
|
|
43623
|
-
}, [configuredTimezone,
|
|
44035
|
+
}, [configuredTimezone, shiftConfig]);
|
|
43624
44036
|
const {
|
|
43625
44037
|
metrics: metrics2,
|
|
43626
44038
|
lineDetails,
|
|
@@ -43630,7 +44042,9 @@ var KPIDetailView = ({
|
|
|
43630
44042
|
} = useRealtimeLineMetrics({
|
|
43631
44043
|
lineId,
|
|
43632
44044
|
date: typeof urlDate === "string" ? urlDate : void 0,
|
|
43633
|
-
shiftId: parsedShiftId
|
|
44045
|
+
shiftId: parsedShiftId,
|
|
44046
|
+
enabled: !isShiftConfigLoading
|
|
44047
|
+
// Pass enabled flag to useRealtimeLineMetrics if supported, or we need to add it
|
|
43634
44048
|
});
|
|
43635
44049
|
const {
|
|
43636
44050
|
workspaces,
|
|
@@ -43639,7 +44053,9 @@ var KPIDetailView = ({
|
|
|
43639
44053
|
refreshWorkspaces
|
|
43640
44054
|
} = useLineWorkspaceMetrics(lineId, {
|
|
43641
44055
|
initialDate: typeof urlDate === "string" ? urlDate : void 0,
|
|
43642
|
-
initialShiftId: parsedShiftId
|
|
44056
|
+
initialShiftId: parsedShiftId,
|
|
44057
|
+
enabled: !isShiftConfigLoading
|
|
44058
|
+
// Pass enabled flag to useLineWorkspaceMetrics if supported, or we need to add it
|
|
43643
44059
|
});
|
|
43644
44060
|
useEffect(() => {
|
|
43645
44061
|
if (activeTab === "monthly_history" && lineId) {
|
|
@@ -43652,7 +44068,9 @@ var KPIDetailView = ({
|
|
|
43652
44068
|
dashboardService.getUnderperformingWorkspaces(
|
|
43653
44069
|
lineId,
|
|
43654
44070
|
currentMonth,
|
|
43655
|
-
currentYear
|
|
44071
|
+
currentYear,
|
|
44072
|
+
shiftConfig?.shifts?.map((s) => s.shiftId)
|
|
44073
|
+
// Pass dynamic shift IDs
|
|
43656
44074
|
)
|
|
43657
44075
|
]).then(([monthlyMetrics, underperformingData]) => {
|
|
43658
44076
|
console.log("Fetched monthly metrics data:", monthlyMetrics);
|
|
@@ -43664,18 +44082,8 @@ var KPIDetailView = ({
|
|
|
43664
44082
|
if (!dayData) {
|
|
43665
44083
|
dayData = {
|
|
43666
44084
|
date,
|
|
43667
|
-
|
|
43668
|
-
|
|
43669
|
-
underperforming_workspaces: 0,
|
|
43670
|
-
total_workspaces: 0,
|
|
43671
|
-
compliance_percentage: 0
|
|
43672
|
-
},
|
|
43673
|
-
nightShift: {
|
|
43674
|
-
avg_efficiency: 0,
|
|
43675
|
-
underperforming_workspaces: 0,
|
|
43676
|
-
total_workspaces: 0,
|
|
43677
|
-
compliance_percentage: 0
|
|
43678
|
-
}
|
|
44085
|
+
shifts: {}
|
|
44086
|
+
// Multi-shift structure: Record<number, ShiftData>
|
|
43679
44087
|
};
|
|
43680
44088
|
dayDataMap.set(dateKey, dayData);
|
|
43681
44089
|
}
|
|
@@ -43683,46 +44091,46 @@ var KPIDetailView = ({
|
|
|
43683
44091
|
avg_efficiency: metric.avg_efficiency || 0,
|
|
43684
44092
|
underperforming_workspaces: metric.underperforming_workspaces || 0,
|
|
43685
44093
|
total_workspaces: metric.total_workspaces || 0,
|
|
43686
|
-
compliance_percentage: 95 + Math.random() * 5
|
|
44094
|
+
compliance_percentage: 95 + Math.random() * 5,
|
|
43687
44095
|
// Mock data: random value between 95-100%
|
|
44096
|
+
hasData: true
|
|
43688
44097
|
};
|
|
43689
|
-
|
|
43690
|
-
dayData.dayShift = shiftData;
|
|
43691
|
-
} else {
|
|
43692
|
-
dayData.nightShift = shiftData;
|
|
43693
|
-
}
|
|
44098
|
+
dayData.shifts[metric.shift_id] = shiftData;
|
|
43694
44099
|
});
|
|
43695
44100
|
const transformedMonthlyData = Array.from(dayDataMap.values());
|
|
43696
44101
|
console.log("Transformed monthly data for calendar:", transformedMonthlyData);
|
|
43697
44102
|
setMonthlyData(transformedMonthlyData);
|
|
43698
|
-
const
|
|
43699
|
-
|
|
43700
|
-
|
|
43701
|
-
|
|
43702
|
-
|
|
43703
|
-
|
|
43704
|
-
|
|
43705
|
-
|
|
43706
|
-
performance_score: day.performance_score
|
|
43707
|
-
}))
|
|
43708
|
-
})),
|
|
43709
|
-
nightShift: (underperformingData.nightShift || []).map((ws) => ({
|
|
43710
|
-
workspace_name: ws.workspace_name || "Unknown Workspace",
|
|
43711
|
-
workspace_uuid: ws.workspace_uuid || ws.workspace_name || `unknown-${Math.random()}`,
|
|
43712
|
-
avg_efficiency: ws.avg_efficiency || 0,
|
|
43713
|
-
last_5_days: (ws.last_5_days || []).map((day) => ({
|
|
43714
|
-
date: day.date,
|
|
43715
|
-
efficiency: day.efficiency ?? 0,
|
|
43716
|
-
performance_score: day.performance_score
|
|
43717
|
-
}))
|
|
44103
|
+
const mapWorkspaces = (workspaces2) => (workspaces2 || []).map((ws) => ({
|
|
44104
|
+
workspace_name: ws.workspace_name || "Unknown Workspace",
|
|
44105
|
+
workspace_uuid: ws.workspace_uuid || ws.workspace_name || `unknown-${Math.random()}`,
|
|
44106
|
+
avg_efficiency: ws.avg_efficiency || 0,
|
|
44107
|
+
last_5_days: (ws.last_5_days || []).map((day) => ({
|
|
44108
|
+
date: day.date,
|
|
44109
|
+
efficiency: day.efficiency ?? 0,
|
|
44110
|
+
performance_score: day.performance_score
|
|
43718
44111
|
}))
|
|
43719
|
-
};
|
|
44112
|
+
}));
|
|
44113
|
+
const mappedData = {};
|
|
44114
|
+
if (underperformingData.dayShift) {
|
|
44115
|
+
mappedData[0] = mapWorkspaces(underperformingData.dayShift);
|
|
44116
|
+
}
|
|
44117
|
+
if (underperformingData.nightShift) {
|
|
44118
|
+
mappedData[1] = mapWorkspaces(underperformingData.nightShift);
|
|
44119
|
+
}
|
|
44120
|
+
Object.entries(underperformingData).forEach(([key, value]) => {
|
|
44121
|
+
if (key !== "dayShift" && key !== "nightShift" && Array.isArray(value)) {
|
|
44122
|
+
const shiftId = parseInt(key);
|
|
44123
|
+
if (!isNaN(shiftId)) {
|
|
44124
|
+
mappedData[shiftId] = mapWorkspaces(value);
|
|
44125
|
+
}
|
|
44126
|
+
}
|
|
44127
|
+
});
|
|
43720
44128
|
setUnderperformingWorkspaces(mappedData);
|
|
43721
44129
|
}).catch((error) => {
|
|
43722
44130
|
console.error("Error fetching monthly data:", error);
|
|
43723
44131
|
});
|
|
43724
44132
|
}
|
|
43725
|
-
}, [activeTab, lineId, currentMonth, currentYear, supabase, dashboardConfig]);
|
|
44133
|
+
}, [activeTab, lineId, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig]);
|
|
43726
44134
|
const lineInfo = useMemo(() => {
|
|
43727
44135
|
if (!metrics2 || !lineDetails || !lineDetails.factory) {
|
|
43728
44136
|
return null;
|
|
@@ -43967,7 +44375,7 @@ var KPIDetailView = ({
|
|
|
43967
44375
|
handleNavigate(backUrl);
|
|
43968
44376
|
}
|
|
43969
44377
|
}, [urlDate, urlShift, lineInfo, onBackClick, backLinkUrl, handleNavigate, urlMonth, urlYear, lineId, currentMonth, currentYear]);
|
|
43970
|
-
if ((lineMetricsLoading || workspacesLoading) && !lineInfo && !metrics2) {
|
|
44378
|
+
if ((lineMetricsLoading || workspacesLoading || isShiftConfigLoading) && !lineInfo && !metrics2) {
|
|
43971
44379
|
return /* @__PURE__ */ jsx(LoadingPage, { message: "Loading line metrics..." });
|
|
43972
44380
|
}
|
|
43973
44381
|
if (lineMetricsError || workspacesError) {
|
|
@@ -44074,7 +44482,10 @@ var KPIDetailView = ({
|
|
|
44074
44482
|
/* @__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: metrics2 && formatLocalDate(new Date(metrics2.date)) }) }),
|
|
44075
44483
|
/* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
|
|
44076
44484
|
/* @__PURE__ */ jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(metrics2.shift_id ?? 0) }),
|
|
44077
|
-
/* @__PURE__ */
|
|
44485
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-medium text-gray-700", children: [
|
|
44486
|
+
getShiftName(metrics2.shift_id ?? 0).replace(/ Shift$/i, ""),
|
|
44487
|
+
" Shift"
|
|
44488
|
+
] })
|
|
44078
44489
|
] }),
|
|
44079
44490
|
!urlDate && !urlShift ? /* @__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(ISTTimer_default, {}) }) }) : urlDate && metrics2.date ? /* @__PURE__ */ jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-blue-100 rounded-full", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-blue-700", children: getDaysDifference2(metrics2.date) }) }) : null
|
|
44080
44491
|
] }),
|
|
@@ -44092,7 +44503,7 @@ var KPIDetailView = ({
|
|
|
44092
44503
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
44093
44504
|
/* @__PURE__ */ jsx("div", { className: "text-blue-600", children: getShiftIcon(metrics2.shift_id ?? 0) }),
|
|
44094
44505
|
/* @__PURE__ */ jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
|
|
44095
|
-
getShiftName(metrics2.shift_id ?? 0),
|
|
44506
|
+
getShiftName(metrics2.shift_id ?? 0).replace(/ Shift$/i, ""),
|
|
44096
44507
|
" Shift"
|
|
44097
44508
|
] })
|
|
44098
44509
|
] })
|
|
@@ -44137,7 +44548,7 @@ var KPIDetailView = ({
|
|
|
44137
44548
|
)
|
|
44138
44549
|
] }),
|
|
44139
44550
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 ml-auto", children: [
|
|
44140
|
-
lineInfo && activeTab === "overview" && /* @__PURE__ */ jsx(LinePdfGenerator, { lineInfo, workspaceData: workspaces || [] }),
|
|
44551
|
+
lineInfo && activeTab === "overview" && /* @__PURE__ */ jsx(LinePdfGenerator, { lineInfo, workspaceData: workspaces || [], shiftName: getShiftName(lineInfo.shift_id) }),
|
|
44141
44552
|
activeTab === "monthly_history" && /* @__PURE__ */ jsx(
|
|
44142
44553
|
LineMonthlyPdfGenerator,
|
|
44143
44554
|
{
|
|
@@ -44147,7 +44558,7 @@ var KPIDetailView = ({
|
|
|
44147
44558
|
underperformingWorkspaces,
|
|
44148
44559
|
selectedMonth: currentMonth,
|
|
44149
44560
|
selectedYear: currentYear,
|
|
44150
|
-
|
|
44561
|
+
selectedShiftId
|
|
44151
44562
|
}
|
|
44152
44563
|
)
|
|
44153
44564
|
] })
|
|
@@ -44250,8 +44661,9 @@ var KPIDetailView = ({
|
|
|
44250
44661
|
monthlyData,
|
|
44251
44662
|
month: currentMonth,
|
|
44252
44663
|
year: currentYear,
|
|
44253
|
-
|
|
44254
|
-
onShiftChange:
|
|
44664
|
+
selectedShiftId,
|
|
44665
|
+
onShiftChange: setSelectedShiftId,
|
|
44666
|
+
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName }))
|
|
44255
44667
|
}
|
|
44256
44668
|
)
|
|
44257
44669
|
]
|
|
@@ -44402,7 +44814,8 @@ var KPIsOverviewView = ({
|
|
|
44402
44814
|
const dashboardConfig = useDashboardConfig();
|
|
44403
44815
|
const navigation = useNavigation(navigate);
|
|
44404
44816
|
const dateTimeConfig = useDateTimeConfig();
|
|
44405
|
-
const
|
|
44817
|
+
const representativeLineId = lineIds?.[0] || lines[0]?.id;
|
|
44818
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(representativeLineId);
|
|
44406
44819
|
const supervisorEnabled = dashboardConfig?.supervisorConfig?.enabled || false;
|
|
44407
44820
|
const dbTimezone = useAppTimezone();
|
|
44408
44821
|
const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
|
|
@@ -44464,15 +44877,21 @@ var KPIsOverviewView = ({
|
|
|
44464
44877
|
return date.toLocaleDateString("en-US", options);
|
|
44465
44878
|
};
|
|
44466
44879
|
const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
|
|
44467
|
-
const shiftName = currentShiftDetails.
|
|
44880
|
+
const shiftName = (currentShiftDetails.shiftName || "Day").replace(/ Shift$/i, "");
|
|
44468
44881
|
const getShiftIcon = (shiftId) => {
|
|
44469
|
-
|
|
44882
|
+
const shiftNameLower = shiftName.toLowerCase();
|
|
44883
|
+
if (shiftNameLower.includes("day") || shiftNameLower.includes("morning") || shiftId === 0) {
|
|
44470
44884
|
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" }) });
|
|
44471
|
-
}
|
|
44885
|
+
}
|
|
44886
|
+
if (shiftNameLower.includes("afternoon") || shiftNameLower.includes("noon") || shiftNameLower.includes("midday")) {
|
|
44887
|
+
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" }) });
|
|
44888
|
+
}
|
|
44889
|
+
if (shiftNameLower.includes("night") || shiftNameLower.includes("evening") || shiftId === 1) {
|
|
44472
44890
|
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: "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" }) });
|
|
44473
44891
|
}
|
|
44892
|
+
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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
44474
44893
|
};
|
|
44475
|
-
if (loading) {
|
|
44894
|
+
if (loading || isShiftConfigLoading) {
|
|
44476
44895
|
return /* @__PURE__ */ jsx(LoadingPage, { message: "Loading production lines..." });
|
|
44477
44896
|
}
|
|
44478
44897
|
if (error) {
|
|
@@ -44641,7 +45060,7 @@ var HeaderRibbon = memo(({
|
|
|
44641
45060
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
44642
45061
|
/* @__PURE__ */ jsx("div", { className: "text-blue-600", children: shiftIcon }),
|
|
44643
45062
|
/* @__PURE__ */ jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
|
|
44644
|
-
shiftName,
|
|
45063
|
+
shiftName.replace(/ Shift$/i, ""),
|
|
44645
45064
|
" Shift"
|
|
44646
45065
|
] })
|
|
44647
45066
|
] })
|
|
@@ -44768,6 +45187,7 @@ var LeaderboardDetailView = memo(({
|
|
|
44768
45187
|
const navigation = useNavigation();
|
|
44769
45188
|
const entityConfig = useEntityConfig();
|
|
44770
45189
|
const [sortAscending, setSortAscending] = useState(false);
|
|
45190
|
+
const timezone = useAppTimezone();
|
|
44771
45191
|
const [isMobile, setIsMobile] = useState(false);
|
|
44772
45192
|
React23__default.useEffect(() => {
|
|
44773
45193
|
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
@@ -44796,6 +45216,9 @@ var LeaderboardDetailView = memo(({
|
|
|
44796
45216
|
() => typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
|
|
44797
45217
|
[shift]
|
|
44798
45218
|
);
|
|
45219
|
+
const availableLineId = Object.keys(configuredLineNames)[0];
|
|
45220
|
+
const effectiveLineId = lineId || userAccessibleLineIds?.[0] || availableLineId;
|
|
45221
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(effectiveLineId);
|
|
44799
45222
|
const {
|
|
44800
45223
|
workspaces,
|
|
44801
45224
|
loading: workspacesLoading,
|
|
@@ -44804,20 +45227,31 @@ var LeaderboardDetailView = memo(({
|
|
|
44804
45227
|
} = useAllWorkspaceMetrics({
|
|
44805
45228
|
initialDate: date,
|
|
44806
45229
|
initialShiftId: typeof shift === "number" ? shift : typeof shift === "string" ? parseInt(shift) : void 0,
|
|
44807
|
-
allowedLineIds: userAccessibleLineIds
|
|
45230
|
+
allowedLineIds: userAccessibleLineIds,
|
|
44808
45231
|
// Filter to user's accessible lines only
|
|
45232
|
+
enabled: !isShiftConfigLoading
|
|
45233
|
+
// Pass enabled flag
|
|
44809
45234
|
});
|
|
44810
45235
|
const getShiftName = useCallback((shiftId2) => {
|
|
44811
|
-
if (shiftId2
|
|
44812
|
-
|
|
44813
|
-
|
|
45236
|
+
if (shiftId2 !== void 0) {
|
|
45237
|
+
return getShiftNameById(shiftId2, timezone || "Asia/Kolkata", shiftConfig);
|
|
45238
|
+
}
|
|
45239
|
+
const currentShift = getCurrentShift(timezone || "Asia/Kolkata", shiftConfig);
|
|
45240
|
+
return currentShift.shiftName || getShiftNameById(currentShift.shiftId, timezone || "Asia/Kolkata", shiftConfig);
|
|
45241
|
+
}, [timezone, shiftConfig]);
|
|
44814
45242
|
const getShiftIcon = useCallback((shiftId2) => {
|
|
44815
|
-
const
|
|
44816
|
-
|
|
45243
|
+
const effectiveShiftId = shiftId2 !== void 0 ? shiftId2 : getCurrentShift(timezone || "Asia/Kolkata", shiftConfig).shiftId;
|
|
45244
|
+
const shiftNameLower = getShiftName(effectiveShiftId).toLowerCase();
|
|
45245
|
+
if (shiftNameLower.includes("day") || shiftNameLower.includes("morning")) {
|
|
44817
45246
|
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" }) });
|
|
44818
|
-
}
|
|
45247
|
+
}
|
|
45248
|
+
if (shiftNameLower.includes("afternoon") || shiftNameLower.includes("noon") || shiftNameLower.includes("midday")) {
|
|
45249
|
+
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" }) });
|
|
45250
|
+
}
|
|
45251
|
+
if (shiftNameLower.includes("night") || shiftNameLower.includes("evening")) {
|
|
44819
45252
|
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: "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" }) });
|
|
44820
45253
|
}
|
|
45254
|
+
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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
44821
45255
|
}, [getShiftName]);
|
|
44822
45256
|
const formatDate = useCallback((date2) => {
|
|
44823
45257
|
return new Intl.DateTimeFormat("en-US", {
|
|
@@ -44867,13 +45301,27 @@ var LeaderboardDetailView = memo(({
|
|
|
44867
45301
|
});
|
|
44868
45302
|
const displayName = workspace.displayName || getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
44869
45303
|
const navParams = workspace.workspace_uuid ? getWorkspaceNavigationParams(workspace.workspace_uuid, displayName, workspace.line_id) : "";
|
|
44870
|
-
const
|
|
45304
|
+
const contextParams = new URLSearchParams();
|
|
45305
|
+
if (date) {
|
|
45306
|
+
contextParams.set("date", date);
|
|
45307
|
+
}
|
|
45308
|
+
if (shiftId !== void 0) {
|
|
45309
|
+
contextParams.set("shift", shiftId.toString());
|
|
45310
|
+
}
|
|
45311
|
+
contextParams.set("returnTo", encodeURIComponent("/leaderboard"));
|
|
45312
|
+
const contextParamString = contextParams.toString();
|
|
44871
45313
|
if (onWorkspaceClick) {
|
|
44872
|
-
|
|
45314
|
+
const combinedParams = navParams ? `${navParams}&${contextParamString}` : `?${contextParamString}`;
|
|
45315
|
+
const enhancedWorkspace = {
|
|
45316
|
+
...workspace,
|
|
45317
|
+
navParams: combinedParams
|
|
45318
|
+
};
|
|
45319
|
+
onWorkspaceClick(enhancedWorkspace, rank);
|
|
44873
45320
|
} else {
|
|
44874
|
-
|
|
45321
|
+
const combinedParams = navParams ? `${navParams}&${contextParamString}` : `?${contextParamString}`;
|
|
45322
|
+
navigation.navigate(`/workspace/${workspace.workspace_uuid}${combinedParams}`);
|
|
44875
45323
|
}
|
|
44876
|
-
}, [onWorkspaceClick, navigation,
|
|
45324
|
+
}, [onWorkspaceClick, navigation, workspacesLength, date, shiftId]);
|
|
44877
45325
|
const workspaceDisplayData = useMemo(() => {
|
|
44878
45326
|
if (!workspaces) return [];
|
|
44879
45327
|
return workspaces.map((ws) => ({
|
|
@@ -44889,7 +45337,7 @@ var LeaderboardDetailView = memo(({
|
|
|
44889
45337
|
return sortAscending ? effA - effB : effB - effA;
|
|
44890
45338
|
});
|
|
44891
45339
|
}, [workspaceDisplayData, sortAscending]);
|
|
44892
|
-
const loading = workspacesLoading;
|
|
45340
|
+
const loading = workspacesLoading || isShiftConfigLoading;
|
|
44893
45341
|
const error = workspacesError;
|
|
44894
45342
|
const currentDateFormatted = useMemo(() => {
|
|
44895
45343
|
const dateStr = (/* @__PURE__ */ new Date()).toDateString();
|
|
@@ -45734,14 +46182,28 @@ var ShiftsView = ({
|
|
|
45734
46182
|
try {
|
|
45735
46183
|
setLoading(true);
|
|
45736
46184
|
setError(null);
|
|
45737
|
-
const { data:
|
|
46185
|
+
const { data: enabledLines, error: linesError } = await supabase.from("lines").select("id, enable").in("id", lineIds).eq("enable", true);
|
|
46186
|
+
if (linesError) {
|
|
46187
|
+
console.error("Error fetching enabled lines:", linesError);
|
|
46188
|
+
showToast("error", "Error loading lines");
|
|
46189
|
+
setError("Failed to load lines");
|
|
46190
|
+
setLoading(false);
|
|
46191
|
+
return;
|
|
46192
|
+
}
|
|
46193
|
+
const enabledLineIds = (enabledLines || []).map((line) => line.id);
|
|
46194
|
+
if (enabledLineIds.length === 0) {
|
|
46195
|
+
setLineConfigs([]);
|
|
46196
|
+
setLoading(false);
|
|
46197
|
+
return;
|
|
46198
|
+
}
|
|
46199
|
+
const { data: dayShiftOperatingHours, error: dayShiftError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id", enabledLineIds);
|
|
45738
46200
|
if (dayShiftError) {
|
|
45739
46201
|
console.error("Error fetching day shift operating hours:", dayShiftError);
|
|
45740
46202
|
showToast("error", "Error loading day shift data");
|
|
45741
46203
|
setError("Failed to load day shift data");
|
|
45742
46204
|
return;
|
|
45743
46205
|
}
|
|
45744
|
-
const { data: nightShiftOperatingHours, error: nightShiftError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id",
|
|
46206
|
+
const { data: nightShiftOperatingHours, error: nightShiftError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id", enabledLineIds);
|
|
45745
46207
|
if (nightShiftError) {
|
|
45746
46208
|
console.error("Error fetching night shift operating hours:", nightShiftError);
|
|
45747
46209
|
showToast("error", "Error loading night shift data");
|
|
@@ -45764,27 +46226,30 @@ var ShiftsView = ({
|
|
|
45764
46226
|
};
|
|
45765
46227
|
return map;
|
|
45766
46228
|
}, {});
|
|
45767
|
-
setLineConfigs((prev) =>
|
|
45768
|
-
const
|
|
45769
|
-
|
|
45770
|
-
|
|
45771
|
-
|
|
45772
|
-
newConfig
|
|
45773
|
-
|
|
45774
|
-
|
|
45775
|
-
|
|
45776
|
-
|
|
45777
|
-
|
|
45778
|
-
|
|
45779
|
-
|
|
45780
|
-
|
|
45781
|
-
|
|
45782
|
-
|
|
45783
|
-
|
|
45784
|
-
|
|
45785
|
-
|
|
45786
|
-
|
|
45787
|
-
|
|
46229
|
+
setLineConfigs((prev) => {
|
|
46230
|
+
const enabledConfigs = prev.filter((config) => enabledLineIds.includes(config.id));
|
|
46231
|
+
return enabledConfigs.map((config) => {
|
|
46232
|
+
const typedConfig = config;
|
|
46233
|
+
const lineId = typedConfig.id;
|
|
46234
|
+
const newConfig = { ...typedConfig };
|
|
46235
|
+
if (dayShiftHoursMap[lineId]) {
|
|
46236
|
+
newConfig.dayShift = {
|
|
46237
|
+
...newConfig.dayShift,
|
|
46238
|
+
...dayShiftHoursMap[lineId]
|
|
46239
|
+
};
|
|
46240
|
+
}
|
|
46241
|
+
if (nightShiftHoursMap[lineId]) {
|
|
46242
|
+
newConfig.nightShift = {
|
|
46243
|
+
...newConfig.nightShift,
|
|
46244
|
+
...nightShiftHoursMap[lineId]
|
|
46245
|
+
};
|
|
46246
|
+
}
|
|
46247
|
+
if (newConfig.isOpen === void 0) {
|
|
46248
|
+
newConfig.isOpen = getStoredLineState(lineId);
|
|
46249
|
+
}
|
|
46250
|
+
return newConfig;
|
|
46251
|
+
});
|
|
46252
|
+
});
|
|
45788
46253
|
setLoading(false);
|
|
45789
46254
|
} catch (error2) {
|
|
45790
46255
|
console.error("Error fetching shift configurations:", error2);
|
|
@@ -46962,6 +47427,10 @@ var TargetsViewUI = ({
|
|
|
46962
47427
|
savingLines,
|
|
46963
47428
|
saveSuccess,
|
|
46964
47429
|
selectedShift,
|
|
47430
|
+
shiftOptions = [
|
|
47431
|
+
{ id: 0, name: "Day Shift" },
|
|
47432
|
+
{ id: 1, name: "Night Shift" }
|
|
47433
|
+
],
|
|
46965
47434
|
isBulkConfigureOpen,
|
|
46966
47435
|
navItems = [],
|
|
46967
47436
|
currentPathname = "/targets",
|
|
@@ -47014,24 +47483,15 @@ var TargetsViewUI = ({
|
|
|
47014
47483
|
] }) }),
|
|
47015
47484
|
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-auto", children: /* @__PURE__ */ jsxs("div", { className: "px-4 sm:px-6 md:px-8 py-4 sm:py-5 md:py-6", children: [
|
|
47016
47485
|
/* @__PURE__ */ jsx("div", { className: "mb-4 sm:mb-6 bg-gradient-to-r from-blue-50 to-blue-50/50 p-3 sm:p-4 rounded-xl border border-blue-100", children: /* @__PURE__ */ jsx("p", { className: "text-xs sm:text-sm text-blue-700 font-medium text-center sm:text-left", children: "Click on a line to expand and configure individual workspace targets." }) }),
|
|
47017
|
-
/* @__PURE__ */ jsx("div", { className: "mb-4 sm:mb-6 flex justify-center relative", children: /* @__PURE__ */
|
|
47018
|
-
|
|
47019
|
-
|
|
47020
|
-
|
|
47021
|
-
|
|
47022
|
-
|
|
47023
|
-
|
|
47024
|
-
|
|
47025
|
-
|
|
47026
|
-
/* @__PURE__ */ jsx(
|
|
47027
|
-
"button",
|
|
47028
|
-
{
|
|
47029
|
-
onClick: () => onShiftChange(1),
|
|
47030
|
-
className: `flex-1 sm:flex-none px-3 sm:px-4 py-2 text-xs sm:text-sm font-medium rounded-md transition-all ${selectedShift === 1 ? "bg-white text-blue-600 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
47031
|
-
children: "Night Shift"
|
|
47032
|
-
}
|
|
47033
|
-
)
|
|
47034
|
-
] }) }),
|
|
47486
|
+
/* @__PURE__ */ jsx("div", { className: "mb-4 sm:mb-6 flex justify-center relative", children: /* @__PURE__ */ jsx("div", { className: "inline-flex bg-gray-100 p-1 rounded-lg w-full max-w-xl sm:w-auto overflow-x-auto", children: shiftOptions.map((option) => /* @__PURE__ */ jsx(
|
|
47487
|
+
"button",
|
|
47488
|
+
{
|
|
47489
|
+
onClick: () => onShiftChange(option.id),
|
|
47490
|
+
className: `flex-1 sm:flex-none px-3 sm:px-4 py-2 text-xs sm:text-sm font-medium rounded-md transition-all whitespace-nowrap ${selectedShift === option.id ? "bg-white text-blue-600 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
|
|
47491
|
+
children: option.name
|
|
47492
|
+
},
|
|
47493
|
+
option.id
|
|
47494
|
+
)) }) }),
|
|
47035
47495
|
/* @__PURE__ */ jsx("div", { className: "space-y-6", children: Object.entries(lineWorkspaces).map(([lineId, line]) => /* @__PURE__ */ jsxs(
|
|
47036
47496
|
"div",
|
|
47037
47497
|
{
|
|
@@ -47336,7 +47796,7 @@ var TargetsView = ({
|
|
|
47336
47796
|
onSaveChanges
|
|
47337
47797
|
}) => {
|
|
47338
47798
|
const timezone = useAppTimezone();
|
|
47339
|
-
|
|
47799
|
+
useMemo(() => {
|
|
47340
47800
|
return lineIds.reduce((acc, lineId) => ({
|
|
47341
47801
|
...acc,
|
|
47342
47802
|
[lineId]: {
|
|
@@ -47358,12 +47818,7 @@ var TargetsView = ({
|
|
|
47358
47818
|
[lineId]: getStoredLineState2(lineId)
|
|
47359
47819
|
}), {});
|
|
47360
47820
|
});
|
|
47361
|
-
const [allShiftsData, setAllShiftsData] = useState({
|
|
47362
|
-
0: initialLineWorkspaces,
|
|
47363
|
-
// Day shift
|
|
47364
|
-
1: initialLineWorkspaces
|
|
47365
|
-
// Night shift (will be populated on first load)
|
|
47366
|
-
});
|
|
47821
|
+
const [allShiftsData, setAllShiftsData] = useState({});
|
|
47367
47822
|
const [actionIds, setActionIds] = useState(null);
|
|
47368
47823
|
const [savingLines, setSavingLines] = useState(
|
|
47369
47824
|
() => lineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
|
|
@@ -47375,10 +47830,11 @@ var TargetsView = ({
|
|
|
47375
47830
|
const [isBulkConfigureOpen, setIsBulkConfigureOpen] = useState(false);
|
|
47376
47831
|
const [selectedWorkspaces, setSelectedWorkspaces] = useState([]);
|
|
47377
47832
|
const [selectedShift, setSelectedShift] = useState(0);
|
|
47833
|
+
const [shiftOptions, setShiftOptions] = useState([]);
|
|
47378
47834
|
const canSaveTargets = useCanSaveTargets();
|
|
47379
47835
|
const [dbValues, setDbValues] = useState({ 0: {}, 1: {} });
|
|
47380
47836
|
const [userEditedFields, setUserEditedFields] = useState(/* @__PURE__ */ new Set());
|
|
47381
|
-
const lineWorkspaces = allShiftsData[selectedShift] ||
|
|
47837
|
+
const lineWorkspaces = allShiftsData[selectedShift] || {};
|
|
47382
47838
|
const setLineWorkspaces = useCallback((updater) => {
|
|
47383
47839
|
setAllShiftsData((prev) => ({
|
|
47384
47840
|
...prev,
|
|
@@ -47407,12 +47863,28 @@ var TargetsView = ({
|
|
|
47407
47863
|
setIsLoading(true);
|
|
47408
47864
|
try {
|
|
47409
47865
|
const currentDate = getOperationalDate(timezone);
|
|
47866
|
+
const { data: shiftsData, error: shiftsError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name").in("line_id", lineIds);
|
|
47867
|
+
if (shiftsError) {
|
|
47868
|
+
console.warn("[TargetsView] Error fetching shift definitions, falling back to defaults", shiftsError);
|
|
47869
|
+
}
|
|
47870
|
+
const derivedShiftOptions = (shiftsData || []).reduce((acc, row) => {
|
|
47871
|
+
if (acc.some((s) => s.id === row.shift_id)) return acc;
|
|
47872
|
+
acc.push({ id: row.shift_id, name: row.shift_name || `Shift ${row.shift_id}` });
|
|
47873
|
+
return acc;
|
|
47874
|
+
}, []);
|
|
47875
|
+
const effectiveShiftOptions = derivedShiftOptions.length > 0 ? derivedShiftOptions.sort((a, b) => a.id - b.id) : [
|
|
47876
|
+
{ id: 0, name: "Day Shift" },
|
|
47877
|
+
{ id: 1, name: "Night Shift" }
|
|
47878
|
+
];
|
|
47879
|
+
setShiftOptions(effectiveShiftOptions);
|
|
47880
|
+
const defaultShiftId = effectiveShiftOptions[0].id;
|
|
47881
|
+
setSelectedShift(defaultShiftId);
|
|
47410
47882
|
const bulkResponse = await workspaceService.fetchBulkTargets({
|
|
47411
47883
|
companyId,
|
|
47412
47884
|
lineIds,
|
|
47413
47885
|
date: currentDate,
|
|
47414
|
-
shifts:
|
|
47415
|
-
// Fetch
|
|
47886
|
+
shifts: effectiveShiftOptions.map((s) => s.id),
|
|
47887
|
+
// Fetch all configured shifts
|
|
47416
47888
|
includeSkus: skuEnabled,
|
|
47417
47889
|
includeActions: true
|
|
47418
47890
|
});
|
|
@@ -47430,10 +47902,14 @@ var TargetsView = ({
|
|
|
47430
47902
|
packaging: packagingAction.id
|
|
47431
47903
|
};
|
|
47432
47904
|
setActionIds(actionIdsData);
|
|
47433
|
-
const newAllShiftsData = {
|
|
47434
|
-
const newDbValues = {
|
|
47905
|
+
const newAllShiftsData = {};
|
|
47906
|
+
const newDbValues = {};
|
|
47907
|
+
effectiveShiftOptions.forEach((opt) => {
|
|
47908
|
+
newAllShiftsData[opt.id] = {};
|
|
47909
|
+
newDbValues[opt.id] = {};
|
|
47910
|
+
});
|
|
47435
47911
|
Object.entries(data.lines).forEach(([lineId, lineData]) => {
|
|
47436
|
-
|
|
47912
|
+
effectiveShiftOptions.forEach(({ id: shiftId }) => {
|
|
47437
47913
|
const shiftData = lineData.shifts[shiftId.toString()];
|
|
47438
47914
|
if (!shiftData) {
|
|
47439
47915
|
console.warn(`No shift ${shiftId} data for line ${lineId}`);
|
|
@@ -47487,6 +47963,37 @@ var TargetsView = ({
|
|
|
47487
47963
|
newAllShiftsData[shiftId][lineId].workspaces = mappedWorkspaces;
|
|
47488
47964
|
});
|
|
47489
47965
|
});
|
|
47966
|
+
effectiveShiftOptions.forEach(({ id: shiftId }) => {
|
|
47967
|
+
lineIds.forEach((lineId) => {
|
|
47968
|
+
if (!newAllShiftsData[shiftId][lineId]) {
|
|
47969
|
+
const lineData = data.lines[lineId];
|
|
47970
|
+
const shift0Data = newAllShiftsData[0]?.[lineId];
|
|
47971
|
+
const enabledWorkspaces = lineData?.workspaces?.filter((ws) => ws.enable === true) || [];
|
|
47972
|
+
const workspaces = enabledWorkspaces.map((ws) => ({
|
|
47973
|
+
id: ws.id,
|
|
47974
|
+
name: ws.workspace_id,
|
|
47975
|
+
targetPPH: "",
|
|
47976
|
+
targetCycleTime: "",
|
|
47977
|
+
targetDayOutput: "",
|
|
47978
|
+
actionType: "assembly",
|
|
47979
|
+
actionId: actionIdsData.assembly
|
|
47980
|
+
})).sort(
|
|
47981
|
+
(a, b) => a.name.localeCompare(b.name, void 0, { numeric: true })
|
|
47982
|
+
);
|
|
47983
|
+
newAllShiftsData[shiftId][lineId] = {
|
|
47984
|
+
productId: "",
|
|
47985
|
+
shiftStartTime: shift0Data?.shiftStartTime || "08:00",
|
|
47986
|
+
shiftEndTime: shift0Data?.shiftEndTime || "19:00",
|
|
47987
|
+
shiftHours: shift0Data?.shiftHours || 11,
|
|
47988
|
+
breaks: shift0Data?.breaks || [],
|
|
47989
|
+
workspaces,
|
|
47990
|
+
factoryId: shift0Data?.factoryId || lineData?.line_info?.factory_id
|
|
47991
|
+
};
|
|
47992
|
+
newDbValues[shiftId][lineId] = {};
|
|
47993
|
+
console.log(`[TargetsView] Initialized empty data for shift ${shiftId}, line ${lineId}`);
|
|
47994
|
+
}
|
|
47995
|
+
});
|
|
47996
|
+
});
|
|
47490
47997
|
setAllShiftsData(newAllShiftsData);
|
|
47491
47998
|
setDbValues(newDbValues);
|
|
47492
47999
|
console.log("[TargetsView] Successfully loaded all data with bulk endpoint:", {
|
|
@@ -47604,7 +48111,7 @@ var TargetsView = ({
|
|
|
47604
48111
|
setUserEditedFields(/* @__PURE__ */ new Set());
|
|
47605
48112
|
if (dbValues[shiftId] && Object.keys(dbValues[shiftId]).length > 0) {
|
|
47606
48113
|
setAllShiftsData((prev) => {
|
|
47607
|
-
const updatedShiftData = { ...prev[shiftId] };
|
|
48114
|
+
const updatedShiftData = { ...prev[shiftId] || {} };
|
|
47608
48115
|
for (const lineId of Object.keys(updatedShiftData)) {
|
|
47609
48116
|
if (dbValues[shiftId][lineId]) {
|
|
47610
48117
|
updatedShiftData[lineId] = {
|
|
@@ -47633,20 +48140,27 @@ var TargetsView = ({
|
|
|
47633
48140
|
};
|
|
47634
48141
|
const handleActionTypeChange = useCallback((lineId, workspaceId, newActionType) => {
|
|
47635
48142
|
if (!actionIds) return;
|
|
47636
|
-
setLineWorkspaces((prev) =>
|
|
47637
|
-
|
|
47638
|
-
|
|
47639
|
-
|
|
47640
|
-
|
|
47641
|
-
(ws) => ws.id === workspaceId ? {
|
|
47642
|
-
...ws,
|
|
47643
|
-
actionType: newActionType,
|
|
47644
|
-
actionId: actionIds[newActionType]
|
|
47645
|
-
} : ws
|
|
47646
|
-
)
|
|
48143
|
+
setLineWorkspaces((prev) => {
|
|
48144
|
+
const currentLineData = prev?.[lineId];
|
|
48145
|
+
if (!currentLineData?.workspaces) {
|
|
48146
|
+
console.warn(`[handleActionTypeChange] No data for line ${lineId} in current shift`);
|
|
48147
|
+
return prev;
|
|
47647
48148
|
}
|
|
47648
|
-
|
|
47649
|
-
|
|
48149
|
+
return {
|
|
48150
|
+
...prev,
|
|
48151
|
+
[lineId]: {
|
|
48152
|
+
...currentLineData,
|
|
48153
|
+
workspaces: currentLineData.workspaces.map(
|
|
48154
|
+
(ws) => ws.id === workspaceId ? {
|
|
48155
|
+
...ws,
|
|
48156
|
+
actionType: newActionType,
|
|
48157
|
+
actionId: actionIds[newActionType]
|
|
48158
|
+
} : ws
|
|
48159
|
+
)
|
|
48160
|
+
}
|
|
48161
|
+
};
|
|
48162
|
+
});
|
|
48163
|
+
}, [actionIds, setLineWorkspaces]);
|
|
47650
48164
|
const handleSaveLine = useCallback(async (lineId) => {
|
|
47651
48165
|
console.log(`[handleSaveLine] Attempting to save line: ${lineId}`);
|
|
47652
48166
|
if (!canSaveTargets) {
|
|
@@ -47826,6 +48340,7 @@ var TargetsView = ({
|
|
|
47826
48340
|
savingLines,
|
|
47827
48341
|
saveSuccess,
|
|
47828
48342
|
selectedShift,
|
|
48343
|
+
shiftOptions,
|
|
47829
48344
|
isBulkConfigureOpen,
|
|
47830
48345
|
navItems: [],
|
|
47831
48346
|
currentPathname: "/targets",
|
|
@@ -47957,12 +48472,10 @@ var WorkspaceDetailView = ({
|
|
|
47957
48472
|
const today = new Date((/* @__PURE__ */ new Date()).toLocaleString("en-US", { timeZone: timezone }));
|
|
47958
48473
|
const [selectedMonth, setSelectedMonth] = useState(today.getMonth());
|
|
47959
48474
|
const [selectedYear, setSelectedYear] = useState(today.getFullYear());
|
|
47960
|
-
const [selectedShift, setSelectedShift] = useState(
|
|
48475
|
+
const [selectedShift, setSelectedShift] = useState(0);
|
|
47961
48476
|
useEffect(() => {
|
|
47962
|
-
if (parsedShiftId
|
|
47963
|
-
setSelectedShift(
|
|
47964
|
-
} else if (parsedShiftId === 0) {
|
|
47965
|
-
setSelectedShift("day");
|
|
48477
|
+
if (parsedShiftId !== void 0) {
|
|
48478
|
+
setSelectedShift(parsedShiftId);
|
|
47966
48479
|
}
|
|
47967
48480
|
}, [parsedShiftId]);
|
|
47968
48481
|
const isHistoricView = Boolean(date && parsedShiftId !== void 0);
|
|
@@ -47974,6 +48487,13 @@ var WorkspaceDetailView = ({
|
|
|
47974
48487
|
const dashboardConfig = useDashboardConfig();
|
|
47975
48488
|
const isClipsEnabled = dashboardConfig?.clipsConfig?.enabled ?? true;
|
|
47976
48489
|
dashboardConfig?.supervisorConfig?.enabled || false;
|
|
48490
|
+
const effectiveLineId = lineId || selectedLineId;
|
|
48491
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(effectiveLineId);
|
|
48492
|
+
const calculatedOperationalDate = useMemo(() => {
|
|
48493
|
+
if (isShiftConfigLoading || !shiftConfig) return null;
|
|
48494
|
+
const currentShift = getCurrentShift(timezone, shiftConfig);
|
|
48495
|
+
return currentShift.date;
|
|
48496
|
+
}, [isShiftConfigLoading, shiftConfig, timezone]);
|
|
47977
48497
|
const {
|
|
47978
48498
|
workspace: workspaceHealth,
|
|
47979
48499
|
loading: healthLoading,
|
|
@@ -48034,7 +48554,9 @@ var WorkspaceDetailView = ({
|
|
|
48034
48554
|
} = useHistoricWorkspaceMetrics(
|
|
48035
48555
|
workspaceId || "",
|
|
48036
48556
|
date || "",
|
|
48037
|
-
parsedShiftId
|
|
48557
|
+
parsedShiftId,
|
|
48558
|
+
{ shiftConfig, enabled: !isShiftConfigLoading }
|
|
48559
|
+
// Pass dynamic shift config and enabled flag
|
|
48038
48560
|
);
|
|
48039
48561
|
const {
|
|
48040
48562
|
metrics: liveMetrics,
|
|
@@ -48042,11 +48564,13 @@ var WorkspaceDetailView = ({
|
|
|
48042
48564
|
error: liveError
|
|
48043
48565
|
} = useWorkspaceDetailedMetrics(
|
|
48044
48566
|
workspaceId || "",
|
|
48045
|
-
getOperationalDate(timezone),
|
|
48046
|
-
void 0
|
|
48567
|
+
calculatedOperationalDate || getOperationalDate(timezone),
|
|
48568
|
+
void 0,
|
|
48569
|
+
{ shiftConfig, enabled: !isShiftConfigLoading }
|
|
48570
|
+
// Pass the dynamic shift config here and enabled flag
|
|
48047
48571
|
);
|
|
48048
48572
|
const workspace = isHistoricView ? historicMetrics : liveMetrics;
|
|
48049
|
-
const loading = isHistoricView ? historicLoading : liveLoading;
|
|
48573
|
+
const loading = (isHistoricView ? historicLoading : liveLoading) || isShiftConfigLoading;
|
|
48050
48574
|
const error = isHistoricView ? historicError : liveError;
|
|
48051
48575
|
const { supervisorName } = useLineSupervisor(workspace?.line_id || lineId);
|
|
48052
48576
|
useEffect(() => {
|
|
@@ -48066,7 +48590,7 @@ var WorkspaceDetailView = ({
|
|
|
48066
48590
|
}, [isClipsEnabled, activeTab]);
|
|
48067
48591
|
useEffect(() => {
|
|
48068
48592
|
if (liveMetrics && !date && !shift) {
|
|
48069
|
-
const currentDate = getOperationalDate(timezone);
|
|
48593
|
+
const currentDate = calculatedOperationalDate || getOperationalDate(timezone);
|
|
48070
48594
|
if (liveMetrics.date !== currentDate) {
|
|
48071
48595
|
setUsingFallbackData(true);
|
|
48072
48596
|
if (activeTab !== "monthly_history") {
|
|
@@ -48076,7 +48600,7 @@ var WorkspaceDetailView = ({
|
|
|
48076
48600
|
setUsingFallbackData(false);
|
|
48077
48601
|
}
|
|
48078
48602
|
}
|
|
48079
|
-
}, [liveMetrics, date, shift, activeTab]);
|
|
48603
|
+
}, [liveMetrics, date, shift, activeTab, calculatedOperationalDate]);
|
|
48080
48604
|
useMemo(() => {
|
|
48081
48605
|
if (isHistoricView && date) {
|
|
48082
48606
|
try {
|
|
@@ -48084,11 +48608,11 @@ var WorkspaceDetailView = ({
|
|
|
48084
48608
|
return date;
|
|
48085
48609
|
} catch (e) {
|
|
48086
48610
|
console.error("Error parsing historic date:", e);
|
|
48087
|
-
return getOperationalDate(timezone);
|
|
48611
|
+
return calculatedOperationalDate || getOperationalDate(timezone);
|
|
48088
48612
|
}
|
|
48089
48613
|
}
|
|
48090
|
-
return getOperationalDate(timezone);
|
|
48091
|
-
}, [isHistoricView, date]);
|
|
48614
|
+
return calculatedOperationalDate || getOperationalDate(timezone);
|
|
48615
|
+
}, [isHistoricView, date, calculatedOperationalDate, timezone]);
|
|
48092
48616
|
const handleMonthlyDataLoaded = useCallback((data) => {
|
|
48093
48617
|
console.log("[handleMonthlyDataLoaded] Received data:", {
|
|
48094
48618
|
dataLength: data?.length,
|
|
@@ -48112,10 +48636,8 @@ var WorkspaceDetailView = ({
|
|
|
48112
48636
|
if (!dayEntry) {
|
|
48113
48637
|
dayEntry = {
|
|
48114
48638
|
date: dateObj,
|
|
48115
|
-
|
|
48116
|
-
//
|
|
48117
|
-
nightShift: null
|
|
48118
|
-
// Start with null instead of zeros
|
|
48639
|
+
shifts: {}
|
|
48640
|
+
// Multi-shift structure: Record<number, CalendarShiftData>
|
|
48119
48641
|
};
|
|
48120
48642
|
dayDataMap.set(dateKey, dayEntry);
|
|
48121
48643
|
}
|
|
@@ -48127,19 +48649,14 @@ var WorkspaceDetailView = ({
|
|
|
48127
48649
|
pphThreshold: metric.pph_threshold || 0,
|
|
48128
48650
|
idealOutput: metric.ideal_output || 0,
|
|
48129
48651
|
rank: metric.workspace_rank || 0,
|
|
48130
|
-
idleTime: metric.idle_time || 0
|
|
48652
|
+
idleTime: metric.idle_time || 0,
|
|
48653
|
+
hasData: true
|
|
48131
48654
|
};
|
|
48132
|
-
|
|
48133
|
-
dayEntry.dayShift = shiftData;
|
|
48134
|
-
} else {
|
|
48135
|
-
dayEntry.nightShift = shiftData;
|
|
48136
|
-
}
|
|
48655
|
+
dayEntry.shifts[metric.shift_id] = shiftData;
|
|
48137
48656
|
});
|
|
48138
|
-
const processedData = Array.from(dayDataMap.values()).filter((entry) =>
|
|
48657
|
+
const processedData = Array.from(dayDataMap.values()).filter((entry) => Object.keys(entry.shifts).length > 0).map((entry) => ({
|
|
48139
48658
|
date: entry.date,
|
|
48140
|
-
|
|
48141
|
-
dayShift: entry.dayShift || { efficiency: 0, output: 0, cycleTime: 0, pph: 0, pphThreshold: 0, idealOutput: 0, rank: 0, idleTime: 0 },
|
|
48142
|
-
nightShift: entry.nightShift || { efficiency: 0, output: 0, cycleTime: 0, pph: 0, pphThreshold: 0, idealOutput: 0, rank: 0, idleTime: 0 }
|
|
48659
|
+
shifts: entry.shifts
|
|
48143
48660
|
}));
|
|
48144
48661
|
console.log(`[handleMonthlyDataLoaded] Transformed data for calendar:`, {
|
|
48145
48662
|
count: processedData.length,
|
|
@@ -48147,7 +48664,6 @@ var WorkspaceDetailView = ({
|
|
|
48147
48664
|
});
|
|
48148
48665
|
setMonthlyData(processedData);
|
|
48149
48666
|
}, []);
|
|
48150
|
-
const effectiveLineId = lineId || selectedLineId;
|
|
48151
48667
|
const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
|
|
48152
48668
|
const shouldShowCycleTimeChart = showCycleTimeChart ?? formattedWorkspaceName.startsWith("FINAL ASSY");
|
|
48153
48669
|
const handleBackNavigation = () => {
|
|
@@ -48168,7 +48684,7 @@ var WorkspaceDetailView = ({
|
|
|
48168
48684
|
if (onNavigate) {
|
|
48169
48685
|
const params = new URLSearchParams();
|
|
48170
48686
|
params.set("fromMonthly", "true");
|
|
48171
|
-
params.set("shift", selectedShift
|
|
48687
|
+
params.set("shift", selectedShift.toString());
|
|
48172
48688
|
if (effectiveLineId) {
|
|
48173
48689
|
params.set("lineId", effectiveLineId);
|
|
48174
48690
|
}
|
|
@@ -48180,7 +48696,7 @@ var WorkspaceDetailView = ({
|
|
|
48180
48696
|
if (onNavigate) {
|
|
48181
48697
|
const params = new URLSearchParams();
|
|
48182
48698
|
params.set("fromMonthly", "true");
|
|
48183
|
-
params.set("shift", selectedShift
|
|
48699
|
+
params.set("shift", selectedShift.toString());
|
|
48184
48700
|
if (effectiveLineId) {
|
|
48185
48701
|
params.set("lineId", effectiveLineId);
|
|
48186
48702
|
}
|
|
@@ -48194,10 +48710,15 @@ var WorkspaceDetailView = ({
|
|
|
48194
48710
|
}
|
|
48195
48711
|
};
|
|
48196
48712
|
const getShiftIcon = (shiftType) => {
|
|
48197
|
-
|
|
48713
|
+
const shiftTypeLower = shiftType?.toLowerCase() || "";
|
|
48714
|
+
if (shiftTypeLower.includes("day") || shiftTypeLower.includes("morning")) {
|
|
48198
48715
|
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" }) });
|
|
48199
|
-
} else {
|
|
48716
|
+
} else if (shiftTypeLower.includes("afternoon") || shiftTypeLower.includes("noon") || shiftTypeLower.includes("midday")) {
|
|
48717
|
+
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" }) });
|
|
48718
|
+
} else if (shiftTypeLower.includes("night") || shiftTypeLower.includes("evening")) {
|
|
48200
48719
|
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: "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" }) });
|
|
48720
|
+
} else {
|
|
48721
|
+
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 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) });
|
|
48201
48722
|
}
|
|
48202
48723
|
};
|
|
48203
48724
|
if (loading) {
|
|
@@ -48374,10 +48895,7 @@ var WorkspaceDetailView = ({
|
|
|
48374
48895
|
] }),
|
|
48375
48896
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
48376
48897
|
/* @__PURE__ */ jsx("div", { className: "text-blue-600", children: getShiftIcon(workspace.shift_type) }),
|
|
48377
|
-
/* @__PURE__ */
|
|
48378
|
-
workspace.shift_type,
|
|
48379
|
-
" Shift"
|
|
48380
|
-
] })
|
|
48898
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm md:text-base font-medium text-blue-600", children: workspace.shift_type })
|
|
48381
48899
|
] })
|
|
48382
48900
|
] }) })
|
|
48383
48901
|
] }),
|
|
@@ -48444,7 +48962,7 @@ var WorkspaceDetailView = ({
|
|
|
48444
48962
|
monthlyData,
|
|
48445
48963
|
selectedMonth,
|
|
48446
48964
|
selectedYear,
|
|
48447
|
-
selectedShift
|
|
48965
|
+
selectedShiftId: selectedShift
|
|
48448
48966
|
}
|
|
48449
48967
|
) })
|
|
48450
48968
|
] })
|
|
@@ -48713,15 +49231,16 @@ var WorkspaceDetailView = ({
|
|
|
48713
49231
|
month: selectedMonth,
|
|
48714
49232
|
year: selectedYear,
|
|
48715
49233
|
workspaceId,
|
|
48716
|
-
selectedShift,
|
|
49234
|
+
selectedShiftId: selectedShift,
|
|
48717
49235
|
monthlyDataLoading,
|
|
48718
|
-
|
|
49236
|
+
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
49237
|
+
onDateSelect: (selectedDate, shiftId) => {
|
|
48719
49238
|
if (onDateSelect) {
|
|
48720
|
-
onDateSelect(selectedDate,
|
|
49239
|
+
onDateSelect(selectedDate, shiftId);
|
|
48721
49240
|
} else if (onNavigate) {
|
|
48722
49241
|
const params = new URLSearchParams();
|
|
48723
49242
|
params.set("date", selectedDate);
|
|
48724
|
-
params.set("shift",
|
|
49243
|
+
params.set("shift", shiftId.toString());
|
|
48725
49244
|
params.set("fromMonthly", "true");
|
|
48726
49245
|
if (effectiveLineId) {
|
|
48727
49246
|
params.set("lineId", effectiveLineId);
|
|
@@ -48744,6 +49263,7 @@ var WorkspaceDetailView = ({
|
|
|
48744
49263
|
workspaceId,
|
|
48745
49264
|
workspaceName: formattedWorkspaceName,
|
|
48746
49265
|
date,
|
|
49266
|
+
lineId: effectiveLineId,
|
|
48747
49267
|
shift,
|
|
48748
49268
|
totalOutput: workspace?.total_actions,
|
|
48749
49269
|
className: "h-[calc(100vh-10rem)]"
|
|
@@ -48900,6 +49420,13 @@ var SKUManagementView = () => {
|
|
|
48900
49420
|
var useWorkspaceHealth = (options) => {
|
|
48901
49421
|
const supabase = useSupabase();
|
|
48902
49422
|
const databaseConfig = useDatabaseConfig();
|
|
49423
|
+
const entityConfig = useEntityConfig();
|
|
49424
|
+
const configuredLineIds = useMemo(() => getConfiguredLineIds(entityConfig), [entityConfig]);
|
|
49425
|
+
const firstConfiguredLineId = configuredLineIds[0];
|
|
49426
|
+
const isFactoryView = !options.lineId || options.lineId === (entityConfig?.factoryViewId || "factory");
|
|
49427
|
+
const effectiveLineIdForShiftConfig = isFactoryView ? firstConfiguredLineId : options.lineId;
|
|
49428
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(effectiveLineIdForShiftConfig);
|
|
49429
|
+
const timezone = useAppTimezone() || "UTC";
|
|
48903
49430
|
const [workspaces, setWorkspaces] = useState([]);
|
|
48904
49431
|
const [summary, setSummary] = useState({
|
|
48905
49432
|
totalWorkspaces: 0,
|
|
@@ -48946,6 +49473,14 @@ var useWorkspaceHealth = (options) => {
|
|
|
48946
49473
|
}, []);
|
|
48947
49474
|
const fetchWorkspacesHealth = useCallback(async () => {
|
|
48948
49475
|
if (isFetchingRef.current) return;
|
|
49476
|
+
if (isShiftConfigLoading) {
|
|
49477
|
+
console.log("[useWorkspaceHealth] \u23F3 Waiting for shift config to load");
|
|
49478
|
+
return;
|
|
49479
|
+
}
|
|
49480
|
+
if (!shiftConfig) {
|
|
49481
|
+
console.warn("[useWorkspaceHealth] \u26A0\uFE0F Shift config is null, waiting for it to load");
|
|
49482
|
+
return;
|
|
49483
|
+
}
|
|
48949
49484
|
if (!options.companyId) {
|
|
48950
49485
|
setWorkspaces([]);
|
|
48951
49486
|
setSummary(computeSummary([]));
|
|
@@ -48956,9 +49491,16 @@ var useWorkspaceHealth = (options) => {
|
|
|
48956
49491
|
isFetchingRef.current = true;
|
|
48957
49492
|
setLoading(true);
|
|
48958
49493
|
setError(null);
|
|
49494
|
+
console.log("[useWorkspaceHealth] \u{1F680} Fetching health status with shift config:", {
|
|
49495
|
+
lineId: options.lineId,
|
|
49496
|
+
hasShiftConfig: !!shiftConfig,
|
|
49497
|
+
shiftId: shiftConfig?.shifts?.[0]?.shiftId
|
|
49498
|
+
});
|
|
48959
49499
|
const workspacesWithStatus = await workspaceHealthService.getWorkspaceHealthStatus({
|
|
48960
49500
|
lineId: options.lineId,
|
|
48961
|
-
companyId: options.companyId
|
|
49501
|
+
companyId: options.companyId,
|
|
49502
|
+
shiftConfig,
|
|
49503
|
+
timezone
|
|
48962
49504
|
});
|
|
48963
49505
|
setWorkspaces(workspacesWithStatus);
|
|
48964
49506
|
setSummary(computeSummary(workspacesWithStatus));
|
|
@@ -48970,7 +49512,7 @@ var useWorkspaceHealth = (options) => {
|
|
|
48970
49512
|
setLoading(false);
|
|
48971
49513
|
isFetchingRef.current = false;
|
|
48972
49514
|
}
|
|
48973
|
-
}, [options.companyId, options.lineId, computeSummary]);
|
|
49515
|
+
}, [options.companyId, options.lineId, computeSummary, shiftConfig, isShiftConfigLoading, timezone]);
|
|
48974
49516
|
useEffect(() => {
|
|
48975
49517
|
fetchWorkspacesHealth();
|
|
48976
49518
|
}, [fetchWorkspacesHealth]);
|
|
@@ -49010,9 +49552,12 @@ var useWorkspaceHealth = (options) => {
|
|
|
49010
49552
|
return {
|
|
49011
49553
|
workspaces,
|
|
49012
49554
|
summary,
|
|
49013
|
-
loading,
|
|
49555
|
+
loading: loading || isShiftConfigLoading || !shiftConfig,
|
|
49014
49556
|
error,
|
|
49015
|
-
refetch: fetchWorkspacesHealth
|
|
49557
|
+
refetch: fetchWorkspacesHealth,
|
|
49558
|
+
// Expose shift config so consumers can pass it to child components
|
|
49559
|
+
shiftConfig,
|
|
49560
|
+
isShiftConfigLoading
|
|
49016
49561
|
};
|
|
49017
49562
|
};
|
|
49018
49563
|
var STATUS_COLORS = {
|
|
@@ -49211,7 +49756,8 @@ var formatTimeRange = (start, end, timezone) => {
|
|
|
49211
49756
|
var WorkspaceUptimeDetailModal = ({
|
|
49212
49757
|
workspace,
|
|
49213
49758
|
isOpen,
|
|
49214
|
-
onClose
|
|
49759
|
+
onClose,
|
|
49760
|
+
shiftConfig: passedShiftConfig
|
|
49215
49761
|
}) => {
|
|
49216
49762
|
const timezone = useAppTimezone() || "UTC";
|
|
49217
49763
|
const logsContainerRef = useRef(null);
|
|
@@ -49225,7 +49771,12 @@ var WorkspaceUptimeDetailModal = ({
|
|
|
49225
49771
|
workspaceId: workspace?.workspace_id,
|
|
49226
49772
|
companyId: workspace?.company_id,
|
|
49227
49773
|
enabled: isOpen && Boolean(workspace?.workspace_id && workspace?.company_id),
|
|
49228
|
-
refreshInterval: 6e4
|
|
49774
|
+
refreshInterval: 6e4,
|
|
49775
|
+
lineId: workspace?.line_id,
|
|
49776
|
+
// Pass shift config from parent if available - avoids duplicate DB queries
|
|
49777
|
+
// and ensures consistent shift timing across the view
|
|
49778
|
+
shiftConfig: passedShiftConfig || void 0,
|
|
49779
|
+
timezone
|
|
49229
49780
|
});
|
|
49230
49781
|
useEffect(() => {
|
|
49231
49782
|
if (!isOpen || !workspace) return;
|
|
@@ -49412,32 +49963,48 @@ var WorkspaceHealthView = ({
|
|
|
49412
49963
|
}) => {
|
|
49413
49964
|
const router = useRouter();
|
|
49414
49965
|
const [groupBy, setGroupBy] = useState("line");
|
|
49966
|
+
const entityConfig = useEntityConfig();
|
|
49967
|
+
const configuredLineIds = useMemo(() => getConfiguredLineIds(entityConfig), [entityConfig]);
|
|
49968
|
+
const firstConfiguredLineId = configuredLineIds[0];
|
|
49969
|
+
const factoryViewId = entityConfig?.factoryViewId || "factory";
|
|
49970
|
+
const isFactoryView = !lineId || lineId === factoryViewId;
|
|
49971
|
+
const effectiveLineId = isFactoryView ? firstConfiguredLineId : lineId;
|
|
49415
49972
|
const timezone = useAppTimezone();
|
|
49973
|
+
const { shiftConfig, isLoading: isShiftConfigLoading } = useDynamicShiftConfig(effectiveLineId);
|
|
49416
49974
|
const [selectedWorkspace, setSelectedWorkspace] = useState(null);
|
|
49417
|
-
const
|
|
49418
|
-
const
|
|
49419
|
-
const
|
|
49420
|
-
const shiftType =
|
|
49975
|
+
const effectiveTimezone = timezone || "UTC";
|
|
49976
|
+
const currentShiftDetails = getCurrentShift(effectiveTimezone, shiftConfig);
|
|
49977
|
+
const operationalDate = currentShiftDetails.date;
|
|
49978
|
+
const shiftType = (currentShiftDetails.shiftName || "Day").replace(/ Shift$/i, "");
|
|
49421
49979
|
const formatDate = (date) => {
|
|
49422
49980
|
const d = new Date(date);
|
|
49423
49981
|
return d.toLocaleDateString("en-IN", {
|
|
49424
49982
|
month: "long",
|
|
49425
49983
|
day: "numeric",
|
|
49426
49984
|
year: "numeric",
|
|
49427
|
-
timeZone:
|
|
49985
|
+
timeZone: effectiveTimezone
|
|
49428
49986
|
});
|
|
49429
49987
|
};
|
|
49430
|
-
const getShiftIcon = (
|
|
49431
|
-
|
|
49988
|
+
const getShiftIcon = () => {
|
|
49989
|
+
const shiftName = (currentShiftDetails.shiftName || "").toLowerCase();
|
|
49990
|
+
if (shiftName.includes("night") || shiftName.includes("evening") || currentShiftDetails.shiftId === 1) {
|
|
49991
|
+
return /* @__PURE__ */ jsx(Moon, { className: "h-4 w-4" });
|
|
49992
|
+
}
|
|
49993
|
+
if (shiftName.includes("afternoon") || shiftName.includes("noon") || shiftName.includes("midday")) {
|
|
49994
|
+
return /* @__PURE__ */ jsx(Sun, { className: "h-4 w-4" });
|
|
49995
|
+
}
|
|
49996
|
+
return /* @__PURE__ */ jsx(Sun, { className: "h-4 w-4" });
|
|
49432
49997
|
};
|
|
49433
49998
|
const {
|
|
49434
49999
|
workspaces,
|
|
49435
50000
|
summary,
|
|
49436
50001
|
loading,
|
|
49437
50002
|
error,
|
|
49438
|
-
refetch
|
|
50003
|
+
refetch,
|
|
50004
|
+
shiftConfig: loadedShiftConfig
|
|
50005
|
+
// Get shift config from the hook to pass to modal
|
|
49439
50006
|
} = useWorkspaceHealth({
|
|
49440
|
-
lineId,
|
|
50007
|
+
lineId: effectiveLineId,
|
|
49441
50008
|
companyId,
|
|
49442
50009
|
enableRealtime: true,
|
|
49443
50010
|
refreshInterval: 1e4
|
|
@@ -49499,7 +50066,7 @@ var WorkspaceHealthView = ({
|
|
|
49499
50066
|
if (percentage >= 90) return "text-yellow-600 dark:text-yellow-400";
|
|
49500
50067
|
return "text-red-600 dark:text-red-400";
|
|
49501
50068
|
};
|
|
49502
|
-
if (loading && !summary) {
|
|
50069
|
+
if (loading && !summary || isShiftConfigLoading) {
|
|
49503
50070
|
return /* @__PURE__ */ jsx("div", { className: "min-h-screen bg-gray-50 dark:bg-gray-900 p-4", children: /* @__PURE__ */ jsx(LoadingState, {}) });
|
|
49504
50071
|
}
|
|
49505
50072
|
if (error) {
|
|
@@ -49609,7 +50176,7 @@ var WorkspaceHealthView = ({
|
|
|
49609
50176
|
/* @__PURE__ */ jsx("span", { className: "text-xs sm:text-sm md:text-base font-medium text-blue-600", children: formatDate(operationalDate) }),
|
|
49610
50177
|
/* @__PURE__ */ jsx("div", { className: "hidden sm:block w-px h-4 bg-blue-300" }),
|
|
49611
50178
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
49612
|
-
/* @__PURE__ */ jsx("div", { className: "text-blue-600", children: getShiftIcon(
|
|
50179
|
+
/* @__PURE__ */ jsx("div", { className: "text-blue-600", children: getShiftIcon() }),
|
|
49613
50180
|
/* @__PURE__ */ jsxs("span", { className: "text-xs sm:text-sm md:text-base font-medium text-blue-600", children: [
|
|
49614
50181
|
shiftType,
|
|
49615
50182
|
" Shift"
|
|
@@ -49697,7 +50264,8 @@ var WorkspaceHealthView = ({
|
|
|
49697
50264
|
{
|
|
49698
50265
|
workspace: selectedWorkspace,
|
|
49699
50266
|
isOpen: Boolean(selectedWorkspace),
|
|
49700
|
-
onClose: handleCloseDetails
|
|
50267
|
+
onClose: handleCloseDetails,
|
|
50268
|
+
shiftConfig: loadedShiftConfig
|
|
49701
50269
|
}
|
|
49702
50270
|
)
|
|
49703
50271
|
] });
|
|
@@ -51734,25 +52302,15 @@ var TeamManagementView_default = TeamManagementView;
|
|
|
51734
52302
|
function BottleneckClipsView({
|
|
51735
52303
|
workspaceId: propWorkspaceId,
|
|
51736
52304
|
workspaceName: propWorkspaceName,
|
|
52305
|
+
lineId: propLineId,
|
|
51737
52306
|
date: propDate,
|
|
51738
52307
|
shift: propShift,
|
|
51739
52308
|
totalOutput: propTotalOutput
|
|
51740
52309
|
}) {
|
|
51741
52310
|
const router = useRouter();
|
|
51742
|
-
const dashboardConfig = useDashboardConfig();
|
|
51743
|
-
const timezone = useAppTimezone();
|
|
51744
52311
|
const workspaceId = propWorkspaceId || router.query.workspaceId;
|
|
51745
52312
|
const workspaceName = propWorkspaceName || router.query.workspaceName || "Workstation";
|
|
51746
|
-
const
|
|
51747
|
-
if (propDate) return propDate;
|
|
51748
|
-
return getOperationalDate(timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC");
|
|
51749
|
-
}, [propDate, timezone, dashboardConfig]);
|
|
51750
|
-
const currentShift = useMemo(() => {
|
|
51751
|
-
if (propShift !== void 0) return propShift;
|
|
51752
|
-
const tz = timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC";
|
|
51753
|
-
const shiftResult = getCurrentShift(tz, dashboardConfig?.shiftConfig);
|
|
51754
|
-
return shiftResult.shiftId;
|
|
51755
|
-
}, [propShift, dashboardConfig, timezone]);
|
|
52313
|
+
const lineId = propLineId || router.query.lineId;
|
|
51756
52314
|
if (!workspaceId) {
|
|
51757
52315
|
return /* @__PURE__ */ jsx(LoadingPage_default, { message: "Loading workspace data..." });
|
|
51758
52316
|
}
|
|
@@ -51801,8 +52359,9 @@ function BottleneckClipsView({
|
|
|
51801
52359
|
{
|
|
51802
52360
|
workspaceId,
|
|
51803
52361
|
workspaceName,
|
|
51804
|
-
|
|
51805
|
-
|
|
52362
|
+
lineId,
|
|
52363
|
+
date: propDate,
|
|
52364
|
+
shift: propShift,
|
|
51806
52365
|
totalOutput: propTotalOutput,
|
|
51807
52366
|
className: "h-full"
|
|
51808
52367
|
}
|
|
@@ -53268,4 +53827,4 @@ function shuffleArray(array) {
|
|
|
53268
53827
|
return shuffled;
|
|
53269
53828
|
}
|
|
53270
53829
|
|
|
53271
|
-
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, CroppedHlsVideoPlayer, 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_MAP_VIEW_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, DiagnosisVideoModal, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, InvitationService, 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, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlayPauseIndicator, 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, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UserManagementService, 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, createInvitationService, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getNextUpdateInterval, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isSafari, 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, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|
|
53830
|
+
export { ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ClipFilterProvider, CompactWorkspaceHealthCard, CongratulationsOverlay, CroppedHlsVideoPlayer, 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_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, 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, DiagnosisVideoModal, EmptyStateMessage, EncouragementOverlay, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, InlineEditableText, InteractiveOnboardingTour, InvitationService, 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, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlayPauseIndicator, 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, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UserManagementService, 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, createInvitationService, createLinesService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateTimeInZone, formatISTDate, formatIdleTime, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAnonClient, getAvailableShiftIds, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getNextUpdateInterval, getOperationalDate, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isLegacyConfiguration, isPrefetchError, isSafari, 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, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useMessages, useMetrics, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|