@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.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 getCurrentShift = (timezone, shiftConfig, now2 = /* @__PURE__ */ new Date()) => {
504
- const dayShiftStartStr = shiftConfig?.dayShift?.startTime || DEFAULT_DAY_SHIFT_START;
505
- const nightShiftStartStr = shiftConfig?.nightShift?.startTime || DEFAULT_NIGHT_SHIFT_START;
506
- const dayShiftId = shiftConfig?.dayShift?.id ?? 0;
507
- const nightShiftId = shiftConfig?.nightShift?.id ?? 1;
508
- const dayShiftStartMinutes = parseTimeToMinutes(dayShiftStartStr);
509
- const nightShiftStartMinutes = parseTimeToMinutes(nightShiftStartStr);
510
- const effectiveDayStart = !isNaN(dayShiftStartMinutes) ? dayShiftStartMinutes : parseTimeToMinutes(DEFAULT_DAY_SHIFT_START);
511
- const effectiveNightStart = !isNaN(nightShiftStartMinutes) ? nightShiftStartMinutes : parseTimeToMinutes(DEFAULT_NIGHT_SHIFT_START);
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 currentHour = zonedNow.getHours();
514
- const currentMinutes = zonedNow.getMinutes();
515
- const currentTotalMinutes = currentHour * 60 + currentMinutes;
516
- const operationalDate = getOperationalDate(timezone, zonedNow, dayShiftStartStr);
517
- let determinedShiftId;
518
- if (effectiveDayStart < effectiveNightStart) {
519
- if (currentTotalMinutes >= effectiveDayStart && currentTotalMinutes < effectiveNightStart) {
520
- determinedShiftId = dayShiftId;
521
- } else {
522
- determinedShiftId = nightShiftId;
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
- } else {
525
- if (currentTotalMinutes >= effectiveDayStart || currentTotalMinutes < effectiveNightStart) {
526
- determinedShiftId = dayShiftId;
527
- } else {
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
- return { shiftId: determinedShiftId, date: operationalDate };
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 dayShiftStartMinutes = parseTimeToMinutes(dayShiftStartStr);
538
- const nightShiftStartMinutes = parseTimeToMinutes(nightShiftStartStr);
539
- if (isNaN(dayShiftStartMinutes) || isNaN(nightShiftStartMinutes)) {
540
- return false;
541
- }
542
- const transitionTimes = [dayShiftStartMinutes, nightShiftStartMinutes];
543
- const zonedNow = toZonedTime(now2, timezone);
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
- let isAfter = false;
559
- if (lowerBoundAfter < upperBoundAfter) {
560
- isAfter = currentTotalMinutes >= lowerBoundAfter && currentTotalMinutes < upperBoundAfter;
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: [shiftConfig.dayShift?.id ?? 0, shiftConfig.nightShift?.id ?? 1]
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 { shiftId, date } = getCurrentShift(timezone, shiftConfig);
2139
- const dayShiftId = shiftConfig?.dayShift?.id ?? 0;
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 defaultNightStart = "18:00";
2144
- const defaultNightEnd = "06:00";
2145
- const shiftStartStr = isDayShift ? shiftConfig?.dayShift?.startTime || defaultDayStart : shiftConfig?.nightShift?.startTime || defaultNightStart;
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 timezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
2328
- const shiftConfig = dashboardConfig?.shiftConfig;
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 timezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "UTC";
2574
- const shiftConfig = dashboardConfig?.shiftConfig;
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(timezone, shiftConfig);
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
- timezone
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 === 0 || id3 === 1;
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 shiftConfig = useShiftConfig();
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 defaultTimezone = dateTimeConfig.defaultTimezone;
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 || "UTC");
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 shiftConfig = useShiftConfig();
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 currentShift = getCurrentShift(
7454
- dateTimeConfig.defaultTimezone || "Asia/Kolkata",
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
- setMetrics(data.metrics || null);
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 shiftConfig = useShiftConfig();
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
- setLoading(false);
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 shiftConfig = useShiftConfig();
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 shiftConfig = useShiftConfig();
7822
- const defaultTimezone = dateTimeConfig?.defaultTimezone || "UTC";
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 isFactoryView = currentLineIdToUse === (entityConfig.factoryViewId || "factory");
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 = isFactoryView ? `line_ids=${targetLineIds.join(",")}` : `line_id=${targetLineIds[0]}`;
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 useLineShiftConfig = (lineId, fallbackConfig) => {
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 defaultTimezone = dateTimeConfig.defaultTimezone;
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(defaultTimezone, shiftConfig);
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
- }, [defaultTimezone, shiftConfig, entityConfig, supabase]);
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(defaultTimezone);
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, defaultTimezone, shiftConfig]);
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 { shiftConfig: dynamicShiftConfig } = useDynamicShiftConfig(lineId);
8368
- const shiftConfig = dynamicShiftConfig;
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 currentShift = useMemo(() => getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig), [dateTimeConfig.defaultTimezone, shiftConfig]);
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 timezone = useAppTimezone();
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
- if (!initialized) {
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 shiftConfig = useShiftConfig();
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 getCurrentShift2 = (currentMinutes, dayStart, nightStart) => {
9870
- const dayStartMinutes = parseTimeToMinutes2(dayStart);
9871
- const nightStartMinutes = parseTimeToMinutes2(nightStart);
9872
- if (nightStartMinutes < dayStartMinutes) {
9873
- return currentMinutes >= nightStartMinutes && currentMinutes < dayStartMinutes ? "night" : "day";
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 >= dayStartMinutes && currentMinutes < nightStartMinutes ? "day" : "night";
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: dayShifts, error: dayError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id", validLineIds);
9892
- const { data: nightShifts, error: nightError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 1).in("line_id", validLineIds);
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 dayShift = dayShifts?.find((s) => s.line_id === lineId);
9899
- const nightShift = nightShifts?.find((s) => s.line_id === lineId);
9900
- if (!dayShift || !nightShift) continue;
9901
- const currentShift = getCurrentShift2(
9902
- currentMinutes,
9903
- dayShift.start_time || "06:00",
9904
- nightShift.start_time || "18:00"
9905
- );
9906
- const activeShift = currentShift === "day" ? dayShift : nightShift;
9907
- const shiftName = currentShift === "day" ? "Day Shift" : "Night Shift";
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 shiftConfig = useShiftConfig();
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 options?.initialShiftId !== void 0 ? options.initialShiftId : currentShift.shiftId;
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 configuredLineIds = options?.allowedLineIds ? allConfiguredLineIds.filter((id3) => options.allowedLineIds.includes(id3)) : allConfiguredLineIds;
10239
+ const configuredLineIds2 = options?.allowedLineIds ? allConfiguredLineIds.filter((id3) => options.allowedLineIds.includes(id3)) : allConfiguredLineIds;
10020
10240
  let enabledWorkspaceIds = [];
10021
- for (const lineId of configuredLineIds) {
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.target.value);
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-2 -bottom-2 left-0 right-0 z-20" }),
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
- className: "absolute inset-0 w-full h-full opacity-0 cursor-pointer z-30 margin-0 padding-0"
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
- if (hiddenVideoRef.current) {
27518
- hiddenVideoRef.current.play()?.catch(() => {
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(workspaceId);
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 provided shift: ${shiftStr} for date: ${date}`);
29827
- return shiftStr;
30164
+ console.log(`[BottlenecksContent] Using explicit date/shift: ${date}, shift ${shiftStr}`);
30165
+ return { effectiveShift: shiftStr, effectiveDate: date };
29828
30166
  }
29829
- if (date) {
29830
- console.log(`[BottlenecksContent] No shift provided for historical date ${date}, defaulting to day shift (0)`);
29831
- return "0";
29832
- } else {
29833
- const currentShift = getCurrentShift(
29834
- timezone,
29835
- // Use dynamic timezone instead of hardcoded default
29836
- shiftConfig
29837
- // Use line-specific shift config from database
29838
- );
29839
- console.log(`[BottlenecksContent] Using current operational shift: ${currentShift.shiftId} with timezone: ${timezone} for workspace: ${workspaceId}`);
29840
- return currentShift.shiftId.toString();
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
- }, [shift, date, timezone, shiftConfig, workspaceId]);
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: date || getOperationalDate(timezone),
29929
- shiftId: effectiveShift,
29930
- enabled: true,
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
- date || getOperationalDate(timezone),
29972
- effectiveShift,
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: date || getOperationalDate(timezone),
29984
- shift: shift || "0"
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}:${date}:${shift}`;
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 = date || getOperationalDate(timezone);
30034
- const shiftStr = effectiveShift;
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, date, s3ClipsService, effectiveShift, dashboardConfig, updateClipCounts, timezone, totalOutput]);
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 = date || getOperationalDate(timezone);
30086
- const shiftStr = effectiveShift;
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, date, s3ClipsService, mergedCounts, effectiveShift, timezone]);
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, date, effectiveShift, s3ClipsService, fetchClipCounts]);
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: date || getOperationalDate(timezone),
30209
- shift: effectiveShift,
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, date, effectiveShift, timezone, getAuthToken4]);
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
- const resolvedDate = date || getOperationalDate(timezone);
30343
- const cacheKey = `${categoryId}-${resolvedDate}-${effectiveShift}`;
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: effectiveShift,
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: effectiveShift,
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, date, effectiveShift, isPercentileCategory, metadataCache, s3ClipsService, timezone, clearLoadingState]);
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 = date || getOperationalDate(timezone);
30539
- const shiftStr = effectiveShift;
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, date, effectiveShift, loadAndPlayClipById, timezone]);
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: date || getOperationalDate(timezone),
31220
- shift: effectiveShift,
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
- selectedShift,
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
- dayShift: { avg_efficiency: 0, underperforming_workspaces: 0, total_workspaces: 0, hasData: false },
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 = selectedShift === "day" ? day.dayShift : day.nightShift;
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
- shift: selectedShift,
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, shiftId);
33487
+ onDateSelect(date, selectedShiftId);
33118
33488
  } else {
33119
- router.navigate(`/kpis/${lineId}?date=${date}&shift=${shiftId}&sourceType=lineMonthlyHistory&returnTo=${encodeURIComponent(returnTo)}`);
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 = { dayShift: [], nightShift: [] },
33530
+ underperformingWorkspaces = {},
33148
33531
  lineId,
33149
- selectedShift = "day",
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 = selectedShift === "day" ? day.dayShift : day.nightShift;
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
- selected_shift: selectedShift
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__ */ jsxs("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: [
33238
- /* @__PURE__ */ jsx(
33239
- "button",
33240
- {
33241
- onClick: () => onShiftChange?.("day"),
33242
- className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShift === "day" ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
33243
- children: "Day Shift"
33244
- }
33245
- ),
33246
- /* @__PURE__ */ jsx(
33247
- "button",
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
- selectedShift,
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
- (selectedShift === "day" ? underperformingWorkspaces.dayShift : underperformingWorkspaces.nightShift)?.map((workspace) => /* @__PURE__ */ jsx(
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 || (selectedShift === "day" ? !underperformingWorkspaces.dayShift?.length : !underperformingWorkspaces.nightShift?.length)) && /* @__PURE__ */ jsx("div", { className: "text-center text-gray-500 py-4", children: "No consistently underperforming workspaces found" })
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
- selectedShift,
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
- shift: selectedShift
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 = selectedShift === "day" ? "Day Shift" : "Night Shift";
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) => selectedShift === "day" ? day.dayShift : day.nightShift
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 = selectedShift === "day" ? dayData.dayShift : dayData.nightShift;
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 = selectedShift === "day" ? underperformingWorkspaces.dayShift : underperformingWorkspaces.nightShift;
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 shiftType = lineInfo.shift_id === 0 ? "Day Shift" : "Night Shift";
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
- selectedShift = "day",
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 = selectedShift === "day" ? day.dayShift : day.nightShift;
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, selectedShift]);
34469
- const handleDayClick = useCallback((day, shift) => {
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 = shift === "day" ? day.dayShift : day.nightShift;
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((shift) => {
34889
+ const handleShiftChange = useCallback((shiftId) => {
34487
34890
  trackCoreEvent("Workspace Calendar Shift Changed", {
34488
34891
  workspace_id: workspaceId,
34489
- new_shift: shift
34892
+ new_shift_id: shiftId
34490
34893
  });
34491
34894
  if (onShiftChange) {
34492
- onShiftChange(shift);
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 = selectedShift === "day" ? day.dayShift : day.nightShift;
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, selectedShift),
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
- }, [selectedShift, isCurrentDate, isFutureDate, getPerformanceColor, handleDayClick, year, month, configuredTimezone, animationComplete, hasRealData]);
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__ */ jsxs("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: [
34597
- /* @__PURE__ */ jsx(
34598
- "button",
34599
- {
34600
- onClick: () => handleShiftChange("day"),
34601
- className: `px-4 py-2 text-sm font-medium rounded-md ${animationComplete ? "transition-all duration-200" : ""} ${selectedShift === "day" ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : `text-gray-600 ${animationComplete ? "hover:text-gray-900 hover:bg-gray-100" : ""}`}`,
34602
- children: "Day Shift"
34603
- }
34604
- ),
34605
- /* @__PURE__ */ jsx(
34606
- "button",
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: selectedShift === "day" ? "Day Shifts" : "Night Shifts" }),
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
- selectedShift === "day" ? "Day Shift" : "Night Shift"
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
- selectedShift = "day",
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 ? selectedShift === "day" ? dayData.dayShift : dayData.nightShift : null;
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 ? selectedShift === "day" ? dayData.dayShift : dayData.nightShift : null;
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, selectedShift]);
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) => selectedShift === "day" ? d.dayShift : d.nightShift).filter(hasRealData);
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, selectedShift]);
35192
+ }, [data, selectedShiftId]);
34795
35193
  const metrics2 = useMemo(() => {
34796
- const validShifts = data.map((d) => selectedShift === "day" ? d.dayShift : d.nightShift).filter(hasRealData);
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, selectedShift]);
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
- shift: selectedShift
35241
+ shift_id: selectedShiftId
34844
35242
  });
