@optifye/dashboard-core 6.11.16 → 6.11.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +22 -1
- package/dist/index.d.ts +22 -1
- package/dist/index.js +679 -431
- package/dist/index.mjs +680 -433
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import React141__default, { createContext, useRef, useCallback, useState, useMem
|
|
|
3
3
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
4
|
import { useRouter } from 'next/router';
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
|
-
import {
|
|
6
|
+
import { formatInTimeZone, fromZonedTime, toZonedTime } from 'date-fns-tz';
|
|
7
7
|
import { format, addDays, subMonths, endOfMonth, startOfMonth, endOfDay, eachDayOfInterval, getDay, isSameDay, isWithinInterval, startOfDay, parseISO, subDays, differenceInMinutes, addMinutes, addMonths, isValid, formatDistanceToNow, isToday, isFuture, isBefore } from 'date-fns';
|
|
8
8
|
import mixpanel from 'mixpanel-browser';
|
|
9
9
|
import { EventEmitter } from 'events';
|
|
@@ -3266,11 +3266,9 @@ var normalizeShiftDefinitions = (timezone, shiftConfig) => {
|
|
|
3266
3266
|
}
|
|
3267
3267
|
return { shifts: legacyShifts, timezone: fallbackTimezone };
|
|
3268
3268
|
};
|
|
3269
|
-
var
|
|
3269
|
+
var determineActiveShiftFromDefinitions = (timezone, shifts, now4 = /* @__PURE__ */ new Date()) => {
|
|
3270
3270
|
const zonedNow = toZonedTime(now4, timezone);
|
|
3271
3271
|
const currentMinutes = zonedNow.getHours() * 60 + zonedNow.getMinutes();
|
|
3272
|
-
let chosen;
|
|
3273
|
-
let operationalDate = getOperationalDate(timezone, now4, shifts[0].startTime);
|
|
3274
3272
|
for (const shift of shifts) {
|
|
3275
3273
|
const start = parseTimeToMinutes(shift.startTime);
|
|
3276
3274
|
const endRaw = parseTimeToMinutes(shift.endTime);
|
|
@@ -3278,32 +3276,47 @@ var determineShiftFromDefinitions = (timezone, shifts, now4 = /* @__PURE__ */ ne
|
|
|
3278
3276
|
const wraps = end <= start;
|
|
3279
3277
|
if (wraps) end += 1440;
|
|
3280
3278
|
if (start <= currentMinutes && currentMinutes < end) {
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3279
|
+
return {
|
|
3280
|
+
shiftId: shift.shiftId,
|
|
3281
|
+
shiftName: shift.shiftName,
|
|
3282
|
+
startTime: shift.startTime,
|
|
3283
|
+
endTime: shift.endTime,
|
|
3284
|
+
timezone,
|
|
3285
|
+
date: getOperationalDate(timezone, now4, shift.startTime)
|
|
3286
|
+
};
|
|
3284
3287
|
}
|
|
3285
3288
|
if (start <= currentMinutes + 1440 && currentMinutes + 1440 < end) {
|
|
3286
|
-
|
|
3287
|
-
|
|
3288
|
-
|
|
3289
|
+
return {
|
|
3290
|
+
shiftId: shift.shiftId,
|
|
3291
|
+
shiftName: shift.shiftName,
|
|
3292
|
+
startTime: shift.startTime,
|
|
3293
|
+
endTime: shift.endTime,
|
|
3294
|
+
timezone,
|
|
3295
|
+
date: getOperationalDate(timezone, now4, shift.startTime)
|
|
3296
|
+
};
|
|
3289
3297
|
}
|
|
3290
3298
|
}
|
|
3291
|
-
|
|
3292
|
-
|
|
3293
|
-
|
|
3299
|
+
return null;
|
|
3300
|
+
};
|
|
3301
|
+
var getCurrentShift = (timezone, shiftConfig, now4 = /* @__PURE__ */ new Date()) => {
|
|
3302
|
+
const { shifts, timezone: effectiveTz } = normalizeShiftDefinitions(timezone, shiftConfig);
|
|
3303
|
+
const activeShift = determineActiveShiftFromDefinitions(effectiveTz, shifts, now4);
|
|
3304
|
+
if (activeShift) {
|
|
3305
|
+
return activeShift;
|
|
3294
3306
|
}
|
|
3307
|
+
const fallbackShift = shifts[0];
|
|
3295
3308
|
return {
|
|
3296
|
-
shiftId:
|
|
3297
|
-
shiftName:
|
|
3298
|
-
startTime:
|
|
3299
|
-
endTime:
|
|
3300
|
-
timezone,
|
|
3301
|
-
date:
|
|
3309
|
+
shiftId: fallbackShift.shiftId,
|
|
3310
|
+
shiftName: fallbackShift.shiftName,
|
|
3311
|
+
startTime: fallbackShift.startTime,
|
|
3312
|
+
endTime: fallbackShift.endTime,
|
|
3313
|
+
timezone: effectiveTz,
|
|
3314
|
+
date: getOperationalDate(effectiveTz, now4, fallbackShift.startTime)
|
|
3302
3315
|
};
|
|
3303
3316
|
};
|
|
3304
|
-
var
|
|
3317
|
+
var getActiveShift = (timezone, shiftConfig, now4 = /* @__PURE__ */ new Date()) => {
|
|
3305
3318
|
const { shifts, timezone: effectiveTz } = normalizeShiftDefinitions(timezone, shiftConfig);
|
|
3306
|
-
return
|
|
3319
|
+
return determineActiveShiftFromDefinitions(effectiveTz, shifts, now4);
|
|
3307
3320
|
};
|
|
3308
3321
|
var isTransitionPeriod = (timezone, shiftConfig, now4 = /* @__PURE__ */ new Date()) => {
|
|
3309
3322
|
const transitionMinutes = shiftConfig?.transitionPeriodMinutes ?? DEFAULT_TRANSITION_MINUTES;
|
|
@@ -3968,7 +3981,8 @@ var dashboardService = {
|
|
|
3968
3981
|
enable,
|
|
3969
3982
|
monitoring_mode,
|
|
3970
3983
|
assembly,
|
|
3971
|
-
video_grid_metric_mode
|
|
3984
|
+
video_grid_metric_mode,
|
|
3985
|
+
recent_flow_window_minutes
|
|
3972
3986
|
`).eq("enable", true);
|
|
3973
3987
|
if (companyId) {
|
|
3974
3988
|
query = query.eq("company_id", companyId);
|
|
@@ -3993,7 +4007,8 @@ var dashboardService = {
|
|
|
3993
4007
|
video_grid_metric_mode: normalizeVideoGridMetricMode(
|
|
3994
4008
|
line.video_grid_metric_mode,
|
|
3995
4009
|
line.assembly ?? false
|
|
3996
|
-
)
|
|
4010
|
+
),
|
|
4011
|
+
recent_flow_window_minutes: line.recent_flow_window_minutes ?? 7
|
|
3997
4012
|
}));
|
|
3998
4013
|
return transformedLines;
|
|
3999
4014
|
} catch (err) {
|
|
@@ -4030,7 +4045,7 @@ var dashboardService = {
|
|
|
4030
4045
|
}
|
|
4031
4046
|
const lineIdsToQuery = configuredLineIds;
|
|
4032
4047
|
const [line1Result, metricsResult2] = await Promise.all([
|
|
4033
|
-
supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single(),
|
|
4048
|
+
supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, recent_flow_window_minutes, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single(),
|
|
4034
4049
|
supabase.from(lineMetricsTable).select("*").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
|
|
4035
4050
|
]);
|
|
4036
4051
|
if (line1Result.error) throw line1Result.error;
|
|
@@ -4086,6 +4101,7 @@ var dashboardService = {
|
|
|
4086
4101
|
date: queryDate,
|
|
4087
4102
|
shift_id: queryShiftId,
|
|
4088
4103
|
monitoring_mode: line1Data.monitoring_mode ?? void 0,
|
|
4104
|
+
recent_flow_window_minutes: line1Data.recent_flow_window_minutes ?? 7,
|
|
4089
4105
|
metrics: {
|
|
4090
4106
|
avg_efficiency: avgEfficiency,
|
|
4091
4107
|
avg_cycle_time: combinedMetricsData.avg_cycle_time / numLines,
|
|
@@ -4109,7 +4125,7 @@ var dashboardService = {
|
|
|
4109
4125
|
throw new Error("Company ID must be configured for detailed line requests.");
|
|
4110
4126
|
}
|
|
4111
4127
|
const [lineResult, metricsResult] = await Promise.all([
|
|
4112
|
-
supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
|
|
4128
|
+
supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, assembly, video_grid_metric_mode, recent_flow_window_minutes, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
|
|
4113
4129
|
supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
|
|
4114
4130
|
]);
|
|
4115
4131
|
if (lineResult.error) throw lineResult.error;
|
|
@@ -4134,6 +4150,7 @@ var dashboardService = {
|
|
|
4134
4150
|
date: queryDate,
|
|
4135
4151
|
shift_id: queryShiftId,
|
|
4136
4152
|
monitoring_mode: lineData.monitoring_mode ?? void 0,
|
|
4153
|
+
recent_flow_window_minutes: lineData.recent_flow_window_minutes ?? 7,
|
|
4137
4154
|
metrics: {
|
|
4138
4155
|
avg_efficiency: metrics2?.avg_efficiency ?? 0,
|
|
4139
4156
|
avg_cycle_time: metrics2?.avg_cycle_time || 0,
|
|
@@ -8467,7 +8484,8 @@ var LinesService = class {
|
|
|
8467
8484
|
videoGridMetricMode: normalizeVideoGridMetricMode(
|
|
8468
8485
|
line.video_grid_metric_mode,
|
|
8469
8486
|
line.assembly ?? false
|
|
8470
|
-
)
|
|
8487
|
+
),
|
|
8488
|
+
recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7
|
|
8471
8489
|
}));
|
|
8472
8490
|
} catch (error) {
|
|
8473
8491
|
console.error("Error fetching lines:", error);
|
|
@@ -8515,7 +8533,8 @@ var LinesService = class {
|
|
|
8515
8533
|
videoGridMetricMode: normalizeVideoGridMetricMode(
|
|
8516
8534
|
line.video_grid_metric_mode,
|
|
8517
8535
|
line.assembly ?? false
|
|
8518
|
-
)
|
|
8536
|
+
),
|
|
8537
|
+
recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7
|
|
8519
8538
|
}));
|
|
8520
8539
|
} catch (error) {
|
|
8521
8540
|
console.error("Error fetching all lines:", error);
|
|
@@ -8572,7 +8591,8 @@ var LinesService = class {
|
|
|
8572
8591
|
videoGridMetricMode: normalizeVideoGridMetricMode(
|
|
8573
8592
|
data.video_grid_metric_mode,
|
|
8574
8593
|
data.assembly ?? false
|
|
8575
|
-
)
|
|
8594
|
+
),
|
|
8595
|
+
recentFlowWindowMinutes: data.recent_flow_window_minutes ?? 7
|
|
8576
8596
|
};
|
|
8577
8597
|
} catch (error) {
|
|
8578
8598
|
console.error("Error fetching line:", error);
|
|
@@ -13326,6 +13346,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13326
13346
|
actionName: item.action_name
|
|
13327
13347
|
}),
|
|
13328
13348
|
recent_flow_percent: item.recent_flow_percent ?? null,
|
|
13349
|
+
recent_flow_window_minutes: item.recent_flow_window_minutes ?? null,
|
|
13329
13350
|
recent_flow_effective_end_at: item.recent_flow_effective_end_at ?? null,
|
|
13330
13351
|
recent_flow_computed_at: item.recent_flow_computed_at ?? null,
|
|
13331
13352
|
incoming_wip_current: item.incoming_wip_current ?? null,
|
|
@@ -32174,6 +32195,7 @@ var LineChartComponent = ({
|
|
|
32174
32195
|
xAxisLabel,
|
|
32175
32196
|
xAxisTickFormatter,
|
|
32176
32197
|
// Pass through for X-axis tick formatting
|
|
32198
|
+
xAxisInterval,
|
|
32177
32199
|
yAxisLabel,
|
|
32178
32200
|
yAxisUnit,
|
|
32179
32201
|
yAxisDomain,
|
|
@@ -32256,6 +32278,7 @@ var LineChartComponent = ({
|
|
|
32256
32278
|
dataKey: xAxisDataKey,
|
|
32257
32279
|
label: xAxisLabel ? { value: xAxisLabel, position: "insideBottom", offset: -10 } : void 0,
|
|
32258
32280
|
tickFormatter: xAxisTickFormatter,
|
|
32281
|
+
interval: xAxisInterval,
|
|
32259
32282
|
tick: { fontSize: 12, fill: axisTickFillColor },
|
|
32260
32283
|
stroke: axisStrokeColor
|
|
32261
32284
|
}
|
|
@@ -32580,6 +32603,212 @@ var CycleTimeChart = React141__default.memo(CycleTimeChartComponent, (prevProps,
|
|
|
32580
32603
|
});
|
|
32581
32604
|
});
|
|
32582
32605
|
CycleTimeChart.displayName = "CycleTimeChart";
|
|
32606
|
+
|
|
32607
|
+
// src/lib/utils/hourlyIdle.ts
|
|
32608
|
+
var DEFAULT_SHIFT_DURATION = 11;
|
|
32609
|
+
var normalizeMinuteSeries = (idleTimeHourly) => {
|
|
32610
|
+
if (!idleTimeHourly || typeof idleTimeHourly !== "object") {
|
|
32611
|
+
return {};
|
|
32612
|
+
}
|
|
32613
|
+
return Object.fromEntries(
|
|
32614
|
+
Object.entries(idleTimeHourly).map(([key, value]) => {
|
|
32615
|
+
if (Array.isArray(value)) {
|
|
32616
|
+
return [key, value];
|
|
32617
|
+
}
|
|
32618
|
+
if (value && Array.isArray(value.values)) {
|
|
32619
|
+
return [key, value.values];
|
|
32620
|
+
}
|
|
32621
|
+
return [key, []];
|
|
32622
|
+
})
|
|
32623
|
+
);
|
|
32624
|
+
};
|
|
32625
|
+
var parseTimeString = (timeValue) => {
|
|
32626
|
+
const [hoursPart, minutesPart] = timeValue.split(":");
|
|
32627
|
+
const hour = Number.parseInt(hoursPart, 10);
|
|
32628
|
+
const minute = Number.parseInt(minutesPart ?? "0", 10);
|
|
32629
|
+
const safeHour = Number.isFinite(hour) ? hour : 0;
|
|
32630
|
+
const safeMinute = Number.isFinite(minute) ? minute : 0;
|
|
32631
|
+
return {
|
|
32632
|
+
hour: safeHour,
|
|
32633
|
+
minute: safeMinute,
|
|
32634
|
+
decimalHour: safeHour + safeMinute / 60
|
|
32635
|
+
};
|
|
32636
|
+
};
|
|
32637
|
+
var buildShiftLayout = ({
|
|
32638
|
+
shiftStart,
|
|
32639
|
+
shiftEnd
|
|
32640
|
+
}) => {
|
|
32641
|
+
const shiftStartTime = parseTimeString(shiftStart);
|
|
32642
|
+
if (!shiftEnd) {
|
|
32643
|
+
return {
|
|
32644
|
+
shiftDuration: DEFAULT_SHIFT_DURATION,
|
|
32645
|
+
shiftStartTime,
|
|
32646
|
+
shiftEndTime: null,
|
|
32647
|
+
hasPartialLastHour: false
|
|
32648
|
+
};
|
|
32649
|
+
}
|
|
32650
|
+
const shiftEndTime = parseTimeString(shiftEnd);
|
|
32651
|
+
let duration = shiftEndTime.decimalHour - shiftStartTime.decimalHour;
|
|
32652
|
+
if (duration <= 0) {
|
|
32653
|
+
duration += 24;
|
|
32654
|
+
}
|
|
32655
|
+
const hasPartialLastHour = shiftEndTime.minute > 0 && shiftEndTime.minute < 60;
|
|
32656
|
+
const shiftDuration = hasPartialLastHour ? Math.ceil(duration) : Math.round(duration);
|
|
32657
|
+
return {
|
|
32658
|
+
shiftDuration,
|
|
32659
|
+
shiftStartTime,
|
|
32660
|
+
shiftEndTime,
|
|
32661
|
+
hasPartialLastHour
|
|
32662
|
+
};
|
|
32663
|
+
};
|
|
32664
|
+
var formatCompactTime = (hour, minute) => {
|
|
32665
|
+
const period = hour >= 12 ? "PM" : "AM";
|
|
32666
|
+
const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
|
|
32667
|
+
if (minute === 0) {
|
|
32668
|
+
return `${hour12}${period}`;
|
|
32669
|
+
}
|
|
32670
|
+
return `${hour12}:${minute.toString().padStart(2, "0")}${period}`;
|
|
32671
|
+
};
|
|
32672
|
+
var formatFullTime = (hour, minute) => {
|
|
32673
|
+
const period = hour >= 12 ? "PM" : "AM";
|
|
32674
|
+
const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
|
|
32675
|
+
return `${hour12}:${minute.toString().padStart(2, "0")} ${period}`;
|
|
32676
|
+
};
|
|
32677
|
+
var getSlotTimeBounds = (hourIndex, layout2) => {
|
|
32678
|
+
const isLastHour = hourIndex === layout2.shiftDuration - 1;
|
|
32679
|
+
const startDecimalHour = layout2.shiftStartTime.decimalHour + hourIndex;
|
|
32680
|
+
const startHour = Math.floor(startDecimalHour) % 24;
|
|
32681
|
+
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
32682
|
+
let endHour;
|
|
32683
|
+
let endMinute;
|
|
32684
|
+
if (isLastHour && layout2.shiftEndTime) {
|
|
32685
|
+
endHour = layout2.shiftEndTime.hour;
|
|
32686
|
+
endMinute = layout2.shiftEndTime.minute;
|
|
32687
|
+
} else {
|
|
32688
|
+
const endDecimalHour = startDecimalHour + 1;
|
|
32689
|
+
endHour = Math.floor(endDecimalHour) % 24;
|
|
32690
|
+
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
32691
|
+
}
|
|
32692
|
+
return {
|
|
32693
|
+
startHour,
|
|
32694
|
+
startMinute,
|
|
32695
|
+
endHour,
|
|
32696
|
+
endMinute
|
|
32697
|
+
};
|
|
32698
|
+
};
|
|
32699
|
+
var getIdleArrayForHour = (hourIndex, idleTimeHourly, layout2) => {
|
|
32700
|
+
const actualHour = (layout2.shiftStartTime.hour + hourIndex) % 24;
|
|
32701
|
+
const startMinute = layout2.shiftStartTime.minute;
|
|
32702
|
+
if (startMinute > 0) {
|
|
32703
|
+
if (hourIndex === 0) {
|
|
32704
|
+
const firstHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
32705
|
+
const nextHourData2 = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
|
|
32706
|
+
return [
|
|
32707
|
+
...firstHourData.slice(startMinute),
|
|
32708
|
+
...nextHourData2.slice(0, startMinute)
|
|
32709
|
+
];
|
|
32710
|
+
}
|
|
32711
|
+
if (hourIndex < layout2.shiftDuration - 1) {
|
|
32712
|
+
const currentHourData3 = idleTimeHourly[actualHour.toString()] || [];
|
|
32713
|
+
const nextHourData2 = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
|
|
32714
|
+
return [
|
|
32715
|
+
...currentHourData3.slice(startMinute),
|
|
32716
|
+
...nextHourData2.slice(0, startMinute)
|
|
32717
|
+
];
|
|
32718
|
+
}
|
|
32719
|
+
if (layout2.hasPartialLastHour && layout2.shiftEndTime) {
|
|
32720
|
+
const currentHourData3 = idleTimeHourly[actualHour.toString()] || [];
|
|
32721
|
+
const nextHourData2 = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
|
|
32722
|
+
return [
|
|
32723
|
+
...currentHourData3.slice(startMinute),
|
|
32724
|
+
...nextHourData2.slice(0, layout2.shiftEndTime.minute)
|
|
32725
|
+
];
|
|
32726
|
+
}
|
|
32727
|
+
const currentHourData2 = idleTimeHourly[actualHour.toString()] || [];
|
|
32728
|
+
const nextHourData = idleTimeHourly[((actualHour + 1) % 24).toString()] || [];
|
|
32729
|
+
return [
|
|
32730
|
+
...currentHourData2.slice(startMinute),
|
|
32731
|
+
...nextHourData.slice(0, startMinute)
|
|
32732
|
+
];
|
|
32733
|
+
}
|
|
32734
|
+
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
32735
|
+
if (hourIndex === layout2.shiftDuration - 1 && layout2.hasPartialLastHour && layout2.shiftEndTime) {
|
|
32736
|
+
return currentHourData.slice(0, layout2.shiftEndTime.minute);
|
|
32737
|
+
}
|
|
32738
|
+
return currentHourData;
|
|
32739
|
+
};
|
|
32740
|
+
var buildHourlyIdleSlots = ({
|
|
32741
|
+
idleTimeHourly,
|
|
32742
|
+
shiftStart,
|
|
32743
|
+
shiftEnd
|
|
32744
|
+
}) => {
|
|
32745
|
+
const normalizedIdleTimeHourly = normalizeMinuteSeries(idleTimeHourly);
|
|
32746
|
+
const layout2 = buildShiftLayout({ shiftStart, shiftEnd });
|
|
32747
|
+
return Array.from({ length: layout2.shiftDuration }, (_, hourIndex) => {
|
|
32748
|
+
const { startHour, startMinute, endHour, endMinute } = getSlotTimeBounds(hourIndex, layout2);
|
|
32749
|
+
const idleArray = getIdleArrayForHour(hourIndex, normalizedIdleTimeHourly, layout2);
|
|
32750
|
+
const idleMinutes = idleArray.filter((value) => value === 1 || value === "1").length;
|
|
32751
|
+
return {
|
|
32752
|
+
hourIndex,
|
|
32753
|
+
hour: `${formatCompactTime(startHour, startMinute)}-${formatCompactTime(endHour, endMinute)}`,
|
|
32754
|
+
timeRange: `${formatFullTime(startHour, startMinute)} - ${formatFullTime(endHour, endMinute)}`,
|
|
32755
|
+
idleMinutes,
|
|
32756
|
+
idleArray
|
|
32757
|
+
};
|
|
32758
|
+
});
|
|
32759
|
+
};
|
|
32760
|
+
var formatIdleTimestamp = ({
|
|
32761
|
+
shiftStart,
|
|
32762
|
+
hourIndex,
|
|
32763
|
+
minuteIndex
|
|
32764
|
+
}) => {
|
|
32765
|
+
const shiftStartTime = parseTimeString(shiftStart);
|
|
32766
|
+
const totalMinutes = (shiftStartTime.hour + hourIndex) * 60 + shiftStartTime.minute + minuteIndex;
|
|
32767
|
+
const hour = Math.floor(totalMinutes / 60) % 24;
|
|
32768
|
+
const minute = totalMinutes % 60;
|
|
32769
|
+
return formatFullTime(hour, minute);
|
|
32770
|
+
};
|
|
32771
|
+
var getHourlyIdlePeriods = ({
|
|
32772
|
+
idleArray,
|
|
32773
|
+
shiftStart,
|
|
32774
|
+
hourIndex
|
|
32775
|
+
}) => {
|
|
32776
|
+
if (!Array.isArray(idleArray) || idleArray.length === 0) {
|
|
32777
|
+
return [];
|
|
32778
|
+
}
|
|
32779
|
+
const periods = [];
|
|
32780
|
+
let currentRange = null;
|
|
32781
|
+
idleArray.forEach((value, minuteIndex) => {
|
|
32782
|
+
if (value === 1 || value === "1") {
|
|
32783
|
+
if (!currentRange) {
|
|
32784
|
+
currentRange = { start: minuteIndex, end: minuteIndex };
|
|
32785
|
+
} else {
|
|
32786
|
+
currentRange.end = minuteIndex;
|
|
32787
|
+
}
|
|
32788
|
+
} else if (value !== "x" && currentRange) {
|
|
32789
|
+
periods.push(currentRange);
|
|
32790
|
+
currentRange = null;
|
|
32791
|
+
}
|
|
32792
|
+
});
|
|
32793
|
+
if (currentRange) {
|
|
32794
|
+
periods.push(currentRange);
|
|
32795
|
+
}
|
|
32796
|
+
return periods.map((period) => ({
|
|
32797
|
+
start: period.start,
|
|
32798
|
+
end: period.end,
|
|
32799
|
+
duration: period.end - period.start + 1,
|
|
32800
|
+
startTime: formatIdleTimestamp({
|
|
32801
|
+
shiftStart,
|
|
32802
|
+
hourIndex,
|
|
32803
|
+
minuteIndex: period.start
|
|
32804
|
+
}),
|
|
32805
|
+
endTime: formatIdleTimestamp({
|
|
32806
|
+
shiftStart,
|
|
32807
|
+
hourIndex,
|
|
32808
|
+
minuteIndex: period.end + 1
|
|
32809
|
+
})
|
|
32810
|
+
}));
|
|
32811
|
+
};
|
|
32583
32812
|
var CycleTimeOverTimeChart = ({
|
|
32584
32813
|
data,
|
|
32585
32814
|
idealCycleTime,
|
|
@@ -32589,7 +32818,8 @@ var CycleTimeOverTimeChart = ({
|
|
|
32589
32818
|
datasetKey,
|
|
32590
32819
|
className = "",
|
|
32591
32820
|
showIdleTime = false,
|
|
32592
|
-
idleTimeData = []
|
|
32821
|
+
idleTimeData = [],
|
|
32822
|
+
idleTimeSlots = []
|
|
32593
32823
|
}) => {
|
|
32594
32824
|
const MAX_DATA_POINTS = 40;
|
|
32595
32825
|
const containerRef = React141__default.useRef(null);
|
|
@@ -32692,50 +32922,60 @@ var CycleTimeOverTimeChart = ({
|
|
|
32692
32922
|
if (!visibleEntries.length) {
|
|
32693
32923
|
return null;
|
|
32694
32924
|
}
|
|
32695
|
-
|
|
32696
|
-
|
|
32697
|
-
|
|
32698
|
-
|
|
32699
|
-
|
|
32700
|
-
|
|
32701
|
-
|
|
32702
|
-
|
|
32703
|
-
|
|
32704
|
-
|
|
32705
|
-
|
|
32706
|
-
|
|
32707
|
-
|
|
32708
|
-
|
|
32709
|
-
|
|
32710
|
-
|
|
32711
|
-
|
|
32712
|
-
|
|
32713
|
-
|
|
32714
|
-
|
|
32715
|
-
|
|
32716
|
-
|
|
32717
|
-
|
|
32718
|
-
|
|
32719
|
-
|
|
32720
|
-
|
|
32721
|
-
|
|
32722
|
-
|
|
32723
|
-
|
|
32724
|
-
|
|
32725
|
-
|
|
32726
|
-
|
|
32727
|
-
|
|
32728
|
-
|
|
32729
|
-
|
|
32730
|
-
|
|
32731
|
-
|
|
32732
|
-
|
|
32733
|
-
|
|
32734
|
-
|
|
32735
|
-
|
|
32736
|
-
|
|
32737
|
-
|
|
32738
|
-
|
|
32925
|
+
const dataPoint = payload[0]?.payload || {};
|
|
32926
|
+
const idlePeriods = showIdleTime && typeof dataPoint.idleMinutes === "number" && dataPoint.idleMinutes > 0 ? getHourlyIdlePeriods({
|
|
32927
|
+
idleArray: dataPoint.idleArray,
|
|
32928
|
+
shiftStart,
|
|
32929
|
+
hourIndex: Number.isFinite(dataPoint.hourIndex) ? dataPoint.hourIndex : 0
|
|
32930
|
+
}) : [];
|
|
32931
|
+
return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-xl border border-gray-100 p-4 min-w-[220px]", children: [
|
|
32932
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 text-sm", children: dataPoint.timeRange || dataPoint.tooltip || "" }) }),
|
|
32933
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
32934
|
+
visibleEntries.map((entry) => {
|
|
32935
|
+
const numericValue = getNumericValue(entry.value);
|
|
32936
|
+
if (numericValue === null) {
|
|
32937
|
+
return null;
|
|
32938
|
+
}
|
|
32939
|
+
if (entry.name === "idleMinutes") {
|
|
32940
|
+
if (!showIdleTime) return null;
|
|
32941
|
+
return /* @__PURE__ */ jsx("div", { className: "border-t border-gray-100 pt-2", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
32942
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Idle Time" }),
|
|
32943
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-orange-600 text-sm", children: [
|
|
32944
|
+
numericValue.toFixed(0),
|
|
32945
|
+
" minutes"
|
|
32946
|
+
] })
|
|
32947
|
+
] }) }, `${entry.name}-${numericValue}`);
|
|
32948
|
+
}
|
|
32949
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
32950
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: "Cycle Time" }),
|
|
32951
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-gray-900 text-sm", children: [
|
|
32952
|
+
numericValue.toFixed(1),
|
|
32953
|
+
" seconds"
|
|
32954
|
+
] })
|
|
32955
|
+
] }, `${entry.name}-${numericValue}`);
|
|
32956
|
+
}),
|
|
32957
|
+
idlePeriods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-gray-50 rounded-lg p-2.5", children: [
|
|
32958
|
+
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
|
|
32959
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idlePeriods.map((period, index) => /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
|
|
32960
|
+
/* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
|
|
32961
|
+
/* @__PURE__ */ jsx("span", { children: period.duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32962
|
+
period.startTime,
|
|
32963
|
+
" (",
|
|
32964
|
+
period.duration,
|
|
32965
|
+
" min)"
|
|
32966
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32967
|
+
period.startTime,
|
|
32968
|
+
" - ",
|
|
32969
|
+
period.endTime,
|
|
32970
|
+
" (",
|
|
32971
|
+
period.duration,
|
|
32972
|
+
" mins)"
|
|
32973
|
+
] }) })
|
|
32974
|
+
] }, index)) })
|
|
32975
|
+
] })
|
|
32976
|
+
] })
|
|
32977
|
+
] });
|
|
32978
|
+
}, [getNumericValue, shiftStart, showIdleTime]);
|
|
32739
32979
|
const renderCycleDot = React141__default.useCallback((props) => {
|
|
32740
32980
|
const { cx: cx2, cy, payload } = props;
|
|
32741
32981
|
const cycleTime = getNumericValue(payload?.cycleTime);
|
|
@@ -32804,14 +33044,18 @@ var CycleTimeOverTimeChart = ({
|
|
|
32804
33044
|
r: 4,
|
|
32805
33045
|
fill: "#f59e0b",
|
|
32806
33046
|
stroke: "#fff",
|
|
32807
|
-
strokeWidth: 1
|
|
33047
|
+
strokeWidth: 1,
|
|
33048
|
+
style: {
|
|
33049
|
+
opacity: showIdleTime ? 1 : 0,
|
|
33050
|
+
transition: "opacity 0.3s ease-in-out"
|
|
33051
|
+
}
|
|
32808
33052
|
}
|
|
32809
33053
|
);
|
|
32810
|
-
}, [getNumericValue]);
|
|
33054
|
+
}, [getNumericValue, showIdleTime]);
|
|
32811
33055
|
const renderIdleActiveDot = React141__default.useCallback((props) => {
|
|
32812
33056
|
const { cx: cx2, cy, payload } = props;
|
|
32813
33057
|
const idleMinutes = getNumericValue(payload?.idleMinutes);
|
|
32814
|
-
if (idleMinutes === null) {
|
|
33058
|
+
if (idleMinutes === null || !showIdleTime) {
|
|
32815
33059
|
return /* @__PURE__ */ jsx("g", {});
|
|
32816
33060
|
}
|
|
32817
33061
|
return /* @__PURE__ */ jsx(
|
|
@@ -32825,25 +33069,40 @@ var CycleTimeOverTimeChart = ({
|
|
|
32825
33069
|
strokeWidth: 2
|
|
32826
33070
|
}
|
|
32827
33071
|
);
|
|
32828
|
-
}, [getNumericValue]);
|
|
33072
|
+
}, [getNumericValue, showIdleTime]);
|
|
32829
33073
|
const chartData = React141__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
|
|
32830
33074
|
const cycleTime = getNumericValue(finalData[i]);
|
|
32831
|
-
const
|
|
33075
|
+
const useIdleSlots = idleTimeSlots.length > 0;
|
|
33076
|
+
const idleSlot = useIdleSlots ? idleTimeSlots[i] ?? null : null;
|
|
33077
|
+
const idleMinutes = useIdleSlots ? idleSlot?.idleMinutes ?? null : getNumericValue(idleTimeData[i]);
|
|
32832
33078
|
return {
|
|
32833
33079
|
timeIndex: i,
|
|
32834
33080
|
label: formatTimeLabel(i),
|
|
32835
|
-
tooltip: formatTooltipTime(i),
|
|
33081
|
+
tooltip: idleSlot?.timeRange || formatTooltipTime(i),
|
|
33082
|
+
timeRange: idleSlot?.timeRange || formatTooltipTime(i),
|
|
33083
|
+
hourIndex: idleSlot?.hourIndex ?? i,
|
|
32836
33084
|
cycleTime,
|
|
32837
33085
|
idleMinutes,
|
|
33086
|
+
idleArray: idleSlot?.idleArray || [],
|
|
32838
33087
|
color: cycleTime !== null && cycleTime <= idealCycleTime ? "#00AB45" : "#E34329"
|
|
32839
33088
|
};
|
|
32840
|
-
}), [DURATION, finalData,
|
|
33089
|
+
}), [DURATION, finalData, idleTimeData, idleTimeSlots, idealCycleTime, getNumericValue]);
|
|
32841
33090
|
const renderLegend = () => {
|
|
32842
|
-
|
|
32843
|
-
|
|
32844
|
-
|
|
32845
|
-
|
|
32846
|
-
|
|
33091
|
+
return /* @__PURE__ */ jsx(
|
|
33092
|
+
"div",
|
|
33093
|
+
{
|
|
33094
|
+
className: "flex items-center justify-start text-[10px] font-bold text-gray-500 mb-6 tracking-[0.05em] gap-5",
|
|
33095
|
+
style: {
|
|
33096
|
+
opacity: showIdleTime ? 1 : 0,
|
|
33097
|
+
pointerEvents: showIdleTime ? "auto" : "none",
|
|
33098
|
+
transition: "opacity 0.3s ease-in-out"
|
|
33099
|
+
},
|
|
33100
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
33101
|
+
/* @__PURE__ */ jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-[#f59e0b]" }),
|
|
33102
|
+
/* @__PURE__ */ jsx("span", { children: "Idle Time (min)" })
|
|
33103
|
+
] })
|
|
33104
|
+
}
|
|
33105
|
+
);
|
|
32847
33106
|
};
|
|
32848
33107
|
return /* @__PURE__ */ jsxs(
|
|
32849
33108
|
"div",
|
|
@@ -32914,7 +33173,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
32914
33173
|
}
|
|
32915
33174
|
}
|
|
32916
33175
|
),
|
|
32917
|
-
|
|
33176
|
+
/* @__PURE__ */ jsx(
|
|
32918
33177
|
YAxis,
|
|
32919
33178
|
{
|
|
32920
33179
|
yAxisId: "idle",
|
|
@@ -32923,7 +33182,11 @@ var CycleTimeOverTimeChart = ({
|
|
|
32923
33182
|
width: 35,
|
|
32924
33183
|
domain: [0, 60],
|
|
32925
33184
|
tickFormatter: (value) => `${value}m`,
|
|
32926
|
-
tick: {
|
|
33185
|
+
tick: {
|
|
33186
|
+
fontSize: 11,
|
|
33187
|
+
fill: showIdleTime ? "#f59e0b" : "transparent",
|
|
33188
|
+
style: { transition: "fill 0.3s ease-in-out" }
|
|
33189
|
+
},
|
|
32927
33190
|
axisLine: false,
|
|
32928
33191
|
tickLine: false
|
|
32929
33192
|
}
|
|
@@ -32971,7 +33234,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
32971
33234
|
},
|
|
32972
33235
|
`${effectiveDatasetKey}:cycle`
|
|
32973
33236
|
),
|
|
32974
|
-
|
|
33237
|
+
/* @__PURE__ */ jsx(
|
|
32975
33238
|
Line,
|
|
32976
33239
|
{
|
|
32977
33240
|
type: "monotone",
|
|
@@ -32986,7 +33249,11 @@ var CycleTimeOverTimeChart = ({
|
|
|
32986
33249
|
isAnimationActive: true,
|
|
32987
33250
|
animationBegin: 300,
|
|
32988
33251
|
animationDuration: 1500,
|
|
32989
|
-
animationEasing: "ease-out"
|
|
33252
|
+
animationEasing: "ease-out",
|
|
33253
|
+
style: {
|
|
33254
|
+
strokeOpacity: showIdleTime ? 1 : 0,
|
|
33255
|
+
transition: "stroke-opacity 0.3s ease-in-out"
|
|
33256
|
+
}
|
|
32990
33257
|
},
|
|
32991
33258
|
`${effectiveDatasetKey}:idle`
|
|
32992
33259
|
)
|
|
@@ -33141,89 +33408,20 @@ var HourlyOutputChartComponent = ({
|
|
|
33141
33408
|
shiftEnd,
|
|
33142
33409
|
showIdleTime = false,
|
|
33143
33410
|
idleTimeHourly,
|
|
33144
|
-
idleTimeClips,
|
|
33145
|
-
idleTimeClipClassifications,
|
|
33146
|
-
shiftDate,
|
|
33147
|
-
timezone,
|
|
33148
33411
|
className = ""
|
|
33149
33412
|
}) => {
|
|
33150
33413
|
const containerRef = React141__default.useRef(null);
|
|
33151
33414
|
const [containerReady, setContainerReady] = React141__default.useState(false);
|
|
33152
33415
|
const [containerWidth, setContainerWidth] = React141__default.useState(0);
|
|
33153
|
-
const
|
|
33154
|
-
|
|
33155
|
-
|
|
33156
|
-
const minute = parseInt(minutes || "0");
|
|
33157
|
-
const decimalHour = hour + minute / 60;
|
|
33158
|
-
return { hour, minute, decimalHour };
|
|
33159
|
-
};
|
|
33160
|
-
const shiftStartTime = getTimeFromTimeString2(shiftStart);
|
|
33161
|
-
React141__default.useMemo(() => {
|
|
33162
|
-
if (!shiftDate || !timezone) return null;
|
|
33163
|
-
const hour = shiftStartTime.hour.toString().padStart(2, "0");
|
|
33164
|
-
const minute = shiftStartTime.minute.toString().padStart(2, "0");
|
|
33165
|
-
return fromZonedTime(`${shiftDate}T${hour}:${minute}:00`, timezone);
|
|
33166
|
-
}, [shiftDate, timezone, shiftStartTime.hour, shiftStartTime.minute]);
|
|
33167
|
-
const idleClipRanges = React141__default.useMemo(() => {
|
|
33168
|
-
if (!idleTimeClips || idleTimeClips.length === 0) return [];
|
|
33169
|
-
return idleTimeClips.map((clip) => ({
|
|
33170
|
-
id: clip.id,
|
|
33171
|
-
start: clip.idle_start_time ? new Date(clip.idle_start_time) : null,
|
|
33172
|
-
end: clip.idle_end_time ? new Date(clip.idle_end_time) : null
|
|
33173
|
-
})).filter((clip) => clip.start && clip.end);
|
|
33174
|
-
}, [idleTimeClips]);
|
|
33175
|
-
React141__default.useCallback((rangeStart, rangeEnd) => {
|
|
33176
|
-
if (!rangeStart || !rangeEnd || idleClipRanges.length === 0) {
|
|
33177
|
-
return "Reason unavailable";
|
|
33178
|
-
}
|
|
33179
|
-
const matchingClip = idleClipRanges.find((clip) => rangeStart >= clip.start && rangeEnd <= clip.end) || idleClipRanges.find((clip) => rangeStart < clip.end && rangeEnd > clip.start);
|
|
33180
|
-
if (!matchingClip) {
|
|
33181
|
-
return "Reason unavailable";
|
|
33182
|
-
}
|
|
33183
|
-
const classification = idleTimeClipClassifications?.[matchingClip.id];
|
|
33184
|
-
if (!classification || classification.status === "processing") {
|
|
33185
|
-
return "Analyzing...";
|
|
33186
|
-
}
|
|
33187
|
-
if (!classification.label) {
|
|
33188
|
-
return "Reason unavailable";
|
|
33189
|
-
}
|
|
33190
|
-
return classification.displayName || classification.label.replace(/_/g, " ");
|
|
33191
|
-
}, [idleClipRanges, idleTimeClipClassifications]);
|
|
33192
|
-
const { shiftDuration, shiftEndTime, hasPartialLastHour } = React141__default.useMemo(() => {
|
|
33193
|
-
console.log("[HourlyOutputChart] Calculating shift duration with:", {
|
|
33416
|
+
const idleSlots = React141__default.useMemo(
|
|
33417
|
+
() => buildHourlyIdleSlots({
|
|
33418
|
+
idleTimeHourly,
|
|
33194
33419
|
shiftStart,
|
|
33195
|
-
shiftEnd
|
|
33196
|
-
|
|
33197
|
-
|
|
33198
|
-
|
|
33199
|
-
|
|
33200
|
-
return {
|
|
33201
|
-
shiftDuration: 11,
|
|
33202
|
-
shiftEndTime: null,
|
|
33203
|
-
hasPartialLastHour: false
|
|
33204
|
-
};
|
|
33205
|
-
}
|
|
33206
|
-
const endTime = getTimeFromTimeString2(shiftEnd);
|
|
33207
|
-
let duration = endTime.decimalHour - shiftStartTime.decimalHour;
|
|
33208
|
-
if (duration <= 0) {
|
|
33209
|
-
duration += 24;
|
|
33210
|
-
}
|
|
33211
|
-
const hasPartial = endTime.minute > 0 && endTime.minute < 60;
|
|
33212
|
-
const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
|
|
33213
|
-
console.log("[HourlyOutputChart] Shift calculation results:", {
|
|
33214
|
-
endTime,
|
|
33215
|
-
duration,
|
|
33216
|
-
hasPartial,
|
|
33217
|
-
hourCount
|
|
33218
|
-
});
|
|
33219
|
-
return {
|
|
33220
|
-
shiftDuration: hourCount,
|
|
33221
|
-
shiftEndTime: endTime,
|
|
33222
|
-
hasPartialLastHour: hasPartial
|
|
33223
|
-
};
|
|
33224
|
-
}, [shiftEnd, shiftStartTime.decimalHour]);
|
|
33225
|
-
const SHIFT_DURATION = shiftDuration;
|
|
33226
|
-
shiftEndTime ? shiftEndTime.hour : (shiftStartTime.hour + SHIFT_DURATION) % 24;
|
|
33420
|
+
shiftEnd
|
|
33421
|
+
}),
|
|
33422
|
+
[idleTimeHourly, shiftStart, shiftEnd]
|
|
33423
|
+
);
|
|
33424
|
+
const SHIFT_DURATION = idleSlots.length;
|
|
33227
33425
|
const [animatedData, setAnimatedData] = React141__default.useState(
|
|
33228
33426
|
() => Array(SHIFT_DURATION).fill(0)
|
|
33229
33427
|
);
|
|
@@ -33346,121 +33544,22 @@ var HourlyOutputChartComponent = ({
|
|
|
33346
33544
|
}
|
|
33347
33545
|
return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
|
|
33348
33546
|
}, [containerWidth]);
|
|
33349
|
-
const formatHour = React141__default.useCallback((hourIndex) => {
|
|
33350
|
-
const isLastHour = hourIndex === SHIFT_DURATION - 1;
|
|
33351
|
-
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
33352
|
-
const startHour = Math.floor(startDecimalHour) % 24;
|
|
33353
|
-
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
33354
|
-
let endHour, endMinute;
|
|
33355
|
-
if (isLastHour && shiftEndTime) {
|
|
33356
|
-
endHour = shiftEndTime.hour;
|
|
33357
|
-
endMinute = shiftEndTime.minute;
|
|
33358
|
-
} else {
|
|
33359
|
-
const endDecimalHour = startDecimalHour + 1;
|
|
33360
|
-
endHour = Math.floor(endDecimalHour) % 24;
|
|
33361
|
-
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
33362
|
-
}
|
|
33363
|
-
const formatTime5 = (h, m) => {
|
|
33364
|
-
const period = h >= 12 ? "PM" : "AM";
|
|
33365
|
-
const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
33366
|
-
if (m === 0) {
|
|
33367
|
-
return `${hour12}${period}`;
|
|
33368
|
-
}
|
|
33369
|
-
return `${hour12}:${m.toString().padStart(2, "0")}${period}`;
|
|
33370
|
-
};
|
|
33371
|
-
return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
|
|
33372
|
-
}, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
|
|
33373
|
-
const formatTimeRange2 = React141__default.useCallback((hourIndex) => {
|
|
33374
|
-
const isLastHour = hourIndex === SHIFT_DURATION - 1;
|
|
33375
|
-
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
33376
|
-
const startHour = Math.floor(startDecimalHour) % 24;
|
|
33377
|
-
const startMinute = Math.round(startDecimalHour % 1 * 60);
|
|
33378
|
-
let endHour, endMinute;
|
|
33379
|
-
if (isLastHour && shiftEndTime) {
|
|
33380
|
-
endHour = shiftEndTime.hour;
|
|
33381
|
-
endMinute = shiftEndTime.minute;
|
|
33382
|
-
} else {
|
|
33383
|
-
const endDecimalHour = startDecimalHour + 1;
|
|
33384
|
-
endHour = Math.floor(endDecimalHour) % 24;
|
|
33385
|
-
endMinute = Math.round(endDecimalHour % 1 * 60);
|
|
33386
|
-
}
|
|
33387
|
-
const formatTime5 = (h, m) => {
|
|
33388
|
-
const period = h >= 12 ? "PM" : "AM";
|
|
33389
|
-
const hour12 = h === 0 ? 12 : h > 12 ? h - 12 : h;
|
|
33390
|
-
return `${hour12}:${m.toString().padStart(2, "0")} ${period}`;
|
|
33391
|
-
};
|
|
33392
|
-
return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
|
|
33393
|
-
}, [shiftStartTime.decimalHour, SHIFT_DURATION, shiftEndTime]);
|
|
33394
33547
|
const chartData = React141__default.useMemo(() => {
|
|
33395
33548
|
return Array.from({ length: SHIFT_DURATION }, (_, i) => {
|
|
33396
|
-
const
|
|
33397
|
-
const startMinute = shiftStartTime.minute;
|
|
33398
|
-
let idleArray = [];
|
|
33399
|
-
let idleMinutes = 0;
|
|
33400
|
-
if (idleTimeHourly) {
|
|
33401
|
-
if (startMinute > 0) {
|
|
33402
|
-
if (i === 0) {
|
|
33403
|
-
const firstHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
33404
|
-
const nextHour = (actualHour + 1) % 24;
|
|
33405
|
-
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
33406
|
-
idleArray = [
|
|
33407
|
-
...firstHourData.slice(startMinute) || [],
|
|
33408
|
-
...nextHourData.slice(0, startMinute) || []
|
|
33409
|
-
];
|
|
33410
|
-
} else if (i < SHIFT_DURATION - 1) {
|
|
33411
|
-
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
33412
|
-
const nextHour = (actualHour + 1) % 24;
|
|
33413
|
-
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
33414
|
-
idleArray = [
|
|
33415
|
-
...currentHourData.slice(startMinute) || [],
|
|
33416
|
-
...nextHourData.slice(0, startMinute) || []
|
|
33417
|
-
];
|
|
33418
|
-
} else {
|
|
33419
|
-
const hasPartialLastHour2 = shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60;
|
|
33420
|
-
if (hasPartialLastHour2) {
|
|
33421
|
-
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
33422
|
-
const nextHour = (actualHour + 1) % 24;
|
|
33423
|
-
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
33424
|
-
if (startMinute > 0) {
|
|
33425
|
-
const firstPart = currentHourData.slice(startMinute) || [];
|
|
33426
|
-
const secondPart = nextHourData.slice(0, shiftEndTime.minute) || [];
|
|
33427
|
-
idleArray = [...firstPart, ...secondPart];
|
|
33428
|
-
} else {
|
|
33429
|
-
idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
|
|
33430
|
-
}
|
|
33431
|
-
} else {
|
|
33432
|
-
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
33433
|
-
const nextHour = (actualHour + 1) % 24;
|
|
33434
|
-
const nextHourData = idleTimeHourly[nextHour.toString()] || [];
|
|
33435
|
-
idleArray = [
|
|
33436
|
-
...currentHourData.slice(startMinute) || [],
|
|
33437
|
-
...nextHourData.slice(0, startMinute) || []
|
|
33438
|
-
];
|
|
33439
|
-
}
|
|
33440
|
-
}
|
|
33441
|
-
} else {
|
|
33442
|
-
const currentHourData = idleTimeHourly[actualHour.toString()] || [];
|
|
33443
|
-
if (i === SHIFT_DURATION - 1 && shiftEndTime && shiftEndTime.minute > 0 && shiftEndTime.minute < 60) {
|
|
33444
|
-
idleArray = currentHourData.slice(0, shiftEndTime.minute) || [];
|
|
33445
|
-
} else {
|
|
33446
|
-
idleArray = currentHourData || [];
|
|
33447
|
-
}
|
|
33448
|
-
}
|
|
33449
|
-
}
|
|
33450
|
-
idleMinutes = idleArray.filter((val) => val === "1" || val === 1).length;
|
|
33549
|
+
const idleSlot = idleSlots[i];
|
|
33451
33550
|
return {
|
|
33452
|
-
hourIndex: i,
|
|
33453
|
-
hour:
|
|
33454
|
-
timeRange:
|
|
33551
|
+
hourIndex: idleSlot?.hourIndex ?? i,
|
|
33552
|
+
hour: idleSlot?.hour || "",
|
|
33553
|
+
timeRange: idleSlot?.timeRange || "",
|
|
33455
33554
|
output: animatedData[i] || 0,
|
|
33456
33555
|
originalOutput: data[i] || 0,
|
|
33457
33556
|
// Keep original data for labels
|
|
33458
33557
|
color: (animatedData[i] || 0) >= Math.round(pphThreshold) ? "#00AB45" : "#E34329",
|
|
33459
|
-
idleMinutes,
|
|
33460
|
-
idleArray
|
|
33558
|
+
idleMinutes: idleSlot?.idleMinutes || 0,
|
|
33559
|
+
idleArray: idleSlot?.idleArray || []
|
|
33461
33560
|
};
|
|
33462
33561
|
});
|
|
33463
|
-
}, [animatedData, data, pphThreshold,
|
|
33562
|
+
}, [animatedData, data, pphThreshold, idleSlots, SHIFT_DURATION]);
|
|
33464
33563
|
const IdleBar = React141__default.useMemo(() => {
|
|
33465
33564
|
if (!idleBarState.visible) return null;
|
|
33466
33565
|
return /* @__PURE__ */ jsx(
|
|
@@ -33622,36 +33721,11 @@ var HourlyOutputChartComponent = ({
|
|
|
33622
33721
|
content: (props) => {
|
|
33623
33722
|
if (!props.active || !props.payload || props.payload.length === 0) return null;
|
|
33624
33723
|
const data2 = props.payload[0].payload;
|
|
33625
|
-
const
|
|
33626
|
-
|
|
33627
|
-
|
|
33628
|
-
data2.
|
|
33629
|
-
|
|
33630
|
-
if (!currentRange) {
|
|
33631
|
-
currentRange = { start: idx, end: idx };
|
|
33632
|
-
} else {
|
|
33633
|
-
currentRange.end = idx;
|
|
33634
|
-
}
|
|
33635
|
-
} else if (val !== "x" && currentRange) {
|
|
33636
|
-
idleRanges.push(currentRange);
|
|
33637
|
-
currentRange = null;
|
|
33638
|
-
}
|
|
33639
|
-
});
|
|
33640
|
-
if (currentRange) {
|
|
33641
|
-
idleRanges.push(currentRange);
|
|
33642
|
-
}
|
|
33643
|
-
}
|
|
33644
|
-
const formatIdleTimestamp = (minuteIdx) => {
|
|
33645
|
-
const fallbackIndex = chartData.findIndex((item) => item.timeRange === data2.timeRange);
|
|
33646
|
-
const hourOffset = Number.isFinite(data2.hourIndex) ? data2.hourIndex : fallbackIndex;
|
|
33647
|
-
const safeHourOffset = hourOffset >= 0 ? hourOffset : 0;
|
|
33648
|
-
const totalMinutes = (shiftStartTime.hour + safeHourOffset) * 60 + shiftStartTime.minute + minuteIdx;
|
|
33649
|
-
const hour = Math.floor(totalMinutes / 60) % 24;
|
|
33650
|
-
const minute = totalMinutes % 60;
|
|
33651
|
-
const period = hour >= 12 ? "PM" : "AM";
|
|
33652
|
-
const hour12 = hour === 0 ? 12 : hour > 12 ? hour - 12 : hour;
|
|
33653
|
-
return `${hour12}:${minute.toString().padStart(2, "0")} ${period}`;
|
|
33654
|
-
};
|
|
33724
|
+
const idlePeriods = showIdleTime ? getHourlyIdlePeriods({
|
|
33725
|
+
idleArray: data2.idleArray,
|
|
33726
|
+
shiftStart,
|
|
33727
|
+
hourIndex: Number.isFinite(data2.hourIndex) ? data2.hourIndex : 0
|
|
33728
|
+
}) : [];
|
|
33655
33729
|
return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-xl border border-gray-100 p-4 min-w-[220px]", children: [
|
|
33656
33730
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between mb-3", children: /* @__PURE__ */ jsx("p", { className: "font-semibold text-gray-900 text-sm", children: data2.timeRange }) }),
|
|
33657
33731
|
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
@@ -33670,27 +33744,22 @@ var HourlyOutputChartComponent = ({
|
|
|
33670
33744
|
" minutes"
|
|
33671
33745
|
] })
|
|
33672
33746
|
] }) }),
|
|
33673
|
-
|
|
33747
|
+
idlePeriods.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-3 bg-gray-50 rounded-lg p-2.5", children: [
|
|
33674
33748
|
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
|
|
33675
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children:
|
|
33676
|
-
const duration = range.end - range.start + 1;
|
|
33677
|
-
const startTime = formatIdleTimestamp(range.start);
|
|
33678
|
-
const endTime = formatIdleTimestamp(range.end + 1);
|
|
33679
|
-
const fallbackIndex = chartData.findIndex((item) => item.timeRange === data2.timeRange);
|
|
33680
|
-
Number.isFinite(data2.hourIndex) ? data2.hourIndex : fallbackIndex;
|
|
33749
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idlePeriods.map((period, index) => {
|
|
33681
33750
|
return /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
|
|
33682
33751
|
/* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
|
|
33683
|
-
/* @__PURE__ */ jsx("span", { children: duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33684
|
-
startTime,
|
|
33752
|
+
/* @__PURE__ */ jsx("span", { children: period.duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33753
|
+
period.startTime,
|
|
33685
33754
|
" (",
|
|
33686
|
-
duration,
|
|
33755
|
+
period.duration,
|
|
33687
33756
|
" min)"
|
|
33688
33757
|
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
33689
|
-
startTime,
|
|
33758
|
+
period.startTime,
|
|
33690
33759
|
" - ",
|
|
33691
|
-
endTime,
|
|
33760
|
+
period.endTime,
|
|
33692
33761
|
" (",
|
|
33693
|
-
duration,
|
|
33762
|
+
period.duration,
|
|
33694
33763
|
" mins)"
|
|
33695
33764
|
] }) })
|
|
33696
33765
|
] }, index);
|
|
@@ -33845,9 +33914,8 @@ var HourlyOutputChart = React141__default.memo(HourlyOutputChartComponent, (prev
|
|
|
33845
33914
|
HourlyOutputChart.displayName = "HourlyOutputChart";
|
|
33846
33915
|
|
|
33847
33916
|
// src/components/dashboard/grid/videoGridMetricUtils.ts
|
|
33848
|
-
var VIDEO_GRID_LEGEND_LABEL = "7 Minute Efficiency";
|
|
33849
33917
|
var MAP_GRID_LEGEND_LABEL = "Efficiency";
|
|
33850
|
-
var MIXED_VIDEO_GRID_LEGEND_LABEL = "Efficiency";
|
|
33918
|
+
var MIXED_VIDEO_GRID_LEGEND_LABEL = "Flow Efficiency";
|
|
33851
33919
|
var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
33852
33920
|
var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
|
|
33853
33921
|
workspace.video_grid_metric_mode,
|
|
@@ -33946,8 +34014,15 @@ var getVideoGridLegendLabel = (workspaces) => {
|
|
|
33946
34014
|
if (recentFlowEnabledCount === 0) {
|
|
33947
34015
|
return MAP_GRID_LEGEND_LABEL;
|
|
33948
34016
|
}
|
|
34017
|
+
const recentFlowWindows = new Set(
|
|
34018
|
+
visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).map((workspace) => workspace.recent_flow_window_minutes ?? 7).filter((value) => typeof value === "number" && Number.isFinite(value))
|
|
34019
|
+
);
|
|
33949
34020
|
if (recentFlowEnabledCount === visibleWorkspaces.length) {
|
|
33950
|
-
|
|
34021
|
+
if (recentFlowWindows.size === 1) {
|
|
34022
|
+
const [windowMinutes] = Array.from(recentFlowWindows);
|
|
34023
|
+
return `${windowMinutes} Minute Efficiency`;
|
|
34024
|
+
}
|
|
34025
|
+
return MIXED_VIDEO_GRID_LEGEND_LABEL;
|
|
33951
34026
|
}
|
|
33952
34027
|
return MIXED_VIDEO_GRID_LEGEND_LABEL;
|
|
33953
34028
|
};
|
|
@@ -33999,8 +34074,9 @@ var VideoCard = React141__default.memo(({
|
|
|
33999
34074
|
const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
|
|
34000
34075
|
const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
|
|
34001
34076
|
const hasBarMetric = typeof videoGridMetricValue === "number" && Number.isFinite(videoGridMetricValue);
|
|
34077
|
+
const shouldRenderMetricBadge = hasDisplayMetric;
|
|
34002
34078
|
const badgeTitle = hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
|
|
34003
|
-
const badgeLabel =
|
|
34079
|
+
const badgeLabel = `${Math.round(videoGridDisplayValue ?? 0)}%`;
|
|
34004
34080
|
const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
|
|
34005
34081
|
const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
|
|
34006
34082
|
const efficiencyStatus = videoGridColorState === "green" ? "High" : videoGridColorState === "yellow" ? "Medium" : videoGridColorState === "red" ? "Low" : "Neutral";
|
|
@@ -34076,7 +34152,7 @@ var VideoCard = React141__default.memo(({
|
|
|
34076
34152
|
lastSeenText
|
|
34077
34153
|
] })
|
|
34078
34154
|
] }) }),
|
|
34079
|
-
/* @__PURE__ */ jsx("div", { className: `absolute ${compact ? "top-1 right-1" : "top-2 right-2"} z-30`, children: /* @__PURE__ */ jsx(
|
|
34155
|
+
shouldRenderMetricBadge && /* @__PURE__ */ jsx("div", { className: `absolute ${compact ? "top-1 right-1" : "top-2 right-2"} z-30`, children: /* @__PURE__ */ jsx(
|
|
34080
34156
|
"div",
|
|
34081
34157
|
{
|
|
34082
34158
|
"data-testid": "video-card-metric-badge",
|
|
@@ -35893,7 +35969,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
35893
35969
|
idleRanges.push(currentRange);
|
|
35894
35970
|
}
|
|
35895
35971
|
}
|
|
35896
|
-
const
|
|
35972
|
+
const formatIdleTimestamp2 = (minuteIdx) => {
|
|
35897
35973
|
const totalMinutes = (shiftStartTime.hour + data.hourIndex) * 60 + shiftStartTime.minute + minuteIdx;
|
|
35898
35974
|
const hour = Math.floor(totalMinutes / 60) % 24;
|
|
35899
35975
|
const minute = totalMinutes % 60;
|
|
@@ -35923,8 +35999,8 @@ var HourlyUptimeChartComponent = ({
|
|
|
35923
35999
|
/* @__PURE__ */ jsx("p", { className: "font-medium text-gray-700 text-xs mb-2", children: "Idle periods:" }),
|
|
35924
36000
|
/* @__PURE__ */ jsx("div", { className: "space-y-1 max-h-32 overflow-y-auto pr-1", children: idleRanges.map((range, index) => {
|
|
35925
36001
|
const duration = range.end - range.start + 1;
|
|
35926
|
-
const startTime =
|
|
35927
|
-
const endTime =
|
|
36002
|
+
const startTime = formatIdleTimestamp2(range.start);
|
|
36003
|
+
const endTime = formatIdleTimestamp2(range.end + 1);
|
|
35928
36004
|
return /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
|
|
35929
36005
|
/* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
|
|
35930
36006
|
/* @__PURE__ */ jsx("span", { children: duration === 1 ? `${startTime} (${duration} min)` : `${startTime} - ${endTime} (${duration} mins)` })
|
|
@@ -49803,8 +49879,7 @@ var WorkspaceCycleTimeMetricCards = ({
|
|
|
49803
49879
|
{
|
|
49804
49880
|
data: idleTimeData.chartData,
|
|
49805
49881
|
isLoading: idleTimeData.isLoading,
|
|
49806
|
-
error: idleTimeData.error
|
|
49807
|
-
variant: "bar"
|
|
49882
|
+
error: idleTimeData.error
|
|
49808
49883
|
}
|
|
49809
49884
|
) })
|
|
49810
49885
|
] })
|
|
@@ -69172,56 +69247,43 @@ var WorkspaceDetailView = ({
|
|
|
69172
69247
|
const canToggleChartIdleTime = !isUptimeMode && !shouldShowCycleTimeLoadingState && !shouldShowCycleTimeUnavailableState;
|
|
69173
69248
|
const idleClipDate = date || workspace?.date || calculatedOperationalDate || getOperationalDate(timezone);
|
|
69174
69249
|
const idleClipShiftId = parsedShiftId ?? workspace?.shift_id;
|
|
69175
|
-
const
|
|
69176
|
-
|
|
69177
|
-
|
|
69178
|
-
|
|
69179
|
-
|
|
69180
|
-
|
|
69181
|
-
|
|
69182
|
-
|
|
69183
|
-
|
|
69184
|
-
|
|
69185
|
-
|
|
69186
|
-
|
|
69187
|
-
|
|
69188
|
-
|
|
69189
|
-
|
|
69190
|
-
|
|
69191
|
-
|
|
69192
|
-
if (endSlotMins > endTotal) endSlotMins = endTotal;
|
|
69193
|
-
let idleCount = 0;
|
|
69194
|
-
for (let m = startSlotMins; m < endSlotMins; m++) {
|
|
69195
|
-
const hourKey = Math.floor(m / 60) % 24;
|
|
69196
|
-
const minuteKey = m % 60;
|
|
69197
|
-
const hourData = idleTimeHourlyObj[hourKey.toString()] || [];
|
|
69198
|
-
if (Array.isArray(hourData)) {
|
|
69199
|
-
const val = hourData[minuteKey];
|
|
69200
|
-
if (val === 1 || val === "1") {
|
|
69201
|
-
idleCount++;
|
|
69202
|
-
}
|
|
69203
|
-
}
|
|
69204
|
-
}
|
|
69205
|
-
result[i] = idleCount;
|
|
69206
|
-
}
|
|
69207
|
-
return result;
|
|
69208
|
-
}, [shouldShowCycleTimeChart, workspace?.idle_time_hourly, workspace?.shift_start, workspace?.shift_end]);
|
|
69250
|
+
const rawHourlyIdleSlots = useMemo(
|
|
69251
|
+
() => !shouldShowCycleTimeChart || !authoritativeCycleMetrics?.shift_start ? [] : buildHourlyIdleSlots({
|
|
69252
|
+
idleTimeHourly: authoritativeCycleMetrics.idle_time_hourly,
|
|
69253
|
+
shiftStart: authoritativeCycleMetrics.shift_start,
|
|
69254
|
+
shiftEnd: authoritativeCycleMetrics.shift_end
|
|
69255
|
+
}),
|
|
69256
|
+
[
|
|
69257
|
+
shouldShowCycleTimeChart,
|
|
69258
|
+
authoritativeCycleMetrics?.idle_time_hourly,
|
|
69259
|
+
authoritativeCycleMetrics?.shift_start,
|
|
69260
|
+
authoritativeCycleMetrics?.shift_end
|
|
69261
|
+
]
|
|
69262
|
+
);
|
|
69263
|
+
const rawHourlyIdleMinutes = useMemo(
|
|
69264
|
+
() => rawHourlyIdleSlots.map((slot) => slot.idleMinutes),
|
|
69265
|
+
[rawHourlyIdleSlots]
|
|
69266
|
+
);
|
|
69209
69267
|
const hourlyIdleMinutes = useMemo(
|
|
69210
69268
|
() => maskFutureHourlySeries({
|
|
69211
69269
|
data: rawHourlyIdleMinutes,
|
|
69212
|
-
shiftStart:
|
|
69213
|
-
shiftEnd:
|
|
69270
|
+
shiftStart: authoritativeCycleMetrics?.shift_start,
|
|
69271
|
+
shiftEnd: authoritativeCycleMetrics?.shift_end,
|
|
69214
69272
|
shiftDate: idleClipDate,
|
|
69215
69273
|
timezone: effectiveCycleTimeTimezone
|
|
69216
69274
|
}),
|
|
69217
69275
|
[
|
|
69218
69276
|
rawHourlyIdleMinutes,
|
|
69219
|
-
|
|
69220
|
-
|
|
69277
|
+
authoritativeCycleMetrics?.shift_start,
|
|
69278
|
+
authoritativeCycleMetrics?.shift_end,
|
|
69221
69279
|
idleClipDate,
|
|
69222
69280
|
effectiveCycleTimeTimezone
|
|
69223
69281
|
]
|
|
69224
69282
|
);
|
|
69283
|
+
const hourlyIdleSlots = useMemo(
|
|
69284
|
+
() => rawHourlyIdleSlots.map((slot, index) => hourlyIdleMinutes[index] === null ? null : slot),
|
|
69285
|
+
[rawHourlyIdleSlots, hourlyIdleMinutes]
|
|
69286
|
+
);
|
|
69225
69287
|
const cycleTimeUnavailableView = useMemo(() => /* @__PURE__ */ jsxs("div", { className: "w-full h-full rounded-lg border border-amber-200 bg-amber-50/70 px-6 py-5 text-center flex flex-col items-center justify-center", children: [
|
|
69226
69288
|
/* @__PURE__ */ jsx("h4", { className: "text-base font-semibold text-amber-900", children: "Cycle data unavailable" }),
|
|
69227
69289
|
/* @__PURE__ */ jsx("p", { className: "mt-2 max-w-md text-sm text-amber-800", children: "This workstation has cycle-time metrics for the selected shift, but no matching `cycle_completion` clips were found for the chart." }),
|
|
@@ -69777,7 +69839,8 @@ var WorkspaceDetailView = ({
|
|
|
69777
69839
|
xAxisMode: "hourly",
|
|
69778
69840
|
datasetKey: cycleTimeDatasetKey,
|
|
69779
69841
|
showIdleTime: showChartIdleTime,
|
|
69780
|
-
idleTimeData: hourlyIdleMinutes
|
|
69842
|
+
idleTimeData: hourlyIdleMinutes,
|
|
69843
|
+
idleTimeSlots: hourlyIdleSlots
|
|
69781
69844
|
}
|
|
69782
69845
|
) : null : /* @__PURE__ */ jsx(
|
|
69783
69846
|
HourlyOutputChart2,
|
|
@@ -69906,7 +69969,8 @@ var WorkspaceDetailView = ({
|
|
|
69906
69969
|
xAxisMode: "hourly",
|
|
69907
69970
|
datasetKey: cycleTimeDatasetKey,
|
|
69908
69971
|
showIdleTime: showChartIdleTime,
|
|
69909
|
-
idleTimeData: hourlyIdleMinutes
|
|
69972
|
+
idleTimeData: hourlyIdleMinutes,
|
|
69973
|
+
idleTimeSlots: hourlyIdleSlots
|
|
69910
69974
|
}
|
|
69911
69975
|
) : null : /* @__PURE__ */ jsx(
|
|
69912
69976
|
HourlyOutputChart2,
|
|
@@ -76424,7 +76488,7 @@ var formatComparisonWindow = ({
|
|
|
76424
76488
|
shiftMode
|
|
76425
76489
|
}) => {
|
|
76426
76490
|
if (comparisonStrategy === "previous_full_week") return "last week";
|
|
76427
|
-
if (comparisonStrategy === "matched_range" &&
|
|
76491
|
+
if (comparisonStrategy === "matched_range" && currentDayCount === 1 && previousDayCount === 1) {
|
|
76428
76492
|
return "previous day";
|
|
76429
76493
|
}
|
|
76430
76494
|
if (!previousDayCount || !Number.isFinite(previousDayCount)) return "previous range";
|
|
@@ -76447,8 +76511,14 @@ var buildDeltaBadge = (delta, options) => {
|
|
|
76447
76511
|
};
|
|
76448
76512
|
};
|
|
76449
76513
|
var normalizeShiftLabel = (shiftName, shiftMode) => {
|
|
76514
|
+
if (shiftMode === "all") {
|
|
76515
|
+
return "All Shifts";
|
|
76516
|
+
}
|
|
76450
76517
|
const trimmedName = shiftName?.trim();
|
|
76451
76518
|
if (trimmedName) {
|
|
76519
|
+
const normalizedName = trimmedName.toLowerCase();
|
|
76520
|
+
if (normalizedName === "day") return "Day Shift";
|
|
76521
|
+
if (normalizedName === "night") return "Night Shift";
|
|
76452
76522
|
return /shift/i.test(trimmedName) ? trimmedName : `${trimmedName} Shift`;
|
|
76453
76523
|
}
|
|
76454
76524
|
if (shiftMode === "night") return "Night Shift";
|
|
@@ -76457,6 +76527,9 @@ var normalizeShiftLabel = (shiftName, shiftMode) => {
|
|
|
76457
76527
|
var getShiftIcon = (shiftName, shiftMode) => {
|
|
76458
76528
|
const normalizedName = (shiftName || "").toLowerCase();
|
|
76459
76529
|
const normalizedMode = shiftMode || "day";
|
|
76530
|
+
if (normalizedMode === "all") {
|
|
76531
|
+
return /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": true, 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" }) });
|
|
76532
|
+
}
|
|
76460
76533
|
if (normalizedName.includes("day") || normalizedName.includes("morning") || normalizedMode === "day") {
|
|
76461
76534
|
return /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", "aria-hidden": true, 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" }) });
|
|
76462
76535
|
}
|
|
@@ -76535,6 +76608,7 @@ var OperationsOverviewHeader = React141__default.memo(({
|
|
|
76535
76608
|
}) => {
|
|
76536
76609
|
bumpRenderCounter();
|
|
76537
76610
|
const subtitleRange = displayDateRange || dateRange;
|
|
76611
|
+
const showLiveShiftMeta = isLiveScope && trendMode !== "all";
|
|
76538
76612
|
const liveShiftLabel = React141__default.useMemo(
|
|
76539
76613
|
() => normalizeShiftLabel(liveShiftName, trendMode),
|
|
76540
76614
|
[liveShiftName, trendMode]
|
|
@@ -76672,8 +76746,8 @@ var OperationsOverviewHeader = React141__default.memo(({
|
|
|
76672
76746
|
] }),
|
|
76673
76747
|
/* @__PURE__ */ jsxs("div", { className: "mt-1 flex flex-wrap items-center justify-center gap-x-2 gap-y-1 text-[11px] font-medium text-slate-500 min-w-0", children: [
|
|
76674
76748
|
/* @__PURE__ */ jsx("span", { className: "truncate text-center", children: mobileSubtitle }),
|
|
76675
|
-
|
|
76676
|
-
|
|
76749
|
+
showLiveShiftMeta ? /* @__PURE__ */ jsx("span", { className: "text-slate-300", children: "|" }) : null,
|
|
76750
|
+
showLiveShiftMeta ? /* @__PURE__ */ jsx("span", { "data-testid": "operations-overview-live-meta", className: "inline-flex items-center gap-1.5 text-gray-600 min-w-0", children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 justify-center truncate", children: [
|
|
76677
76751
|
/* @__PURE__ */ jsx("span", { className: "opacity-75 shrink-0", children: liveShiftIcon }),
|
|
76678
76752
|
/* @__PURE__ */ jsx("span", { className: "truncate", children: liveShiftLabel })
|
|
76679
76753
|
] }) }) : null
|
|
@@ -76720,7 +76794,7 @@ var OperationsOverviewHeader = React141__default.memo(({
|
|
|
76720
76794
|
] }),
|
|
76721
76795
|
/* @__PURE__ */ jsxs("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-x-3 gap-y-1 text-xs sm:text-sm font-medium text-slate-500 text-center", children: [
|
|
76722
76796
|
/* @__PURE__ */ jsx("span", { children: desktopSubtitle }),
|
|
76723
|
-
|
|
76797
|
+
showLiveShiftMeta ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
76724
76798
|
/* @__PURE__ */ jsx("span", { className: "text-slate-300", children: "|" }),
|
|
76725
76799
|
/* @__PURE__ */ jsx("span", { "data-testid": "operations-overview-live-meta", className: "inline-flex items-center gap-1.5 text-gray-600", children: /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 justify-center", children: [
|
|
76726
76800
|
/* @__PURE__ */ jsx("span", { className: "opacity-75", children: liveShiftIcon }),
|
|
@@ -77294,18 +77368,18 @@ var EfficiencyTrendCard = React141__default.memo(({
|
|
|
77294
77368
|
return (trend.data.points || []).map((point, index) => ({
|
|
77295
77369
|
name: (() => {
|
|
77296
77370
|
const rawLabel = point.label?.trim() || "";
|
|
77297
|
-
if (
|
|
77298
|
-
return rawLabel || `Hour ${index + 1}`;
|
|
77299
|
-
}
|
|
77300
|
-
if (rawLabel && !/^Hour\s+\d+$/i.test(rawLabel)) {
|
|
77371
|
+
if (rawLabel) {
|
|
77301
77372
|
return rawLabel;
|
|
77302
77373
|
}
|
|
77374
|
+
if (!hourlyLabelStartTime) {
|
|
77375
|
+
return "";
|
|
77376
|
+
}
|
|
77303
77377
|
const hourIndex = typeof point.hour_index === "number" ? point.hour_index : index;
|
|
77304
77378
|
const [hoursPart, minutesPart] = hourlyLabelStartTime.split(":");
|
|
77305
77379
|
const startHours = Number(hoursPart);
|
|
77306
77380
|
const startMinutes = Number(minutesPart);
|
|
77307
77381
|
if (!Number.isFinite(startHours) || !Number.isFinite(startMinutes)) {
|
|
77308
|
-
return
|
|
77382
|
+
return "";
|
|
77309
77383
|
}
|
|
77310
77384
|
const totalMinutes = startHours * 60 + startMinutes + hourIndex * 60;
|
|
77311
77385
|
const hour24 = Math.floor(totalMinutes / 60) % 24;
|
|
@@ -77367,6 +77441,12 @@ var EfficiencyTrendCard = React141__default.memo(({
|
|
|
77367
77441
|
if (!dayOfWeek || typeof label !== "string") return label;
|
|
77368
77442
|
return `${label} (${dayOfWeek})`;
|
|
77369
77443
|
}, [isHourlyTrend]);
|
|
77444
|
+
const trendXAxisTickFormatter = React141__default.useCallback((value, index) => {
|
|
77445
|
+
if (!isHourlyTrend) {
|
|
77446
|
+
return typeof value === "string" ? value : String(value ?? "");
|
|
77447
|
+
}
|
|
77448
|
+
return index % 2 === 0 ? typeof value === "string" ? value : String(value ?? "") : "";
|
|
77449
|
+
}, [isHourlyTrend]);
|
|
77370
77450
|
return /* @__PURE__ */ jsxs("div", { className: "bg-white rounded-xl shadow-[0_2px_10px_-3px_rgba(6,81,237,0.1)] border border-slate-100 flex flex-col overflow-hidden text-left", children: [
|
|
77371
77451
|
/* @__PURE__ */ jsx("div", { className: "px-6 py-5 flex-none flex justify-between items-center border-b border-slate-50/50", children: /* @__PURE__ */ jsx("h2", { className: "text-lg font-semibold text-gray-700", children: "Efficiency Trend" }) }),
|
|
77372
77452
|
/* @__PURE__ */ jsx("div", { className: "flex-1 min-h-[250px] w-full p-4 pt-4 relative", children: showInitialSkeleton ? /* @__PURE__ */ jsx(OverviewChartSkeleton, {}) : /* @__PURE__ */ jsx("div", { className: "absolute inset-0 pb-2 pr-4 pl-1", children: /* @__PURE__ */ jsx(
|
|
@@ -77375,6 +77455,8 @@ var EfficiencyTrendCard = React141__default.memo(({
|
|
|
77375
77455
|
data: trendData,
|
|
77376
77456
|
lines: efficiencyLineConfig,
|
|
77377
77457
|
xAxisDataKey: "name",
|
|
77458
|
+
xAxisInterval: isHourlyTrend ? 0 : void 0,
|
|
77459
|
+
xAxisTickFormatter: trendXAxisTickFormatter,
|
|
77378
77460
|
yAxisUnit: "%",
|
|
77379
77461
|
yAxisDomain: [0, 100],
|
|
77380
77462
|
showLegend: false,
|
|
@@ -77880,6 +77962,62 @@ var classifyShiftBucket = ({
|
|
|
77880
77962
|
if (normalizedShiftId === 1) return "night";
|
|
77881
77963
|
return null;
|
|
77882
77964
|
};
|
|
77965
|
+
var getShiftWindowsForConfig = (shiftConfig, timezone) => {
|
|
77966
|
+
if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
|
|
77967
|
+
return shiftConfig.shifts.map((shift) => ({
|
|
77968
|
+
shiftId: shift.shiftId,
|
|
77969
|
+
shiftName: shift.shiftName,
|
|
77970
|
+
startTime: shift.startTime,
|
|
77971
|
+
endTime: shift.endTime
|
|
77972
|
+
}));
|
|
77973
|
+
}
|
|
77974
|
+
const windows = [];
|
|
77975
|
+
if (shiftConfig?.dayShift) {
|
|
77976
|
+
windows.push({
|
|
77977
|
+
shiftId: shiftConfig.dayShift.id ?? 0,
|
|
77978
|
+
shiftName: shiftConfig.dayShift.name || "Day Shift",
|
|
77979
|
+
startTime: shiftConfig.dayShift.startTime || "06:00",
|
|
77980
|
+
endTime: shiftConfig.dayShift.endTime || "18:00"
|
|
77981
|
+
});
|
|
77982
|
+
}
|
|
77983
|
+
if (shiftConfig?.nightShift) {
|
|
77984
|
+
windows.push({
|
|
77985
|
+
shiftId: shiftConfig.nightShift.id ?? 1,
|
|
77986
|
+
shiftName: shiftConfig.nightShift.name || "Night Shift",
|
|
77987
|
+
startTime: shiftConfig.nightShift.startTime || "18:00",
|
|
77988
|
+
endTime: shiftConfig.nightShift.endTime || "06:00"
|
|
77989
|
+
});
|
|
77990
|
+
}
|
|
77991
|
+
if (windows.length > 0) {
|
|
77992
|
+
return windows;
|
|
77993
|
+
}
|
|
77994
|
+
return [
|
|
77995
|
+
{
|
|
77996
|
+
shiftId: 0,
|
|
77997
|
+
shiftName: "Day Shift",
|
|
77998
|
+
startTime: "06:00",
|
|
77999
|
+
endTime: "18:00"
|
|
78000
|
+
},
|
|
78001
|
+
{
|
|
78002
|
+
shiftId: 1,
|
|
78003
|
+
shiftName: "Night Shift",
|
|
78004
|
+
startTime: "18:00",
|
|
78005
|
+
endTime: "06:00"
|
|
78006
|
+
}
|
|
78007
|
+
];
|
|
78008
|
+
};
|
|
78009
|
+
var normalizeShiftWindowMinutes = (startTime, endTime) => {
|
|
78010
|
+
const startMinutes = parseTimeToMinutes3(startTime);
|
|
78011
|
+
const endMinutesRaw = parseTimeToMinutes3(endTime);
|
|
78012
|
+
if (startMinutes === null || endMinutesRaw === null) {
|
|
78013
|
+
return null;
|
|
78014
|
+
}
|
|
78015
|
+
let endMinutes = endMinutesRaw;
|
|
78016
|
+
if (endMinutes <= startMinutes) {
|
|
78017
|
+
endMinutes += 24 * 60;
|
|
78018
|
+
}
|
|
78019
|
+
return { startMinutes, endMinutes };
|
|
78020
|
+
};
|
|
77883
78021
|
var PlantHeadView = () => {
|
|
77884
78022
|
const supabase = useSupabase();
|
|
77885
78023
|
const entityConfig = useEntityConfig();
|
|
@@ -77905,6 +78043,7 @@ var PlantHeadView = () => {
|
|
|
77905
78043
|
const [selectedSupervisorId, setSelectedSupervisorId] = React141__default.useState("all");
|
|
77906
78044
|
const [selectedLineIds, setSelectedLineIds] = React141__default.useState([]);
|
|
77907
78045
|
const [isInitialScopeReady, setIsInitialScopeReady] = React141__default.useState(false);
|
|
78046
|
+
const [shiftResolutionTick, setShiftResolutionTick] = React141__default.useState(0);
|
|
77908
78047
|
const hasAutoInitializedScopeRef = React141__default.useRef(false);
|
|
77909
78048
|
const hasUserAdjustedScopeRef = React141__default.useRef(false);
|
|
77910
78049
|
React141__default.useEffect(() => {
|
|
@@ -78009,34 +78148,151 @@ var PlantHeadView = () => {
|
|
|
78009
78148
|
shiftConfigMap,
|
|
78010
78149
|
isLoading: isShiftConfigLoading
|
|
78011
78150
|
} = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
|
|
78012
|
-
|
|
78013
|
-
|
|
78014
|
-
|
|
78015
|
-
|
|
78016
|
-
|
|
78017
|
-
|
|
78018
|
-
|
|
78019
|
-
|
|
78020
|
-
|
|
78021
|
-
const referenceShiftConfig = referenceLineId ? shiftConfigMap.get(referenceLineId) : null;
|
|
78022
|
-
const normalizedGroupShiftId = normalizeShiftId(group.shiftId);
|
|
78023
|
-
const shiftDefinition = referenceShiftConfig?.shifts?.find((shift) => normalizeShiftId(shift.shiftId) === normalizedGroupShiftId);
|
|
78024
|
-
const resolvedMode = classifyShiftBucket({
|
|
78025
|
-
shiftName: group.shiftName,
|
|
78026
|
-
shiftId: normalizedGroupShiftId,
|
|
78027
|
-
startTime: shiftDefinition?.startTime,
|
|
78028
|
-
endTime: shiftDefinition?.endTime
|
|
78029
|
-
});
|
|
78030
|
-
if (!resolvedMode || resolvedMode === "all") return null;
|
|
78031
|
-
return {
|
|
78032
|
-
date: group.date,
|
|
78033
|
-
trendMode: resolvedMode,
|
|
78034
|
-
shiftName: shiftDefinition?.shiftName || group.shiftName || null
|
|
78151
|
+
React141__default.useEffect(() => {
|
|
78152
|
+
if (scopedLineIds.length === 0 || isShiftConfigLoading) {
|
|
78153
|
+
return;
|
|
78154
|
+
}
|
|
78155
|
+
const intervalId = window.setInterval(() => {
|
|
78156
|
+
setShiftResolutionTick((previous) => previous + 1);
|
|
78157
|
+
}, 6e4);
|
|
78158
|
+
return () => {
|
|
78159
|
+
clearInterval(intervalId);
|
|
78035
78160
|
};
|
|
78036
|
-
}, [
|
|
78161
|
+
}, [isShiftConfigLoading, scopedLineIds.length]);
|
|
78162
|
+
const shiftResolutionNow = React141__default.useMemo(
|
|
78163
|
+
() => /* @__PURE__ */ new Date(),
|
|
78164
|
+
[shiftResolutionTick]
|
|
78165
|
+
);
|
|
78166
|
+
const earliestDayShiftStartTime = React141__default.useMemo(() => {
|
|
78167
|
+
const candidateStarts = [];
|
|
78168
|
+
scopedLineIds.forEach((lineId) => {
|
|
78169
|
+
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
78170
|
+
getShiftWindowsForConfig(shiftConfig).forEach((shift) => {
|
|
78171
|
+
const bucket = classifyShiftBucket({
|
|
78172
|
+
shiftName: shift.shiftName,
|
|
78173
|
+
shiftId: shift.shiftId,
|
|
78174
|
+
startTime: shift.startTime,
|
|
78175
|
+
endTime: shift.endTime
|
|
78176
|
+
});
|
|
78177
|
+
const startMinutes = parseTimeToMinutes3(shift.startTime);
|
|
78178
|
+
if (bucket === "day" && startMinutes !== null) {
|
|
78179
|
+
candidateStarts.push(startMinutes);
|
|
78180
|
+
}
|
|
78181
|
+
});
|
|
78182
|
+
});
|
|
78183
|
+
if (candidateStarts.length === 0) {
|
|
78184
|
+
scopedLineIds.forEach((lineId) => {
|
|
78185
|
+
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
78186
|
+
getShiftWindowsForConfig(shiftConfig).forEach((shift) => {
|
|
78187
|
+
const startMinutes = parseTimeToMinutes3(shift.startTime);
|
|
78188
|
+
if (startMinutes !== null) {
|
|
78189
|
+
candidateStarts.push(startMinutes);
|
|
78190
|
+
}
|
|
78191
|
+
});
|
|
78192
|
+
});
|
|
78193
|
+
}
|
|
78194
|
+
if (candidateStarts.length === 0) {
|
|
78195
|
+
return "06:00";
|
|
78196
|
+
}
|
|
78197
|
+
const earliestMinutes = Math.min(...candidateStarts);
|
|
78198
|
+
const hours = Math.floor(earliestMinutes / 60);
|
|
78199
|
+
const minutes = earliestMinutes % 60;
|
|
78200
|
+
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
78201
|
+
}, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
|
|
78202
|
+
const resolvedOperationalToday = React141__default.useMemo(
|
|
78203
|
+
() => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
|
|
78204
|
+
[appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
|
|
78205
|
+
);
|
|
78206
|
+
const activeLineShiftStates = React141__default.useMemo(() => {
|
|
78207
|
+
return scopedLineIds.flatMap((lineId) => {
|
|
78208
|
+
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
78209
|
+
const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
|
|
78210
|
+
if (!activeShift) {
|
|
78211
|
+
return [];
|
|
78212
|
+
}
|
|
78213
|
+
const trendBucket = classifyShiftBucket({
|
|
78214
|
+
shiftName: activeShift.shiftName,
|
|
78215
|
+
shiftId: activeShift.shiftId,
|
|
78216
|
+
startTime: activeShift.startTime,
|
|
78217
|
+
endTime: activeShift.endTime
|
|
78218
|
+
});
|
|
78219
|
+
if (!trendBucket || trendBucket === "all") {
|
|
78220
|
+
return [];
|
|
78221
|
+
}
|
|
78222
|
+
return [{
|
|
78223
|
+
lineId,
|
|
78224
|
+
trendMode: trendBucket,
|
|
78225
|
+
shiftId: activeShift.shiftId,
|
|
78226
|
+
shiftName: activeShift.shiftName || null,
|
|
78227
|
+
startTime: activeShift.startTime || null,
|
|
78228
|
+
endTime: activeShift.endTime || null,
|
|
78229
|
+
date: activeShift.date
|
|
78230
|
+
}];
|
|
78231
|
+
});
|
|
78232
|
+
}, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
|
|
78233
|
+
const hasActiveDayShiftLine = React141__default.useMemo(
|
|
78234
|
+
() => activeLineShiftStates.some((shift) => shift.trendMode === "day" && shift.date === resolvedOperationalToday),
|
|
78235
|
+
[activeLineShiftStates, resolvedOperationalToday]
|
|
78236
|
+
);
|
|
78237
|
+
const hasActiveNightShiftLine = React141__default.useMemo(
|
|
78238
|
+
() => activeLineShiftStates.some((shift) => shift.trendMode === "night" && shift.date === resolvedOperationalToday),
|
|
78239
|
+
[activeLineShiftStates, resolvedOperationalToday]
|
|
78240
|
+
);
|
|
78241
|
+
const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
|
|
78242
|
+
const hourlyWindowStartTime = React141__default.useMemo(() => {
|
|
78243
|
+
if (scopedLineIds.length === 0) {
|
|
78244
|
+
return null;
|
|
78245
|
+
}
|
|
78246
|
+
const startCandidates = [];
|
|
78247
|
+
const endCandidates = [];
|
|
78248
|
+
scopedLineIds.forEach((lineId) => {
|
|
78249
|
+
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
78250
|
+
getShiftWindowsForConfig(shiftConfig).forEach((shift) => {
|
|
78251
|
+
const bucket = classifyShiftBucket({
|
|
78252
|
+
shiftName: shift.shiftName,
|
|
78253
|
+
shiftId: shift.shiftId,
|
|
78254
|
+
startTime: shift.startTime,
|
|
78255
|
+
endTime: shift.endTime
|
|
78256
|
+
});
|
|
78257
|
+
if (resolvedTrendMode !== "all" && bucket !== resolvedTrendMode) {
|
|
78258
|
+
return;
|
|
78259
|
+
}
|
|
78260
|
+
const normalizedWindow = normalizeShiftWindowMinutes(shift.startTime, shift.endTime);
|
|
78261
|
+
if (!normalizedWindow) {
|
|
78262
|
+
return;
|
|
78263
|
+
}
|
|
78264
|
+
startCandidates.push(normalizedWindow.startMinutes);
|
|
78265
|
+
endCandidates.push(normalizedWindow.endMinutes);
|
|
78266
|
+
});
|
|
78267
|
+
});
|
|
78268
|
+
if (resolvedTrendMode === "all") {
|
|
78269
|
+
const dayStartCandidates = startCandidates.length > 0 ? scopedLineIds.flatMap((lineId) => {
|
|
78270
|
+
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
78271
|
+
return getShiftWindowsForConfig(shiftConfig).map((shift) => {
|
|
78272
|
+
const bucket = classifyShiftBucket({
|
|
78273
|
+
shiftName: shift.shiftName,
|
|
78274
|
+
shiftId: shift.shiftId,
|
|
78275
|
+
startTime: shift.startTime,
|
|
78276
|
+
endTime: shift.endTime
|
|
78277
|
+
});
|
|
78278
|
+
return bucket === "day" ? parseTimeToMinutes3(shift.startTime) : null;
|
|
78279
|
+
}).filter((value) => value !== null);
|
|
78280
|
+
}) : [];
|
|
78281
|
+
if (dayStartCandidates.length > 0) {
|
|
78282
|
+
startCandidates.splice(0, startCandidates.length, ...dayStartCandidates);
|
|
78283
|
+
}
|
|
78284
|
+
}
|
|
78285
|
+
if (startCandidates.length === 0 || endCandidates.length === 0) {
|
|
78286
|
+
return null;
|
|
78287
|
+
}
|
|
78288
|
+
const earliestMinutes = Math.min(...startCandidates);
|
|
78289
|
+
const hours = Math.floor(earliestMinutes / 60);
|
|
78290
|
+
const minutes = earliestMinutes % 60;
|
|
78291
|
+
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
78292
|
+
}, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
|
|
78037
78293
|
const isShiftScopeResolved = React141__default.useMemo(
|
|
78038
|
-
() => !isShiftConfigLoading
|
|
78039
|
-
[
|
|
78294
|
+
() => !isShiftConfigLoading,
|
|
78295
|
+
[isShiftConfigLoading]
|
|
78040
78296
|
);
|
|
78041
78297
|
const initializedTimezoneRef = React141__default.useRef(appTimezone);
|
|
78042
78298
|
React141__default.useEffect(() => {
|
|
@@ -78063,7 +78319,7 @@ var PlantHeadView = () => {
|
|
|
78063
78319
|
return;
|
|
78064
78320
|
}
|
|
78065
78321
|
setDateRange((previous) => {
|
|
78066
|
-
const nextStartKey =
|
|
78322
|
+
const nextStartKey = resolvedOperationalToday || fallbackOperationalDate;
|
|
78067
78323
|
if (previous.startKey === nextStartKey && previous.endKey === nextStartKey) {
|
|
78068
78324
|
return previous;
|
|
78069
78325
|
}
|
|
@@ -78072,11 +78328,11 @@ var PlantHeadView = () => {
|
|
|
78072
78328
|
endKey: nextStartKey
|
|
78073
78329
|
};
|
|
78074
78330
|
});
|
|
78075
|
-
setTrendMode(
|
|
78331
|
+
setTrendMode("all");
|
|
78076
78332
|
setUsesThisWeekComparison(false);
|
|
78077
78333
|
hasAutoInitializedScopeRef.current = true;
|
|
78078
78334
|
setIsInitialScopeReady(true);
|
|
78079
|
-
}, [
|
|
78335
|
+
}, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
|
|
78080
78336
|
const handleDateRangeChange = React141__default.useCallback((range, meta) => {
|
|
78081
78337
|
hasUserAdjustedScopeRef.current = true;
|
|
78082
78338
|
setIsInitialScopeReady(true);
|
|
@@ -78153,45 +78409,36 @@ var PlantHeadView = () => {
|
|
|
78153
78409
|
if (isInitialScopeReady) {
|
|
78154
78410
|
return dateRange;
|
|
78155
78411
|
}
|
|
78156
|
-
const nextStartKey =
|
|
78412
|
+
const nextStartKey = resolvedOperationalToday || fallbackOperationalDate;
|
|
78157
78413
|
return {
|
|
78158
78414
|
startKey: nextStartKey,
|
|
78159
78415
|
endKey: nextStartKey
|
|
78160
78416
|
};
|
|
78161
|
-
}, [
|
|
78417
|
+
}, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
|
|
78162
78418
|
const effectiveTrendMode = React141__default.useMemo(
|
|
78163
|
-
() =>
|
|
78164
|
-
[
|
|
78419
|
+
() => resolvedTrendMode,
|
|
78420
|
+
[resolvedTrendMode]
|
|
78165
78421
|
);
|
|
78166
78422
|
const hourlyLabelStartTime = React141__default.useMemo(() => {
|
|
78167
|
-
if (
|
|
78168
|
-
return null;
|
|
78169
|
-
}
|
|
78170
|
-
const shiftStartTimes = /* @__PURE__ */ new Set();
|
|
78171
|
-
scopedLineIds.forEach((lineId) => {
|
|
78172
|
-
const shiftConfig = shiftConfigMap.get(lineId);
|
|
78173
|
-
const matchingShift = shiftConfig?.shifts?.find((shift) => classifyShiftBucket({
|
|
78174
|
-
shiftName: shift.shiftName,
|
|
78175
|
-
shiftId: shift.shiftId,
|
|
78176
|
-
startTime: shift.startTime,
|
|
78177
|
-
endTime: shift.endTime
|
|
78178
|
-
}) === effectiveTrendMode);
|
|
78179
|
-
if (matchingShift?.startTime) {
|
|
78180
|
-
shiftStartTimes.add(matchingShift.startTime);
|
|
78181
|
-
}
|
|
78182
|
-
});
|
|
78183
|
-
if (shiftStartTimes.size !== 1) {
|
|
78423
|
+
if (scopedLineIds.length === 0) {
|
|
78184
78424
|
return null;
|
|
78185
78425
|
}
|
|
78186
|
-
return
|
|
78187
|
-
}, [
|
|
78188
|
-
const
|
|
78189
|
-
() => effectiveDateRange.startKey === effectiveDateRange.endKey
|
|
78190
|
-
[effectiveDateRange.endKey, effectiveDateRange.startKey
|
|
78426
|
+
return hourlyWindowStartTime;
|
|
78427
|
+
}, [hourlyWindowStartTime, scopedLineIds.length]);
|
|
78428
|
+
const isSingleDayScope = React141__default.useMemo(
|
|
78429
|
+
() => effectiveDateRange.startKey === effectiveDateRange.endKey,
|
|
78430
|
+
[effectiveDateRange.endKey, effectiveDateRange.startKey]
|
|
78191
78431
|
);
|
|
78192
78432
|
const isLiveScope = React141__default.useMemo(
|
|
78193
|
-
() =>
|
|
78194
|
-
[
|
|
78433
|
+
() => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && (effectiveTrendMode === "all" || effectiveTrendMode === "day" && hasActiveDayShiftLine || effectiveTrendMode === "night" && hasActiveNightShiftLine),
|
|
78434
|
+
[
|
|
78435
|
+
effectiveDateRange.startKey,
|
|
78436
|
+
effectiveTrendMode,
|
|
78437
|
+
hasActiveDayShiftLine,
|
|
78438
|
+
hasActiveNightShiftLine,
|
|
78439
|
+
isSingleDayScope,
|
|
78440
|
+
resolvedOperationalToday
|
|
78441
|
+
]
|
|
78195
78442
|
);
|
|
78196
78443
|
const handleOpenLineDetails = React141__default.useCallback((lineId, lineName) => {
|
|
78197
78444
|
trackCoreEvent("Operations Overview Line Clicked", {
|
|
@@ -78226,7 +78473,7 @@ var PlantHeadView = () => {
|
|
|
78226
78473
|
displayDateRange: headerDateRange,
|
|
78227
78474
|
trendMode,
|
|
78228
78475
|
isLiveScope,
|
|
78229
|
-
liveShiftName:
|
|
78476
|
+
liveShiftName: isLiveScope && trendMode !== "all" ? trendMode : null,
|
|
78230
78477
|
lineOptions,
|
|
78231
78478
|
supervisorOptions,
|
|
78232
78479
|
selectedSupervisorId,
|
|
@@ -78761,4 +79008,4 @@ var streamProxyConfig = {
|
|
|
78761
79008
|
}
|
|
78762
79009
|
};
|
|
78763
79010
|
|
|
78764
|
-
export { ACTION_FAMILIES, 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, AvatarUpload, 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, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, 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_HOME_VIEW_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, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, 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, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, 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, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|
|
79011
|
+
export { ACTION_FAMILIES, 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, AvatarUpload, 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, ChangeRoleDialog, ClipFilterProvider, ClipsCostView_default as ClipsCostView, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, 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_HOME_VIEW_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, EFFICIENCY_ON_TRACK_THRESHOLD, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, FittingTitle, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, HourlyUptimeChart, ISTTimer_default as ISTTimer, IdleTimeVlmConfigProvider, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend5 as Legend, LineAssignmentDropdown, 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, MobileMenuProvider, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlantHeadView_default as PlantHeadView, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, SettingsPopup, 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, UptimeDonutChart, UptimeLineChart, UptimeMetricCards, UserAvatar, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceCycleTimeMetricCards, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, alertsService, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, awardsService, buildDateKey, buildKPIsFromLineMetricsRow, buildShiftGroupsKey, canRoleAccessDashboardPath, canRoleAccessTeamManagement, canRoleAssignFactories, canRoleAssignLines, canRoleChangeRole, canRoleInviteRole, canRoleManageCompany, canRoleManageTargets, canRoleManageUsers, canRoleRemoveUser, canRoleViewClipsCost, canRoleViewUsageStats, captureSentryException, captureSentryMessage, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearSentryContext, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStorageService, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatAwardMonth, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration2 as formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getActionDisplayName, getActiveShift, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAssignableRoles, getAssignmentColumnLabel, getAvailableShiftIds, getAwardBadgeType, getAwardDescription, getAwardTitle, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getCurrentWeekFullRange, getCurrentWeekToDateRange, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getInitials, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getRoleAssignmentKind, getRoleDescription, getRoleLabel, getRoleMetadata, getRoleNavPaths, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShiftWorkDurationSeconds, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getVisibleRolesForCurrentUser, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isEfficiencyOnTrack, isFactoryScopedRole, isFullMonthRange, isLegacyConfiguration, isLoopbackHostname, isPrefetchError, isRecentFlowVideoGridMetricMode, isSafari, isSupervisorRole, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWipGatedVideoGridMetricMode, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, lineLeaderboardService, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeActionFamily, normalizeDateKeyRange, normalizeRoleLevel, normalizeVideoGridMetricMode, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, setSentryUserContext, setSentryWorkspaceContext, shouldEnableLocalDevTestLogin, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useClipsInit, useCompanyClipsCost, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHideMobileHeader, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useIdleTimeVlmConfig, useKpiTrends, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMobileMenu, useMonthlyTrend, useMultiLineShiftConfigs, useNavigation, useOperationalShiftKey, useOptionalSupabase, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShiftGroups, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthLastSeen, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, useWorkspaceVideoStreams, userService, videoPrefetchManager, videoPreloader, weeklyTopPerformerService, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
|