34845
- onDateSelect(formattedDate, selectedShift);
34846
- }, [workspaceId, selectedShift, onDateSelect]);
34847
- const handleShiftChange = useCallback((shift) => {
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
- new_shift: shift
35248
+ new_shift_id: shiftId
34851
35249
  });
34852
35250
  if (onShiftChange) {
34853
- onShiftChange(shift);
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__ */ jsxs("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: [
34867
- /* @__PURE__ */ jsx(
34868
- "button",
34869
- {
34870
- onClick: () => handleShiftChange("day"),
34871
- className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShift === "day" ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
34872
- children: "Day Shift"
34873
- }
34874
- ),
34875
- /* @__PURE__ */ jsx(
34876
- "button",
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 ? selectedShift === "day" ? day.dayShift : day.nightShift : null;
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 shiftType = "Day Shift";
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
- selectedShift,
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
- shift: selectedShift
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 = selectedShift === "day" ? "Day Shift" : "Night Shift";
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) => selectedShift === "day" ? day.dayShift : day.nightShift
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 = selectedShift === "day" ? dayData.dayShift : dayData.nightShift;
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
- return currentShift.shiftId === 0 ? "Day" : "Night";
37385
+ const rawName = currentShift.shiftName || "Day";
37386
+ return rawName.toLowerCase().includes("shift") ? rawName : `${rawName} Shift`;
36985
37387
  };
36986
37388
  const getShiftIcon = () => {
36987
- const shift = getShiftName();
36988
- if (shift === "Day") {
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
- } else {
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__ */ jsxs("div", { className: "inline-flex items-center gap-0.5 sm:gap-1", children: [
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__ */ jsxs("span", { className: "text-[10px] sm:text-xs md:text-sm font-medium text-gray-500 sm:text-gray-600 whitespace-nowrap", children: [
37005
- getShiftName(),
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 now2 = /* @__PURE__ */ new Date();
42027
- const currentHour = now2.getHours();
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 shift = getShiftName();
42032
- if (shift === "Day") {
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
- } else {
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({ dayShift: [], nightShift: [] });
43566
- const [selectedShift, setSelectedShift] = useState("day");
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 === 0 ? "Day" : "Night";
43598
- }, []);
44008
+ return getShiftNameById(shiftId, configuredTimezone, shiftConfig);
44009
+ }, [configuredTimezone, shiftConfig]);
43599
44010
  const getShiftIcon = useCallback((shiftId) => {
43600
- const shift = getShiftName(shiftId);
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
- } else {
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
- }, [getShiftName]);
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 = dashboardConfig.shiftConfig?.dayShift?.startTime || "06:00";
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, dashboardConfig.shiftConfig]);
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
- dayShift: {
43668
- avg_efficiency: 0,
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
- if (metric.shift_id === 0) {
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 mappedData = {
43699
- dayShift: (underperformingData.dayShift || []).map((ws) => ({
43700
- workspace_name: ws.workspace_name || "Unknown Workspace",
43701
- workspace_uuid: ws.workspace_uuid || ws.workspace_name || `unknown-${Math.random()}`,
43702
- avg_efficiency: ws.avg_efficiency || 0,
43703
- last_5_days: (ws.last_5_days || []).map((day) => ({
43704
- date: day.date,
43705
- efficiency: day.efficiency ?? 0,
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__ */ jsx("span", { className: "text-xs font-medium text-gray-700", children: getShiftName(metrics2.shift_id ?? 0) })
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
- selectedShift
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
- selectedShift,
44254
- onShiftChange: setSelectedShift
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 shiftConfig = useShiftConfig();
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.shiftId === 0 ? "Day" : "Night";
44880
+ const shiftName = (currentShiftDetails.shiftName || "Day").replace(/ Shift$/i, "");
44468
44881
  const getShiftIcon = (shiftId) => {
44469
- if (shiftId === 0) {
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
- } else {
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 === void 0) return "Day";
44812
- return shiftId2 === 0 ? "Day" : "Night";
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 shift2 = getShiftName(shiftId2);
44816
- if (shift2 === "Day") {
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
- } else {
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 returnToParam = `&returnTo=${encodeURIComponent(`/leaderboard`)}`;
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
- onWorkspaceClick(workspace, rank);
45314
+ const combinedParams = navParams ? `${navParams}&${contextParamString}` : `?${contextParamString}`;
45315
+ const enhancedWorkspace = {
45316
+ ...workspace,
45317
+ navParams: combinedParams
45318
+ };
45319
+ onWorkspaceClick(enhancedWorkspace, rank);
44873
45320
  } else {
44874
- navigation.navigate(`/workspace/${workspace.workspace_uuid}${navParams}${returnToParam}`);
45321
+ const combinedParams = navParams ? `${navParams}&${contextParamString}` : `?${contextParamString}`;
45322
+ navigation.navigate(`/workspace/${workspace.workspace_uuid}${combinedParams}`);
44875
45323
  }
44876
- }, [onWorkspaceClick, navigation, lineId, workspacesLength]);
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: dayShiftOperatingHours, error: dayShiftError } = await supabase.from("line_operating_hours").select("line_id, start_time, end_time, breaks").eq("shift_id", 0).in("line_id", lineIds);
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", lineIds);
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) => prev.map((config) => {
45768
- const typedConfig = config;
45769
- const lineId = typedConfig.id;
45770
- const newConfig = { ...typedConfig };
45771
- if (dayShiftHoursMap[lineId]) {
45772
- newConfig.dayShift = {
45773
- ...newConfig.dayShift,
45774
- ...dayShiftHoursMap[lineId]
45775
- };
45776
- }
45777
- if (nightShiftHoursMap[lineId]) {
45778
- newConfig.nightShift = {
45779
- ...newConfig.nightShift,
45780
- ...nightShiftHoursMap[lineId]
45781
- };
45782
- }
45783
- if (newConfig.isOpen === void 0) {
45784
- newConfig.isOpen = getStoredLineState(lineId);
45785
- }
45786
- return newConfig;
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__ */ jsxs("div", { className: "inline-flex bg-gray-100 p-1 rounded-lg w-full max-w-xs sm:w-auto", children: [
47018
- /* @__PURE__ */ jsx(
47019
- "button",
47020
- {
47021
- onClick: () => onShiftChange(0),
47022
- 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 === 0 ? "bg-white text-blue-600 shadow-sm" : "text-gray-600 hover:text-gray-900"}`,
47023
- children: "Day Shift"
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
- const initialLineWorkspaces = useMemo(() => {
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] || initialLineWorkspaces;
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: [0, 1],
47415
- // Fetch both shifts at once
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 = { 0: {}, 1: {} };
47434
- const newDbValues = { 0: {}, 1: {} };
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
- [0, 1].forEach((shiftId) => {
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
- ...prev,
47638
- [lineId]: {
47639
- ...prev[lineId],
47640
- workspaces: prev[lineId].workspaces.map(
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
- }, [actionIds]);
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("day");
48475
+ const [selectedShift, setSelectedShift] = useState(0);
47961
48476
  useEffect(() => {
47962
- if (parsedShiftId === 1) {
47963
- setSelectedShift("night");
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
- dayShift: null,
48116
- // Start with null instead of zeros
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
- if (metric.shift_id === 0) {
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) => entry.dayShift !== null || entry.nightShift !== null).map((entry) => ({
48657
+ const processedData = Array.from(dayDataMap.values()).filter((entry) => Object.keys(entry.shifts).length > 0).map((entry) => ({
48139
48658
  date: entry.date,
48140
- // If a shift is null (no data), provide zeros for compatibility
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 === "night" ? "1" : "0");
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 === "night" ? "1" : "0");
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
- if (shiftType === "Day") {
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__ */ jsxs("span", { className: "text-sm md:text-base font-medium text-blue-600", children: [
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
- onDateSelect: (selectedDate, shift2) => {
49236
+ availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
49237
+ onDateSelect: (selectedDate, shiftId) => {
48719
49238
  if (onDateSelect) {
48720
- onDateSelect(selectedDate, shift2);
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", shift2 === "day" ? "0" : "1");
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 operationalDate = getOperationalDate(timezone || "UTC");
49418
- const currentHour = (/* @__PURE__ */ new Date()).getHours();
49419
- const isNightShift = currentHour >= 18 || currentHour < 6;
49420
- const shiftType = isNightShift ? "Night" : "Day";
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: "Asia/Kolkata"
49985
+ timeZone: effectiveTimezone
49428
49986
  });
49429
49987
  };
49430
- const getShiftIcon = (shift) => {
49431
- return shift === "Night" ? /* @__PURE__ */ jsx(Moon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Sun, { className: "h-4 w-4" });
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(shiftType) }),
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 operationalDate = useMemo(() => {
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
- date: operationalDate,
51805
- shift: currentShift,
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 };