@optifye/dashboard-core 6.11.11 → 6.11.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +92 -40
- package/dist/index.d.mts +88 -24
- package/dist/index.d.ts +88 -24
- package/dist/index.js +1466 -694
- package/dist/index.mjs +1460 -693
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11,8 +11,8 @@ var events = require('events');
|
|
|
11
11
|
var supabaseJs = require('@supabase/supabase-js');
|
|
12
12
|
var Hls = require('hls.js');
|
|
13
13
|
var useSWR = require('swr');
|
|
14
|
-
var motionUtils = require('motion-utils');
|
|
15
14
|
var lucideReact = require('lucide-react');
|
|
15
|
+
var motionUtils = require('motion-utils');
|
|
16
16
|
var recharts = require('recharts');
|
|
17
17
|
var reactSlot = require('@radix-ui/react-slot');
|
|
18
18
|
var SelectPrimitive = require('@radix-ui/react-select');
|
|
@@ -3446,6 +3446,25 @@ function isValidFactoryViewConfiguration(entityConfig) {
|
|
|
3446
3446
|
return lineIds.length > 0;
|
|
3447
3447
|
}
|
|
3448
3448
|
|
|
3449
|
+
// src/lib/constants/videoGridMetricMode.ts
|
|
3450
|
+
var VALID_VIDEO_GRID_METRIC_MODES = /* @__PURE__ */ new Set([
|
|
3451
|
+
"efficiency",
|
|
3452
|
+
"recent_flow",
|
|
3453
|
+
"recent_flow_wip_gated"
|
|
3454
|
+
]);
|
|
3455
|
+
var normalizeVideoGridMetricMode = (value, assemblyEnabled = false) => {
|
|
3456
|
+
const normalized = typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
3457
|
+
if (VALID_VIDEO_GRID_METRIC_MODES.has(normalized)) {
|
|
3458
|
+
return normalized;
|
|
3459
|
+
}
|
|
3460
|
+
return assemblyEnabled ? "recent_flow_wip_gated" : "efficiency";
|
|
3461
|
+
};
|
|
3462
|
+
var isRecentFlowVideoGridMetricMode = (value, assemblyEnabled = false) => {
|
|
3463
|
+
const normalized = normalizeVideoGridMetricMode(value, assemblyEnabled);
|
|
3464
|
+
return normalized === "recent_flow" || normalized === "recent_flow_wip_gated";
|
|
3465
|
+
};
|
|
3466
|
+
var isWipGatedVideoGridMetricMode = (value, assemblyEnabled = false) => normalizeVideoGridMetricMode(value, assemblyEnabled) === "recent_flow_wip_gated";
|
|
3467
|
+
|
|
3449
3468
|
// src/lib/services/lineMetricsSelection.ts
|
|
3450
3469
|
var toTimestamp = (value) => {
|
|
3451
3470
|
if (typeof value !== "string") return 0;
|
|
@@ -3907,7 +3926,7 @@ var dashboardService = {
|
|
|
3907
3926
|
company_name: data.company_name || "Company X",
|
|
3908
3927
|
date: data.date,
|
|
3909
3928
|
shift_id: data.shift_id,
|
|
3910
|
-
action_name: data.action_name || "",
|
|
3929
|
+
action_name: data.action_display_name || data.action_name || "",
|
|
3911
3930
|
shift_start: data.shift_start || (data.shift_id === (shiftConfig.dayShift?.id ?? 0) ? shiftConfig.dayShift?.startTime : shiftConfig.nightShift?.startTime) || "00:00",
|
|
3912
3931
|
shift_end: data.shift_end || (data.shift_id === (shiftConfig.dayShift?.id ?? 0) ? shiftConfig.dayShift?.endTime : shiftConfig.nightShift?.endTime) || "00:00",
|
|
3913
3932
|
shift_type: data.shift_type || (data.shift_id === (shiftConfig.dayShift?.id ?? 0) ? "Day" : "Night"),
|
|
@@ -3976,7 +3995,9 @@ var dashboardService = {
|
|
|
3976
3995
|
company_id,
|
|
3977
3996
|
companies!lines_company_id_fkey(company_name:name),
|
|
3978
3997
|
enable,
|
|
3979
|
-
monitoring_mode
|
|
3998
|
+
monitoring_mode,
|
|
3999
|
+
assembly,
|
|
4000
|
+
video_grid_metric_mode
|
|
3980
4001
|
`).eq("enable", true);
|
|
3981
4002
|
if (companyId) {
|
|
3982
4003
|
query = query.eq("company_id", companyId);
|
|
@@ -3996,7 +4017,12 @@ var dashboardService = {
|
|
|
3996
4017
|
company_name: line.companies?.company_name ?? "N/A",
|
|
3997
4018
|
enable: line.enable ?? true,
|
|
3998
4019
|
// Default to true if not specified
|
|
3999
|
-
monitoring_mode: line.monitoring_mode ?? "output"
|
|
4020
|
+
monitoring_mode: line.monitoring_mode ?? "output",
|
|
4021
|
+
assembly: line.assembly ?? false,
|
|
4022
|
+
video_grid_metric_mode: normalizeVideoGridMetricMode(
|
|
4023
|
+
line.video_grid_metric_mode,
|
|
4024
|
+
line.assembly ?? false
|
|
4025
|
+
)
|
|
4000
4026
|
}));
|
|
4001
4027
|
return transformedLines;
|
|
4002
4028
|
} catch (err) {
|
|
@@ -4033,7 +4059,7 @@ var dashboardService = {
|
|
|
4033
4059
|
}
|
|
4034
4060
|
const lineIdsToQuery = configuredLineIds;
|
|
4035
4061
|
const [line1Result, metricsResult2] = await Promise.all([
|
|
4036
|
-
supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", defaultLineId).single(),
|
|
4062
|
+
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(),
|
|
4037
4063
|
supabase.from(lineMetricsTable).select("*").in("line_id", lineIdsToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
|
|
4038
4064
|
]);
|
|
4039
4065
|
if (line1Result.error) throw line1Result.error;
|
|
@@ -4112,7 +4138,7 @@ var dashboardService = {
|
|
|
4112
4138
|
throw new Error("Company ID must be configured for detailed line requests.");
|
|
4113
4139
|
}
|
|
4114
4140
|
const [lineResult, metricsResult] = await Promise.all([
|
|
4115
|
-
supabase.from(linesTable).select("id, line_name, factory_id, monitoring_mode, factories!lines_factory_id_fkey(factory_name), company_id, companies!lines_company_id_fkey(company_name:name)").eq("id", lineIdToQuery).single(),
|
|
4141
|
+
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(),
|
|
4116
4142
|
supabase.from(lineMetricsTable).select("*").eq("line_id", lineIdToQuery).eq("shift_id", queryShiftId).eq("date", queryDate)
|
|
4117
4143
|
]);
|
|
4118
4144
|
if (lineResult.error) throw lineResult.error;
|
|
@@ -4928,25 +4954,25 @@ var workspaceService = {
|
|
|
4928
4954
|
if (!configuredFactoryId) {
|
|
4929
4955
|
throw new Error("Factory ID (entityConfig.factoryId) must be configured to update line thresholds.");
|
|
4930
4956
|
}
|
|
4931
|
-
let outputWorkspaces = workspaces.filter((ws) => ws.action_type === "
|
|
4957
|
+
let outputWorkspaces = workspaces.filter((ws) => ws.action_type === "output");
|
|
4932
4958
|
if (outputWorkspaces.length === 0) {
|
|
4933
|
-
const
|
|
4934
|
-
const
|
|
4959
|
+
const outputKeywords = ["output", "packaging", "package", "packing", "pack"];
|
|
4960
|
+
const possibleOutputWorkspaces = workspaces.filter((ws) => {
|
|
4935
4961
|
if (ws.workspace_id && typeof ws.workspace_id === "string") {
|
|
4936
4962
|
const wsIdLower = ws.workspace_id.toLowerCase();
|
|
4937
|
-
return
|
|
4963
|
+
return outputKeywords.some((keyword) => wsIdLower.includes(keyword));
|
|
4938
4964
|
}
|
|
4939
4965
|
return false;
|
|
4940
4966
|
});
|
|
4941
|
-
if (
|
|
4942
|
-
outputWorkspaces =
|
|
4967
|
+
if (possibleOutputWorkspaces.length > 0) {
|
|
4968
|
+
outputWorkspaces = possibleOutputWorkspaces;
|
|
4943
4969
|
} else {
|
|
4944
|
-
console.warn("[WorkspaceService] Unable to determine
|
|
4970
|
+
console.warn("[WorkspaceService] Unable to determine output-family workspaces for threshold calculation. Using all workspaces.");
|
|
4945
4971
|
outputWorkspaces = workspaces;
|
|
4946
4972
|
}
|
|
4947
4973
|
}
|
|
4948
4974
|
if (outputWorkspaces.length === 0 && workspaces.length > 0) {
|
|
4949
|
-
console.warn('[WorkspaceService] No workspaces with action_type "
|
|
4975
|
+
console.warn('[WorkspaceService] No workspaces with action_type "output" found for line threshold calculation. Thresholds might be zero.');
|
|
4950
4976
|
}
|
|
4951
4977
|
const totalDayOutput = outputWorkspaces.reduce((sum, ws) => sum + (ws.action_total_day_output || 0), 0);
|
|
4952
4978
|
const totalPPH = outputWorkspaces.reduce((sum, ws) => sum + (ws.action_pph_threshold || 0), 0);
|
|
@@ -8466,7 +8492,11 @@ var LinesService = class {
|
|
|
8466
8492
|
createdAt: line.created_at,
|
|
8467
8493
|
factoryId: line.factory_id,
|
|
8468
8494
|
monitoringMode: line.monitoring_mode ?? "output",
|
|
8469
|
-
assembly: line.assembly ?? false
|
|
8495
|
+
assembly: line.assembly ?? false,
|
|
8496
|
+
videoGridMetricMode: normalizeVideoGridMetricMode(
|
|
8497
|
+
line.video_grid_metric_mode,
|
|
8498
|
+
line.assembly ?? false
|
|
8499
|
+
)
|
|
8470
8500
|
}));
|
|
8471
8501
|
} catch (error) {
|
|
8472
8502
|
console.error("Error fetching lines:", error);
|
|
@@ -8510,7 +8540,11 @@ var LinesService = class {
|
|
|
8510
8540
|
createdAt: line.created_at,
|
|
8511
8541
|
factoryId: line.factory_id,
|
|
8512
8542
|
monitoringMode: line.monitoring_mode ?? "output",
|
|
8513
|
-
assembly: line.assembly ?? false
|
|
8543
|
+
assembly: line.assembly ?? false,
|
|
8544
|
+
videoGridMetricMode: normalizeVideoGridMetricMode(
|
|
8545
|
+
line.video_grid_metric_mode,
|
|
8546
|
+
line.assembly ?? false
|
|
8547
|
+
)
|
|
8514
8548
|
}));
|
|
8515
8549
|
} catch (error) {
|
|
8516
8550
|
console.error("Error fetching all lines:", error);
|
|
@@ -8562,7 +8596,12 @@ var LinesService = class {
|
|
|
8562
8596
|
isActive: data.enable,
|
|
8563
8597
|
createdAt: data.created_at,
|
|
8564
8598
|
factoryId: data.factory_id,
|
|
8565
|
-
monitoringMode: data.monitoring_mode ?? "output"
|
|
8599
|
+
monitoringMode: data.monitoring_mode ?? "output",
|
|
8600
|
+
assembly: data.assembly ?? false,
|
|
8601
|
+
videoGridMetricMode: normalizeVideoGridMetricMode(
|
|
8602
|
+
data.video_grid_metric_mode,
|
|
8603
|
+
data.assembly ?? false
|
|
8604
|
+
)
|
|
8566
8605
|
};
|
|
8567
8606
|
} catch (error) {
|
|
8568
8607
|
console.error("Error fetching line:", error);
|
|
@@ -9703,78 +9742,6 @@ var createStorageService = (supabase) => ({
|
|
|
9703
9742
|
}
|
|
9704
9743
|
});
|
|
9705
9744
|
|
|
9706
|
-
// src/lib/constants/idleTimeColors.ts
|
|
9707
|
-
var IDLE_TIME_REASON_COLORS = {
|
|
9708
|
-
"Operator Absent": {
|
|
9709
|
-
hex: "#dc2626",
|
|
9710
|
-
// red-600 - Critical/Urgent
|
|
9711
|
-
text: "text-red-600",
|
|
9712
|
-
bg: "bg-red-50",
|
|
9713
|
-
border: "border-red-200"
|
|
9714
|
-
},
|
|
9715
|
-
"No Material": {
|
|
9716
|
-
hex: "#f59e0b",
|
|
9717
|
-
// amber-500 - Warning/Supply Chain
|
|
9718
|
-
text: "text-amber-600",
|
|
9719
|
-
bg: "bg-amber-50",
|
|
9720
|
-
border: "border-amber-200"
|
|
9721
|
-
},
|
|
9722
|
-
"Machine Downtime": {
|
|
9723
|
-
hex: "#3b82f6",
|
|
9724
|
-
// blue-500 - Scheduled/Technical
|
|
9725
|
-
text: "text-blue-600",
|
|
9726
|
-
bg: "bg-blue-50",
|
|
9727
|
-
border: "border-blue-200"
|
|
9728
|
-
},
|
|
9729
|
-
"Operator Idle": {
|
|
9730
|
-
hex: "#8b5cf6",
|
|
9731
|
-
// violet-500 - Low Priority/Behavioral
|
|
9732
|
-
text: "text-violet-600",
|
|
9733
|
-
bg: "bg-violet-50",
|
|
9734
|
-
border: "border-violet-200"
|
|
9735
|
-
}
|
|
9736
|
-
};
|
|
9737
|
-
var FALLBACK_HEX_COLORS = [
|
|
9738
|
-
"#dc2626",
|
|
9739
|
-
// red-600
|
|
9740
|
-
"#ea580c",
|
|
9741
|
-
// orange-600
|
|
9742
|
-
"#ca8a04",
|
|
9743
|
-
// yellow-600
|
|
9744
|
-
"#16a34a",
|
|
9745
|
-
// green-600
|
|
9746
|
-
"#0891b2",
|
|
9747
|
-
// cyan-600
|
|
9748
|
-
"#2563eb",
|
|
9749
|
-
// blue-600
|
|
9750
|
-
"#7c3aed",
|
|
9751
|
-
// violet-600
|
|
9752
|
-
"#c026d3"
|
|
9753
|
-
// fuchsia-600
|
|
9754
|
-
];
|
|
9755
|
-
var DEFAULT_CONFIG3 = {
|
|
9756
|
-
hex: "#9ca3af",
|
|
9757
|
-
text: "text-gray-500",
|
|
9758
|
-
bg: "bg-gray-50",
|
|
9759
|
-
border: "border-gray-200"
|
|
9760
|
-
};
|
|
9761
|
-
function getIdleTimeReasonColor(reason, index = 0) {
|
|
9762
|
-
const normalizedReason = reason.includes("_") ? reason.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ") : reason;
|
|
9763
|
-
if (IDLE_TIME_REASON_COLORS[normalizedReason]) {
|
|
9764
|
-
return IDLE_TIME_REASON_COLORS[normalizedReason];
|
|
9765
|
-
}
|
|
9766
|
-
const lowerReason = normalizedReason.toLowerCase();
|
|
9767
|
-
const foundKey = Object.keys(IDLE_TIME_REASON_COLORS).find((k) => k.toLowerCase() === lowerReason);
|
|
9768
|
-
if (foundKey) {
|
|
9769
|
-
return IDLE_TIME_REASON_COLORS[foundKey];
|
|
9770
|
-
}
|
|
9771
|
-
const fallbackHex = FALLBACK_HEX_COLORS[index % FALLBACK_HEX_COLORS.length];
|
|
9772
|
-
return {
|
|
9773
|
-
...DEFAULT_CONFIG3,
|
|
9774
|
-
hex: fallbackHex
|
|
9775
|
-
};
|
|
9776
|
-
}
|
|
9777
|
-
|
|
9778
9745
|
// src/lib/services/idleTimeReasonService.ts
|
|
9779
9746
|
async function fetchIdleTimeReasons(params) {
|
|
9780
9747
|
const { workspaceId, lineId, date, shiftId, startDate, endDate, token } = params;
|
|
@@ -9832,7 +9799,12 @@ async function fetchIdleTimeReasons(params) {
|
|
|
9832
9799
|
}
|
|
9833
9800
|
function transformToChartData(data) {
|
|
9834
9801
|
return data.reasons.map((reason) => ({
|
|
9835
|
-
name: formatReasonLabel(reason.reason),
|
|
9802
|
+
name: reason.display_name || formatReasonLabel(reason.reason_key || reason.reason),
|
|
9803
|
+
reasonKey: reason.reason_key || reason.reason,
|
|
9804
|
+
displayName: reason.display_name || formatReasonLabel(reason.reason_key || reason.reason),
|
|
9805
|
+
paletteToken: reason.palette_token,
|
|
9806
|
+
iconToken: reason.icon_token,
|
|
9807
|
+
isKnown: reason.is_known,
|
|
9836
9808
|
value: reason.percentage,
|
|
9837
9809
|
totalDurationSeconds: reason.total_duration_seconds,
|
|
9838
9810
|
efficiencyLossPercentage: reason.efficiency_loss_percentage ?? null
|
|
@@ -9841,9 +9813,6 @@ function transformToChartData(data) {
|
|
|
9841
9813
|
function formatReasonLabel(reason) {
|
|
9842
9814
|
return reason.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
9843
9815
|
}
|
|
9844
|
-
function getReasonColor(reason, index = 0) {
|
|
9845
|
-
return getIdleTimeReasonColor(reason, index).hex;
|
|
9846
|
-
}
|
|
9847
9816
|
|
|
9848
9817
|
// src/lib/services/sessionTracker.ts
|
|
9849
9818
|
function generateSessionId() {
|
|
@@ -11566,6 +11535,52 @@ var workspaceMetricsStore = {
|
|
|
11566
11535
|
}
|
|
11567
11536
|
};
|
|
11568
11537
|
|
|
11538
|
+
// src/lib/constants/actions.ts
|
|
11539
|
+
var ACTION_NAMES = {
|
|
11540
|
+
/** Assembly operations */
|
|
11541
|
+
ASSEMBLY: "Assembly",
|
|
11542
|
+
/** Packaging operations */
|
|
11543
|
+
PACKAGING: "Packaging",
|
|
11544
|
+
/** Output operations (user-facing label for the legacy packaging family) */
|
|
11545
|
+
OUTPUT: "Output",
|
|
11546
|
+
/** Inspection operations */
|
|
11547
|
+
INSPECTION: "Inspection",
|
|
11548
|
+
/** Testing operations */
|
|
11549
|
+
TESTING: "Testing",
|
|
11550
|
+
/** Quality control operations */
|
|
11551
|
+
QUALITY_CONTROL: "Quality Control"
|
|
11552
|
+
};
|
|
11553
|
+
var ACTION_FAMILIES = {
|
|
11554
|
+
ASSEMBLY: "assembly",
|
|
11555
|
+
OUTPUT: "output",
|
|
11556
|
+
OTHER: "other"
|
|
11557
|
+
};
|
|
11558
|
+
var normalizeActionFamily = (params) => {
|
|
11559
|
+
const explicitValue = (params.actionFamily ?? params.actionType ?? "").trim().toLowerCase();
|
|
11560
|
+
if (explicitValue === ACTION_FAMILIES.ASSEMBLY) return ACTION_FAMILIES.ASSEMBLY;
|
|
11561
|
+
if (explicitValue === ACTION_FAMILIES.OUTPUT || explicitValue === "packaging") {
|
|
11562
|
+
return ACTION_FAMILIES.OUTPUT;
|
|
11563
|
+
}
|
|
11564
|
+
if (explicitValue === ACTION_FAMILIES.OTHER) return ACTION_FAMILIES.OTHER;
|
|
11565
|
+
const normalizedName = (params.actionName ?? "").trim().toLowerCase();
|
|
11566
|
+
if (!normalizedName) return null;
|
|
11567
|
+
if (normalizedName === "output" || normalizedName.includes("packag")) {
|
|
11568
|
+
return ACTION_FAMILIES.OUTPUT;
|
|
11569
|
+
}
|
|
11570
|
+
if (normalizedName.includes("assembly")) {
|
|
11571
|
+
return ACTION_FAMILIES.ASSEMBLY;
|
|
11572
|
+
}
|
|
11573
|
+
return ACTION_FAMILIES.OTHER;
|
|
11574
|
+
};
|
|
11575
|
+
var getActionDisplayName = (params) => {
|
|
11576
|
+
const explicitDisplayName = (params.displayName ?? "").trim();
|
|
11577
|
+
if (explicitDisplayName) return explicitDisplayName;
|
|
11578
|
+
const family = normalizeActionFamily(params);
|
|
11579
|
+
if (family === ACTION_FAMILIES.OUTPUT) return ACTION_NAMES.OUTPUT;
|
|
11580
|
+
if (family === ACTION_FAMILIES.ASSEMBLY) return ACTION_NAMES.ASSEMBLY;
|
|
11581
|
+
return (params.actionName ?? "").trim();
|
|
11582
|
+
};
|
|
11583
|
+
|
|
11569
11584
|
// src/lib/utils/workspaceMetricsTransform.ts
|
|
11570
11585
|
var coerceNumber = (value, fallback = 0) => {
|
|
11571
11586
|
const num = typeof value === "number" ? value : Number(value);
|
|
@@ -11755,10 +11770,17 @@ var toWorkspaceDetailedMetrics = ({
|
|
|
11755
11770
|
const targetOutput = coerceNumber(data.target_output ?? data.total_day_output, 0);
|
|
11756
11771
|
const idealOutput = coerceNumber(data.ideal_output ?? data.ideal_output_until_now, 0);
|
|
11757
11772
|
const outputDifference = totalActions - idealOutput;
|
|
11773
|
+
const hourlyCycleTimes = Array.isArray(data.hourly_cycle_times) ? data.hourly_cycle_times.map((value) => coerceNumber(value, 0)) : [];
|
|
11758
11774
|
const totalWorkspacesValue = coerceNumber(
|
|
11759
11775
|
data.total_workspaces ?? lineMetricsById?.[data.line_id || ""]?.total_workspaces ?? workspaceConfig.totalWorkspaces,
|
|
11760
11776
|
0
|
|
11761
11777
|
);
|
|
11778
|
+
const actionFamily = normalizeActionFamily({
|
|
11779
|
+
actionFamily: data.action_family,
|
|
11780
|
+
actionType: data.action_type,
|
|
11781
|
+
actionName: data.action_name
|
|
11782
|
+
});
|
|
11783
|
+
const actionType = actionFamily === "assembly" || actionFamily === "output" ? actionFamily : null;
|
|
11762
11784
|
return {
|
|
11763
11785
|
workspace_id: data.workspace_id,
|
|
11764
11786
|
workspace_name: data.workspace_name,
|
|
@@ -11769,8 +11791,20 @@ var toWorkspaceDetailedMetrics = ({
|
|
|
11769
11791
|
company_name: data.company_name || "",
|
|
11770
11792
|
date: data.date,
|
|
11771
11793
|
shift_id: shiftId,
|
|
11772
|
-
action_name:
|
|
11773
|
-
|
|
11794
|
+
action_name: getActionDisplayName({
|
|
11795
|
+
displayName: data.action_display_name,
|
|
11796
|
+
actionFamily: data.action_family,
|
|
11797
|
+
actionType: data.action_type,
|
|
11798
|
+
actionName: data.action_name
|
|
11799
|
+
}),
|
|
11800
|
+
action_type: actionType,
|
|
11801
|
+
action_family: actionFamily,
|
|
11802
|
+
action_display_name: getActionDisplayName({
|
|
11803
|
+
displayName: data.action_display_name,
|
|
11804
|
+
actionFamily: data.action_family,
|
|
11805
|
+
actionType: data.action_type,
|
|
11806
|
+
actionName: data.action_name
|
|
11807
|
+
}),
|
|
11774
11808
|
shift_start: shiftStart,
|
|
11775
11809
|
shift_end: shiftEnd,
|
|
11776
11810
|
shift_type: shiftType,
|
|
@@ -11783,6 +11817,7 @@ var toWorkspaceDetailedMetrics = ({
|
|
|
11783
11817
|
avg_efficiency: coerceNumber(data.efficiency ?? data.avg_efficiency, 0),
|
|
11784
11818
|
total_actions: totalActions,
|
|
11785
11819
|
hourly_action_counts: hourlyActionCounts,
|
|
11820
|
+
hourly_cycle_times: hourlyCycleTimes,
|
|
11786
11821
|
workspace_rank: coerceNumber(data.workspace_rank, 0),
|
|
11787
11822
|
total_workspaces: totalWorkspacesValue,
|
|
11788
11823
|
ideal_output_until_now: idealOutput,
|
|
@@ -13321,6 +13356,12 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13321
13356
|
const transformedWorkspaceData = allWorkspaceMetrics.map((item) => {
|
|
13322
13357
|
const idleTimeValue = typeof item.idle_time === "number" ? item.idle_time : Number(item.idle_time);
|
|
13323
13358
|
const idleTimeSeconds = Number.isFinite(idleTimeValue) ? idleTimeValue : void 0;
|
|
13359
|
+
const actionFamily = normalizeActionFamily({
|
|
13360
|
+
actionFamily: item.action_family,
|
|
13361
|
+
actionType: item.action_type,
|
|
13362
|
+
actionName: item.action_name
|
|
13363
|
+
});
|
|
13364
|
+
const actionType = actionFamily === "assembly" || actionFamily === "output" ? actionFamily : null;
|
|
13324
13365
|
return {
|
|
13325
13366
|
company_id: item.company_id || companyId,
|
|
13326
13367
|
line_id: item.line_id,
|
|
@@ -13340,7 +13381,18 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13340
13381
|
monitoring_mode: item.monitoring_mode ?? void 0,
|
|
13341
13382
|
idle_time: idleTimeSeconds,
|
|
13342
13383
|
assembly_enabled: item.assembly_enabled ?? false,
|
|
13343
|
-
|
|
13384
|
+
video_grid_metric_mode: normalizeVideoGridMetricMode(
|
|
13385
|
+
item.video_grid_metric_mode,
|
|
13386
|
+
item.assembly_enabled ?? false
|
|
13387
|
+
),
|
|
13388
|
+
action_type: actionType,
|
|
13389
|
+
action_family: actionFamily,
|
|
13390
|
+
action_display_name: getActionDisplayName({
|
|
13391
|
+
displayName: item.action_display_name,
|
|
13392
|
+
actionFamily: item.action_family,
|
|
13393
|
+
actionType: item.action_type,
|
|
13394
|
+
actionName: item.action_name
|
|
13395
|
+
}),
|
|
13344
13396
|
recent_flow_mode: item.recent_flow_mode ?? void 0,
|
|
13345
13397
|
recent_flow_percent: item.recent_flow_percent ?? null,
|
|
13346
13398
|
recent_flow_actual_rate_pph: item.recent_flow_actual_rate_pph ?? null,
|
|
@@ -19260,8 +19312,115 @@ function useIdleTimeReasons({
|
|
|
19260
19312
|
refetch: fetchData
|
|
19261
19313
|
};
|
|
19262
19314
|
}
|
|
19315
|
+
var DEFAULT_PALETTE_TOKEN = "slate";
|
|
19316
|
+
var DEFAULT_ICON_TOKEN = "help-circle";
|
|
19317
|
+
var PALETTE_CONFIG = {
|
|
19318
|
+
red: {
|
|
19319
|
+
hex: "#dc2626",
|
|
19320
|
+
textClass: "text-red-600",
|
|
19321
|
+
bgClass: "bg-red-50",
|
|
19322
|
+
borderClass: "border-red-200"
|
|
19323
|
+
},
|
|
19324
|
+
amber: {
|
|
19325
|
+
hex: "#f59e0b",
|
|
19326
|
+
textClass: "text-amber-600",
|
|
19327
|
+
bgClass: "bg-amber-50",
|
|
19328
|
+
borderClass: "border-amber-200"
|
|
19329
|
+
},
|
|
19330
|
+
blue: {
|
|
19331
|
+
hex: "#3b82f6",
|
|
19332
|
+
textClass: "text-blue-600",
|
|
19333
|
+
bgClass: "bg-blue-50",
|
|
19334
|
+
borderClass: "border-blue-200"
|
|
19335
|
+
},
|
|
19336
|
+
violet: {
|
|
19337
|
+
hex: "#8b5cf6",
|
|
19338
|
+
textClass: "text-violet-600",
|
|
19339
|
+
bgClass: "bg-violet-50",
|
|
19340
|
+
borderClass: "border-violet-200"
|
|
19341
|
+
},
|
|
19342
|
+
emerald: {
|
|
19343
|
+
hex: "#10b981",
|
|
19344
|
+
textClass: "text-emerald-600",
|
|
19345
|
+
bgClass: "bg-emerald-50",
|
|
19346
|
+
borderClass: "border-emerald-200"
|
|
19347
|
+
},
|
|
19348
|
+
cyan: {
|
|
19349
|
+
hex: "#0891b2",
|
|
19350
|
+
textClass: "text-cyan-600",
|
|
19351
|
+
bgClass: "bg-cyan-50",
|
|
19352
|
+
borderClass: "border-cyan-200"
|
|
19353
|
+
},
|
|
19354
|
+
slate: {
|
|
19355
|
+
hex: "#64748b",
|
|
19356
|
+
textClass: "text-slate-600",
|
|
19357
|
+
bgClass: "bg-slate-50",
|
|
19358
|
+
borderClass: "border-slate-200"
|
|
19359
|
+
}
|
|
19360
|
+
};
|
|
19361
|
+
var ICON_CONFIG = {
|
|
19362
|
+
"alert-triangle": lucideReact.AlertTriangle,
|
|
19363
|
+
"refresh-cw": lucideReact.RefreshCw,
|
|
19364
|
+
package: lucideReact.Package,
|
|
19365
|
+
clock: lucideReact.Clock,
|
|
19366
|
+
"user-x": lucideReact.UserX,
|
|
19367
|
+
wrench: lucideReact.Wrench,
|
|
19368
|
+
activity: lucideReact.Activity,
|
|
19369
|
+
"help-circle": lucideReact.HelpCircle
|
|
19370
|
+
};
|
|
19371
|
+
var humanizeIdleReasonLabel = (value) => {
|
|
19372
|
+
const text = String(value || "").trim();
|
|
19373
|
+
if (!text) {
|
|
19374
|
+
return "Unknown";
|
|
19375
|
+
}
|
|
19376
|
+
return text.replace(/_/g, " ").split(/\s+/).filter(Boolean).map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
|
|
19377
|
+
};
|
|
19378
|
+
var normalizePaletteToken = (value) => {
|
|
19379
|
+
const token = String(value || "").trim().toLowerCase();
|
|
19380
|
+
if (token in PALETTE_CONFIG) {
|
|
19381
|
+
return token;
|
|
19382
|
+
}
|
|
19383
|
+
return DEFAULT_PALETTE_TOKEN;
|
|
19384
|
+
};
|
|
19385
|
+
var normalizeIconToken = (value) => {
|
|
19386
|
+
const token = String(value || "").trim().toLowerCase();
|
|
19387
|
+
if (token in ICON_CONFIG) {
|
|
19388
|
+
return token;
|
|
19389
|
+
}
|
|
19390
|
+
return DEFAULT_ICON_TOKEN;
|
|
19391
|
+
};
|
|
19392
|
+
var getIdleReasonPresentation = (metadata) => {
|
|
19393
|
+
const label = typeof metadata?.label === "string" && metadata.label.trim() ? metadata.label.trim() : null;
|
|
19394
|
+
const displayName = typeof metadata?.displayName === "string" && metadata.displayName.trim() ? metadata.displayName.trim() : humanizeIdleReasonLabel(label);
|
|
19395
|
+
const paletteToken = normalizePaletteToken(metadata?.paletteToken);
|
|
19396
|
+
const iconToken = normalizeIconToken(metadata?.iconToken);
|
|
19397
|
+
return {
|
|
19398
|
+
label,
|
|
19399
|
+
displayName,
|
|
19400
|
+
paletteToken,
|
|
19401
|
+
iconToken,
|
|
19402
|
+
isKnown: Boolean(metadata?.isKnown),
|
|
19403
|
+
Icon: ICON_CONFIG[iconToken],
|
|
19404
|
+
...PALETTE_CONFIG[paletteToken]
|
|
19405
|
+
};
|
|
19406
|
+
};
|
|
19407
|
+
var getIdleReasonHexColor = (metadata) => getIdleReasonPresentation(metadata).hex;
|
|
19263
19408
|
|
|
19264
19409
|
// src/lib/services/clipClassificationService.ts
|
|
19410
|
+
var normalizeClassification = (value) => {
|
|
19411
|
+
const rawLabel = typeof value?.label === "string" ? value.label.trim() : "";
|
|
19412
|
+
const label = rawLabel || void 0;
|
|
19413
|
+
const parsedConfidence = typeof value?.confidence === "number" ? value.confidence : typeof value?.confidence === "string" ? Number(value.confidence) : void 0;
|
|
19414
|
+
return {
|
|
19415
|
+
status: value?.status === "classified" ? "classified" : "processing",
|
|
19416
|
+
label,
|
|
19417
|
+
displayName: typeof value?.display_name === "string" ? value.display_name : label ? humanizeIdleReasonLabel(label) : void 0,
|
|
19418
|
+
paletteToken: typeof value?.palette_token === "string" ? value.palette_token : void 0,
|
|
19419
|
+
iconToken: typeof value?.icon_token === "string" ? value.icon_token : void 0,
|
|
19420
|
+
isKnown: typeof value?.is_known === "boolean" ? value.is_known : void 0,
|
|
19421
|
+
confidence: parsedConfidence !== void 0 && Number.isFinite(parsedConfidence) ? parsedConfidence : void 0
|
|
19422
|
+
};
|
|
19423
|
+
};
|
|
19265
19424
|
function parseCleanLabel(rawLabel) {
|
|
19266
19425
|
if (!rawLabel) return null;
|
|
19267
19426
|
const patterns = [
|
|
@@ -19315,7 +19474,13 @@ async function fetchClassifications(clipIds, token) {
|
|
|
19315
19474
|
);
|
|
19316
19475
|
}
|
|
19317
19476
|
const data = await response.json();
|
|
19318
|
-
|
|
19477
|
+
const rawClassifications = data.classifications || {};
|
|
19478
|
+
return Object.fromEntries(
|
|
19479
|
+
Object.entries(rawClassifications).map(([clipId, classification]) => [
|
|
19480
|
+
clipId,
|
|
19481
|
+
normalizeClassification(classification)
|
|
19482
|
+
])
|
|
19483
|
+
);
|
|
19319
19484
|
} catch (error) {
|
|
19320
19485
|
console.error("Error fetching chunk:", error);
|
|
19321
19486
|
return Object.fromEntries(
|
|
@@ -19356,21 +19521,30 @@ function useClassificationRealtimeUpdates({
|
|
|
19356
19521
|
},
|
|
19357
19522
|
(payload) => {
|
|
19358
19523
|
console.log("[useClassificationRealtimeUpdates] New classification:", payload);
|
|
19359
|
-
|
|
19360
|
-
|
|
19361
|
-
|
|
19362
|
-
|
|
19363
|
-
|
|
19364
|
-
|
|
19365
|
-
|
|
19366
|
-
|
|
19367
|
-
|
|
19368
|
-
|
|
19369
|
-
|
|
19524
|
+
void (async () => {
|
|
19525
|
+
try {
|
|
19526
|
+
const { clip_id, clip_label, confidence_score } = payload.new;
|
|
19527
|
+
const token = await getAccessTokenOrRedirect(supabase, { redirectReason: "session_expired" });
|
|
19528
|
+
const fetched = await fetchClassifications([clip_id], token);
|
|
19529
|
+
const classification = fetched[clip_id];
|
|
19530
|
+
if (classification) {
|
|
19531
|
+
onClassificationUpdate(clip_id, classification);
|
|
19532
|
+
return;
|
|
19533
|
+
}
|
|
19534
|
+
const parsedLabel = parseCleanLabel(clip_label);
|
|
19535
|
+
if (parsedLabel) {
|
|
19536
|
+
onClassificationUpdate(clip_id, {
|
|
19537
|
+
status: "classified",
|
|
19538
|
+
label: parsedLabel,
|
|
19539
|
+
confidence: confidence_score || 0
|
|
19540
|
+
});
|
|
19541
|
+
} else {
|
|
19542
|
+
console.warn("[useClassificationRealtimeUpdates] Failed to parse label:", clip_label);
|
|
19543
|
+
}
|
|
19544
|
+
} catch (error) {
|
|
19545
|
+
console.error("[useClassificationRealtimeUpdates] Error processing update:", error);
|
|
19370
19546
|
}
|
|
19371
|
-
}
|
|
19372
|
-
console.error("[useClassificationRealtimeUpdates] Error processing update:", error);
|
|
19373
|
-
}
|
|
19547
|
+
})();
|
|
19374
19548
|
}
|
|
19375
19549
|
).subscribe((status) => {
|
|
19376
19550
|
console.log(`[useClassificationRealtimeUpdates] Subscription status:`, status);
|
|
@@ -32402,90 +32576,99 @@ var CycleTimeOverTimeChart = ({
|
|
|
32402
32576
|
data,
|
|
32403
32577
|
idealCycleTime,
|
|
32404
32578
|
shiftStart,
|
|
32405
|
-
|
|
32579
|
+
shiftEnd,
|
|
32580
|
+
xAxisMode = "recent",
|
|
32581
|
+
datasetKey,
|
|
32582
|
+
className = "",
|
|
32583
|
+
showIdleTime = false,
|
|
32584
|
+
idleTimeData = []
|
|
32406
32585
|
}) => {
|
|
32407
32586
|
const MAX_DATA_POINTS = 40;
|
|
32408
32587
|
const containerRef = React141__namespace.default.useRef(null);
|
|
32409
32588
|
const [containerReady, setContainerReady] = React141__namespace.default.useState(false);
|
|
32410
|
-
const
|
|
32411
|
-
const [hours, minutes] =
|
|
32412
|
-
|
|
32589
|
+
const parseTimeToMinutes3 = (value) => {
|
|
32590
|
+
const [hours, minutes] = value.split(":").map(Number);
|
|
32591
|
+
if (!Number.isFinite(hours) || !Number.isFinite(minutes)) return 0;
|
|
32592
|
+
return hours * 60 + minutes;
|
|
32413
32593
|
};
|
|
32414
|
-
|
|
32415
|
-
|
|
32416
|
-
|
|
32594
|
+
const formatHourLabel = (slotIndex) => {
|
|
32595
|
+
const baseMinutes = parseTimeToMinutes3(shiftStart);
|
|
32596
|
+
const absoluteMinutes = baseMinutes + slotIndex * 60;
|
|
32597
|
+
const hour24 = Math.floor(absoluteMinutes % (24 * 60) / 60);
|
|
32598
|
+
const ampm = hour24 >= 12 ? "PM" : "AM";
|
|
32599
|
+
const hour12 = hour24 % 12 || 12;
|
|
32600
|
+
return `${hour12}${ampm}`;
|
|
32601
|
+
};
|
|
32602
|
+
const formatHourRangeLabel = (slotIndex) => {
|
|
32603
|
+
const startLabel = formatHourLabel(slotIndex);
|
|
32604
|
+
const endLabel = shiftEnd && slotIndex === DURATION - 1 ? formatHourLabel(slotIndex + 1) : formatHourLabel(slotIndex + 1);
|
|
32605
|
+
return `${startLabel} - ${endLabel}`;
|
|
32417
32606
|
};
|
|
32607
|
+
const getDisplayData = React141__namespace.default.useCallback((rawData) => {
|
|
32608
|
+
if (xAxisMode === "hourly") return rawData;
|
|
32609
|
+
return rawData.slice(Math.max(0, rawData.length - MAX_DATA_POINTS));
|
|
32610
|
+
}, [xAxisMode]);
|
|
32418
32611
|
const displayData = getDisplayData(data);
|
|
32419
32612
|
const DURATION = displayData.length;
|
|
32420
|
-
const
|
|
32421
|
-
const
|
|
32422
|
-
const
|
|
32423
|
-
const
|
|
32424
|
-
|
|
32425
|
-
|
|
32426
|
-
|
|
32427
|
-
const animate = (currentTime) => {
|
|
32428
|
-
const elapsed = currentTime - startTime;
|
|
32429
|
-
const progress7 = Math.min(elapsed / duration, 1);
|
|
32430
|
-
const easeOutQuint = (t) => 1 - Math.pow(1 - t, 5);
|
|
32431
|
-
const easedProgress = easeOutQuint(progress7);
|
|
32432
|
-
const newData = startData.map((start, index) => {
|
|
32433
|
-
const target = targetData[index] || 0;
|
|
32434
|
-
const change = target - start;
|
|
32435
|
-
const scaleFactor = Math.min(1, 50 / Math.abs(change || 1));
|
|
32436
|
-
const adjustedEasing = progress7 * (scaleFactor + (1 - scaleFactor) * easedProgress);
|
|
32437
|
-
return start + change * adjustedEasing;
|
|
32438
|
-
});
|
|
32439
|
-
setAnimatedData(newData);
|
|
32440
|
-
prevDataRef.current = newData;
|
|
32441
|
-
if (progress7 < 1) {
|
|
32442
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
32443
|
-
} else {
|
|
32444
|
-
setAnimatedData(targetData);
|
|
32445
|
-
prevDataRef.current = targetData;
|
|
32446
|
-
}
|
|
32447
|
-
};
|
|
32448
|
-
if (animationFrameRef.current) {
|
|
32449
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
32450
|
-
}
|
|
32451
|
-
animationFrameRef.current = requestAnimationFrame(animate);
|
|
32452
|
-
}, []);
|
|
32613
|
+
const effectiveDatasetKey = datasetKey || `cycle-time:${xAxisMode}`;
|
|
32614
|
+
const [animatedDatasetKey, setAnimatedDatasetKey] = React141__namespace.default.useState(null);
|
|
32615
|
+
const shouldAnimate = animatedDatasetKey !== effectiveDatasetKey;
|
|
32616
|
+
const handleAnimationEnd = React141__namespace.default.useCallback(() => {
|
|
32617
|
+
setAnimatedDatasetKey((currentValue) => currentValue === effectiveDatasetKey ? currentValue : effectiveDatasetKey);
|
|
32618
|
+
}, [effectiveDatasetKey]);
|
|
32619
|
+
const finalData = displayData;
|
|
32453
32620
|
React141__namespace.default.useEffect(() => {
|
|
32454
|
-
|
|
32455
|
-
|
|
32456
|
-
|
|
32621
|
+
const containerNode = containerRef.current;
|
|
32622
|
+
if (!containerNode) {
|
|
32623
|
+
setContainerReady(true);
|
|
32624
|
+
return void 0;
|
|
32457
32625
|
}
|
|
32458
|
-
|
|
32459
|
-
|
|
32460
|
-
cancelAnimationFrame(animationFrameRef.current);
|
|
32461
|
-
}
|
|
32462
|
-
};
|
|
32463
|
-
}, [data, animateToNewData]);
|
|
32464
|
-
React141__namespace.default.useEffect(() => {
|
|
32626
|
+
let frameId = null;
|
|
32627
|
+
let resizeObserver = null;
|
|
32465
32628
|
const checkContainerDimensions = () => {
|
|
32466
|
-
|
|
32467
|
-
|
|
32468
|
-
|
|
32469
|
-
|
|
32470
|
-
}
|
|
32629
|
+
const rect = containerNode.getBoundingClientRect();
|
|
32630
|
+
const isReady = rect.width > 0 && rect.height > 0;
|
|
32631
|
+
if (isReady) {
|
|
32632
|
+
setContainerReady(true);
|
|
32471
32633
|
}
|
|
32634
|
+
return isReady;
|
|
32472
32635
|
};
|
|
32473
|
-
checkContainerDimensions()
|
|
32474
|
-
|
|
32475
|
-
if (containerRef.current) {
|
|
32476
|
-
resizeObserver.observe(containerRef.current);
|
|
32636
|
+
if (checkContainerDimensions()) {
|
|
32637
|
+
return void 0;
|
|
32477
32638
|
}
|
|
32478
|
-
|
|
32639
|
+
frameId = window.requestAnimationFrame(() => {
|
|
32640
|
+
checkContainerDimensions();
|
|
32641
|
+
});
|
|
32642
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
32643
|
+
resizeObserver = new ResizeObserver(() => {
|
|
32644
|
+
if (checkContainerDimensions() && resizeObserver) {
|
|
32645
|
+
resizeObserver.disconnect();
|
|
32646
|
+
resizeObserver = null;
|
|
32647
|
+
}
|
|
32648
|
+
});
|
|
32649
|
+
resizeObserver.observe(containerNode);
|
|
32650
|
+
} else {
|
|
32479
32651
|
setContainerReady(true);
|
|
32480
|
-
}
|
|
32652
|
+
}
|
|
32481
32653
|
return () => {
|
|
32482
|
-
|
|
32483
|
-
|
|
32654
|
+
if (frameId !== null) {
|
|
32655
|
+
window.cancelAnimationFrame(frameId);
|
|
32656
|
+
}
|
|
32657
|
+
resizeObserver?.disconnect();
|
|
32484
32658
|
};
|
|
32485
32659
|
}, []);
|
|
32660
|
+
const labelInterval = React141__namespace.default.useMemo(() => {
|
|
32661
|
+
if (xAxisMode === "hourly") {
|
|
32662
|
+
return Math.max(1, Math.ceil(DURATION / 8));
|
|
32663
|
+
}
|
|
32664
|
+
return 5;
|
|
32665
|
+
}, [xAxisMode, DURATION]);
|
|
32486
32666
|
const formatTimeLabel = (dataIndex) => {
|
|
32487
32667
|
if (DURATION === 0) return "";
|
|
32488
|
-
if (dataIndex %
|
|
32668
|
+
if (dataIndex % labelInterval !== 0 && dataIndex !== DURATION - 1) return "";
|
|
32669
|
+
if (xAxisMode === "hourly") {
|
|
32670
|
+
return formatHourLabel(dataIndex);
|
|
32671
|
+
}
|
|
32489
32672
|
const timeAgo = (DURATION - 1 - dataIndex) * 90;
|
|
32490
32673
|
const minutes = Math.floor(timeAgo / 60);
|
|
32491
32674
|
const seconds = timeAgo % 60;
|
|
@@ -32499,6 +32682,9 @@ var CycleTimeOverTimeChart = ({
|
|
|
32499
32682
|
};
|
|
32500
32683
|
const formatTooltipTime = (dataIndex) => {
|
|
32501
32684
|
if (DURATION === 0) return "";
|
|
32685
|
+
if (xAxisMode === "hourly") {
|
|
32686
|
+
return formatHourRangeLabel(dataIndex);
|
|
32687
|
+
}
|
|
32502
32688
|
const timeAgo = (DURATION - 1 - dataIndex) * 90;
|
|
32503
32689
|
const minutes = Math.floor(timeAgo / 60);
|
|
32504
32690
|
const seconds = timeAgo % 60;
|
|
@@ -32512,39 +32698,40 @@ var CycleTimeOverTimeChart = ({
|
|
|
32512
32698
|
return `${minutes} minutes ${seconds} seconds ago`;
|
|
32513
32699
|
}
|
|
32514
32700
|
};
|
|
32515
|
-
const chartData = Array.from({ length: DURATION }, (_, i) => {
|
|
32701
|
+
const chartData = React141__namespace.default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
|
|
32516
32702
|
return {
|
|
32517
32703
|
timeIndex: i,
|
|
32518
32704
|
label: formatTimeLabel(i),
|
|
32519
32705
|
tooltip: formatTooltipTime(i),
|
|
32520
|
-
cycleTime:
|
|
32521
|
-
|
|
32706
|
+
cycleTime: finalData[i] || 0,
|
|
32707
|
+
idleMinutes: showIdleTime && idleTimeData && idleTimeData[i] || 0,
|
|
32708
|
+
color: (finalData[i] || 0) <= idealCycleTime ? "#00AB45" : "#E34329"
|
|
32522
32709
|
};
|
|
32523
|
-
});
|
|
32524
|
-
const renderLegend = () =>
|
|
32525
|
-
|
|
32526
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
32527
|
-
"
|
|
32528
|
-
|
|
32529
|
-
|
|
32530
|
-
|
|
32531
|
-
] }) });
|
|
32710
|
+
}), [DURATION, finalData, showIdleTime, idleTimeData, idealCycleTime]);
|
|
32711
|
+
const renderLegend = () => {
|
|
32712
|
+
if (!showIdleTime) return null;
|
|
32713
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-start text-[10px] font-bold text-gray-500 mb-6 tracking-[0.05em] gap-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
32714
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2.5 h-2.5 rounded-full bg-[#f59e0b]" }),
|
|
32715
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Idle Time (min)" })
|
|
32716
|
+
] }) });
|
|
32717
|
+
};
|
|
32532
32718
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
32533
32719
|
"div",
|
|
32534
32720
|
{
|
|
32535
32721
|
ref: containerRef,
|
|
32536
|
-
className: `w-full h-full min-w-0 relative pb-
|
|
32722
|
+
className: `w-full h-full min-w-0 flex flex-col relative pb-2 ${className}`,
|
|
32537
32723
|
style: { minHeight: "200px", minWidth: 0 },
|
|
32538
32724
|
children: [
|
|
32539
|
-
|
|
32725
|
+
renderLegend(),
|
|
32726
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0 w-full", children: containerReady ? /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
32540
32727
|
recharts.LineChart,
|
|
32541
32728
|
{
|
|
32542
32729
|
data: chartData,
|
|
32543
32730
|
margin: {
|
|
32544
|
-
top:
|
|
32731
|
+
top: 5,
|
|
32545
32732
|
right: 30,
|
|
32546
32733
|
bottom: 25,
|
|
32547
|
-
left:
|
|
32734
|
+
left: 10
|
|
32548
32735
|
},
|
|
32549
32736
|
children: [
|
|
32550
32737
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false }),
|
|
@@ -32554,17 +32741,18 @@ var CycleTimeOverTimeChart = ({
|
|
|
32554
32741
|
dataKey: "label",
|
|
32555
32742
|
tick: { fontSize: 11 },
|
|
32556
32743
|
interval: 0,
|
|
32557
|
-
angle: -30,
|
|
32558
|
-
textAnchor: "end",
|
|
32559
|
-
tickMargin: 15,
|
|
32560
|
-
height: 60
|
|
32744
|
+
angle: xAxisMode === "hourly" ? 0 : -30,
|
|
32745
|
+
textAnchor: xAxisMode === "hourly" ? "middle" : "end",
|
|
32746
|
+
tickMargin: xAxisMode === "hourly" ? 8 : 15,
|
|
32747
|
+
height: xAxisMode === "hourly" ? 40 : 60
|
|
32561
32748
|
}
|
|
32562
32749
|
),
|
|
32563
32750
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
32564
32751
|
recharts.YAxis,
|
|
32565
32752
|
{
|
|
32566
32753
|
tickMargin: 8,
|
|
32567
|
-
width:
|
|
32754
|
+
width: 45,
|
|
32755
|
+
yAxisId: "cycle",
|
|
32568
32756
|
domain: ["auto", "auto"],
|
|
32569
32757
|
ticks: [0, idealCycleTime, ...Array.from({ length: 4 }, (_, i) => (i + 1) * Math.ceil(idealCycleTime / 2))].sort((a, b) => a - b),
|
|
32570
32758
|
tickFormatter: (value) => String(value),
|
|
@@ -32588,6 +32776,20 @@ var CycleTimeOverTimeChart = ({
|
|
|
32588
32776
|
}
|
|
32589
32777
|
}
|
|
32590
32778
|
),
|
|
32779
|
+
showIdleTime && /* @__PURE__ */ jsxRuntime.jsx(
|
|
32780
|
+
recharts.YAxis,
|
|
32781
|
+
{
|
|
32782
|
+
yAxisId: "idle",
|
|
32783
|
+
orientation: "right",
|
|
32784
|
+
tickMargin: 8,
|
|
32785
|
+
width: 35,
|
|
32786
|
+
domain: [0, 60],
|
|
32787
|
+
tickFormatter: (value) => `${value}m`,
|
|
32788
|
+
tick: { fontSize: 11, fill: "#f59e0b" },
|
|
32789
|
+
axisLine: false,
|
|
32790
|
+
tickLine: false
|
|
32791
|
+
}
|
|
32792
|
+
),
|
|
32591
32793
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
32592
32794
|
recharts.Tooltip,
|
|
32593
32795
|
{
|
|
@@ -32615,8 +32817,11 @@ var CycleTimeOverTimeChart = ({
|
|
|
32615
32817
|
}
|
|
32616
32818
|
return label;
|
|
32617
32819
|
},
|
|
32618
|
-
formatter: (value) => {
|
|
32820
|
+
formatter: (value, name) => {
|
|
32619
32821
|
const numValue = typeof value === "number" ? value : Number(value);
|
|
32822
|
+
if (name === "idleMinutes") {
|
|
32823
|
+
return [`${numValue.toFixed(0)} minutes`, "Idle Time"];
|
|
32824
|
+
}
|
|
32620
32825
|
return [`${numValue.toFixed(1)} seconds`, "Cycle Time"];
|
|
32621
32826
|
},
|
|
32622
32827
|
animationDuration: 200
|
|
@@ -32626,6 +32831,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
32626
32831
|
recharts.ReferenceLine,
|
|
32627
32832
|
{
|
|
32628
32833
|
y: idealCycleTime,
|
|
32834
|
+
yAxisId: "cycle",
|
|
32629
32835
|
stroke: "#E34329",
|
|
32630
32836
|
strokeDasharray: "3 3",
|
|
32631
32837
|
strokeWidth: 2,
|
|
@@ -32642,6 +32848,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
32642
32848
|
recharts.Line,
|
|
32643
32849
|
{
|
|
32644
32850
|
type: "monotone",
|
|
32851
|
+
yAxisId: "cycle",
|
|
32645
32852
|
dataKey: "cycleTime",
|
|
32646
32853
|
stroke: "#3B82F6",
|
|
32647
32854
|
strokeWidth: 2,
|
|
@@ -32691,15 +32898,35 @@ var CycleTimeOverTimeChart = ({
|
|
|
32691
32898
|
}
|
|
32692
32899
|
);
|
|
32693
32900
|
},
|
|
32901
|
+
isAnimationActive: shouldAnimate,
|
|
32694
32902
|
animationBegin: 0,
|
|
32695
|
-
animationDuration:
|
|
32903
|
+
animationDuration: 1200,
|
|
32904
|
+
animationEasing: "ease-out",
|
|
32905
|
+
onAnimationEnd: handleAnimationEnd
|
|
32906
|
+
},
|
|
32907
|
+
`${effectiveDatasetKey}:cycle`
|
|
32908
|
+
),
|
|
32909
|
+
showIdleTime && /* @__PURE__ */ jsxRuntime.jsx(
|
|
32910
|
+
recharts.Line,
|
|
32911
|
+
{
|
|
32912
|
+
type: "monotone",
|
|
32913
|
+
yAxisId: "idle",
|
|
32914
|
+
dataKey: "idleMinutes",
|
|
32915
|
+
stroke: "#f59e0b",
|
|
32916
|
+
strokeWidth: 2,
|
|
32917
|
+
strokeDasharray: "4 4",
|
|
32918
|
+
dot: { r: 4, fill: "#f59e0b", stroke: "#fff", strokeWidth: 1 },
|
|
32919
|
+
activeDot: { r: 6, fill: "#f59e0b", stroke: "#fff", strokeWidth: 2 },
|
|
32920
|
+
isAnimationActive: shouldAnimate,
|
|
32921
|
+
animationBegin: 0,
|
|
32922
|
+
animationDuration: 1200,
|
|
32696
32923
|
animationEasing: "ease-out"
|
|
32697
|
-
}
|
|
32924
|
+
},
|
|
32925
|
+
`${effectiveDatasetKey}:idle`
|
|
32698
32926
|
)
|
|
32699
32927
|
]
|
|
32700
32928
|
}
|
|
32701
|
-
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center bg-gray-50 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500 text-sm", children: "Loading chart..." }) })
|
|
32702
|
-
renderLegend()
|
|
32929
|
+
) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center bg-gray-50 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-500 text-sm", children: "Loading chart..." }) }) })
|
|
32703
32930
|
]
|
|
32704
32931
|
}
|
|
32705
32932
|
);
|
|
@@ -32891,7 +33118,7 @@ var HourlyOutputChartComponent = ({
|
|
|
32891
33118
|
if (!classification.label) {
|
|
32892
33119
|
return "Reason unavailable";
|
|
32893
33120
|
}
|
|
32894
|
-
return classification.label.replace(/_/g, " ");
|
|
33121
|
+
return classification.displayName || classification.label.replace(/_/g, " ");
|
|
32895
33122
|
}, [idleClipRanges, idleTimeClipClassifications]);
|
|
32896
33123
|
const { shiftDuration, shiftEndTime, hasPartialLastHour } = React141__namespace.default.useMemo(() => {
|
|
32897
33124
|
console.log("[HourlyOutputChart] Calculating shift duration with:", {
|
|
@@ -33549,23 +33776,82 @@ var HourlyOutputChart = React141__namespace.default.memo(HourlyOutputChartCompon
|
|
|
33549
33776
|
HourlyOutputChart.displayName = "HourlyOutputChart";
|
|
33550
33777
|
|
|
33551
33778
|
// src/components/dashboard/grid/videoGridMetricUtils.ts
|
|
33552
|
-
var VIDEO_GRID_LEGEND_LABEL = "
|
|
33779
|
+
var VIDEO_GRID_LEGEND_LABEL = "Flow";
|
|
33553
33780
|
var MAP_GRID_LEGEND_LABEL = "Efficiency";
|
|
33554
33781
|
var MIXED_VIDEO_GRID_LEGEND_LABEL = "Flow / Efficiency";
|
|
33555
33782
|
var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
33556
|
-
var
|
|
33557
|
-
|
|
33783
|
+
var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
|
|
33784
|
+
workspace.video_grid_metric_mode,
|
|
33785
|
+
workspace.assembly_enabled === true
|
|
33786
|
+
);
|
|
33787
|
+
var isVideoGridWipGated = (workspace) => isWipGatedVideoGridMetricMode(
|
|
33788
|
+
workspace.video_grid_metric_mode,
|
|
33789
|
+
workspace.assembly_enabled === true
|
|
33790
|
+
);
|
|
33791
|
+
var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) && isFiniteNumber2(workspace.recent_flow_percent);
|
|
33792
|
+
var isVideoGridRecentFlowUnavailable = (workspace) => isVideoGridRecentFlowEnabled(workspace) && !hasVideoGridRecentFlow(workspace);
|
|
33558
33793
|
var getVideoGridMetricValue = (workspace) => {
|
|
33559
33794
|
const recentFlowPercent = workspace.recent_flow_percent;
|
|
33560
|
-
if (
|
|
33795
|
+
if (hasVideoGridRecentFlow(workspace) && isFiniteNumber2(recentFlowPercent)) {
|
|
33561
33796
|
return recentFlowPercent;
|
|
33562
33797
|
}
|
|
33798
|
+
if (isVideoGridRecentFlowUnavailable(workspace)) {
|
|
33799
|
+
return null;
|
|
33800
|
+
}
|
|
33563
33801
|
return workspace.efficiency;
|
|
33564
33802
|
};
|
|
33565
33803
|
var hasIncomingWipMapping = (workspace) => Boolean(workspace.incoming_wip_buffer_name);
|
|
33804
|
+
var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
33805
|
+
const metricValue = getVideoGridMetricValue(workspace);
|
|
33806
|
+
if (!isFiniteNumber2(metricValue)) {
|
|
33807
|
+
return "neutral";
|
|
33808
|
+
}
|
|
33809
|
+
return getEfficiencyColor(metricValue, legend);
|
|
33810
|
+
};
|
|
33811
|
+
var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
33812
|
+
if (!hasVideoGridRecentFlow(workspace) || !isVideoGridWipGated(workspace)) {
|
|
33813
|
+
return false;
|
|
33814
|
+
}
|
|
33815
|
+
if (getVideoGridBaseColorState(workspace, legend) !== "red") {
|
|
33816
|
+
return false;
|
|
33817
|
+
}
|
|
33818
|
+
if (!hasIncomingWipMapping(workspace)) {
|
|
33819
|
+
return false;
|
|
33820
|
+
}
|
|
33821
|
+
return isFiniteNumber2(workspace.incoming_wip_current) && workspace.incoming_wip_current <= 1;
|
|
33822
|
+
};
|
|
33823
|
+
var toMinuteBucket = (minuteBucket) => Number.isFinite(minuteBucket) ? Math.floor(minuteBucket) : Math.floor(Date.now() / 6e4);
|
|
33824
|
+
var getEffectiveFlowMinuteBucket = (workspace) => {
|
|
33825
|
+
const effectiveAt = workspace.recent_flow_effective_end_at;
|
|
33826
|
+
if (!effectiveAt) {
|
|
33827
|
+
return void 0;
|
|
33828
|
+
}
|
|
33829
|
+
const timestamp = Date.parse(effectiveAt);
|
|
33830
|
+
if (!Number.isFinite(timestamp)) {
|
|
33831
|
+
return void 0;
|
|
33832
|
+
}
|
|
33833
|
+
return Math.floor(timestamp / 6e4);
|
|
33834
|
+
};
|
|
33835
|
+
var hashWorkspaceKey = (workspace) => {
|
|
33836
|
+
const workspaceKey = workspace.workspace_uuid || workspace.workspace_name || "unknown";
|
|
33837
|
+
let hash = 0;
|
|
33838
|
+
for (let index = 0; index < workspaceKey.length; index += 1) {
|
|
33839
|
+
hash = (hash * 31 + workspaceKey.charCodeAt(index)) % 2147483647;
|
|
33840
|
+
}
|
|
33841
|
+
return hash;
|
|
33842
|
+
};
|
|
33843
|
+
var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
|
|
33844
|
+
const bucket = getEffectiveFlowMinuteBucket(workspace) ?? toMinuteBucket(minuteBucket);
|
|
33845
|
+
const offset = (hashWorkspaceKey(workspace) % 11 + bucket % 11 + 11) % 11;
|
|
33846
|
+
return 100 + offset;
|
|
33847
|
+
};
|
|
33848
|
+
var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace);
|
|
33566
33849
|
var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
33567
|
-
const baseColor =
|
|
33568
|
-
if (!
|
|
33850
|
+
const baseColor = getVideoGridBaseColorState(workspace, legend);
|
|
33851
|
+
if (!hasVideoGridRecentFlow(workspace)) {
|
|
33852
|
+
return baseColor;
|
|
33853
|
+
}
|
|
33854
|
+
if (!isVideoGridWipGated(workspace)) {
|
|
33569
33855
|
return baseColor;
|
|
33570
33856
|
}
|
|
33571
33857
|
if (baseColor !== "red") {
|
|
@@ -33577,7 +33863,7 @@ var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
|
|
|
33577
33863
|
if (!isFiniteNumber2(workspace.incoming_wip_current)) {
|
|
33578
33864
|
return "neutral";
|
|
33579
33865
|
}
|
|
33580
|
-
if (workspace
|
|
33866
|
+
if (isLowWipGreenOverride(workspace, legend)) {
|
|
33581
33867
|
return "green";
|
|
33582
33868
|
}
|
|
33583
33869
|
return baseColor;
|
|
@@ -33587,11 +33873,11 @@ var getVideoGridLegendLabel = (workspaces) => {
|
|
|
33587
33873
|
if (visibleWorkspaces.length === 0) {
|
|
33588
33874
|
return MAP_GRID_LEGEND_LABEL;
|
|
33589
33875
|
}
|
|
33590
|
-
const
|
|
33591
|
-
if (
|
|
33876
|
+
const recentFlowEnabledCount = visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).length;
|
|
33877
|
+
if (recentFlowEnabledCount === 0) {
|
|
33592
33878
|
return MAP_GRID_LEGEND_LABEL;
|
|
33593
33879
|
}
|
|
33594
|
-
if (
|
|
33880
|
+
if (recentFlowEnabledCount === visibleWorkspaces.length) {
|
|
33595
33881
|
return VIDEO_GRID_LEGEND_LABEL;
|
|
33596
33882
|
}
|
|
33597
33883
|
return MIXED_VIDEO_GRID_LEGEND_LABEL;
|
|
@@ -33618,6 +33904,7 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33618
33904
|
useRAF = true,
|
|
33619
33905
|
className = "",
|
|
33620
33906
|
compact = false,
|
|
33907
|
+
displayMinuteBucket,
|
|
33621
33908
|
displayName,
|
|
33622
33909
|
lastSeenLabel,
|
|
33623
33910
|
onMouseEnter,
|
|
@@ -33638,8 +33925,13 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33638
33925
|
const lastSeenText = lastSeenLabel || "Unknown";
|
|
33639
33926
|
const workspaceDisplayName = displayName || getWorkspaceDisplayName(workspace.workspace_name, workspace.line_id);
|
|
33640
33927
|
const videoGridMetricValue = getVideoGridMetricValue(workspace);
|
|
33928
|
+
const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
|
|
33641
33929
|
const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
|
|
33642
|
-
const
|
|
33930
|
+
const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
|
|
33931
|
+
const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
|
|
33932
|
+
const hasBarMetric = typeof videoGridMetricValue === "number" && Number.isFinite(videoGridMetricValue);
|
|
33933
|
+
const badgeTitle = hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
|
|
33934
|
+
const badgeLabel = hasDisplayMetric ? `${Math.round(videoGridDisplayValue)}%` : "X";
|
|
33643
33935
|
const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
|
|
33644
33936
|
const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
|
|
33645
33937
|
const efficiencyStatus = videoGridColorState === "green" ? "High" : videoGridColorState === "yellow" ? "Medium" : videoGridColorState === "red" ? "Low" : "Neutral";
|
|
@@ -33718,19 +34010,18 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33718
34010
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute ${compact ? "top-1 right-1" : "top-2 right-2"} z-30`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
33719
34011
|
"div",
|
|
33720
34012
|
{
|
|
34013
|
+
"data-testid": "video-card-metric-badge",
|
|
33721
34014
|
className: `bg-black/70 backdrop-blur-sm rounded ${compact ? "px-1.5 py-1" : "px-2 py-1"} text-white border border-white/10`,
|
|
33722
34015
|
title: badgeTitle,
|
|
33723
|
-
children: /* @__PURE__ */ jsxRuntime.
|
|
33724
|
-
Math.round(videoGridMetricValue),
|
|
33725
|
-
"%"
|
|
33726
|
-
] })
|
|
34016
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${compact ? "text-[10px]" : "text-xs"} font-semibold`, children: badgeLabel })
|
|
33727
34017
|
}
|
|
33728
34018
|
) }),
|
|
33729
34019
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute bottom-0 left-0 right-0 ${compact ? "h-0.5" : "h-1"} bg-black/50 z-30`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
33730
34020
|
"div",
|
|
33731
34021
|
{
|
|
34022
|
+
"data-testid": "video-card-metric-bar",
|
|
33732
34023
|
className: `h-full ${efficiencyBarClass} transition-all duration-500`,
|
|
33733
|
-
style: { width: `${Math.min(100, videoGridMetricValue)}%` }
|
|
34024
|
+
style: { width: `${hasBarMetric ? Math.min(100, Math.max(0, videoGridMetricValue)) : videoGridColorState === "neutral" ? 100 : 0}%` }
|
|
33734
34025
|
}
|
|
33735
34026
|
) })
|
|
33736
34027
|
] }),
|
|
@@ -33761,7 +34052,7 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33761
34052
|
}
|
|
33762
34053
|
);
|
|
33763
34054
|
}, (prevProps, nextProps) => {
|
|
33764
|
-
if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.assembly_enabled !== nextProps.workspace.assembly_enabled || prevProps.workspace.recent_flow_percent !== nextProps.workspace.recent_flow_percent || prevProps.workspace.incoming_wip_current !== nextProps.workspace.incoming_wip_current || prevProps.workspace.incoming_wip_buffer_name !== nextProps.workspace.incoming_wip_buffer_name || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
|
|
34055
|
+
if (prevProps.workspace.efficiency !== nextProps.workspace.efficiency || prevProps.workspace.assembly_enabled !== nextProps.workspace.assembly_enabled || prevProps.workspace.video_grid_metric_mode !== nextProps.workspace.video_grid_metric_mode || prevProps.workspace.recent_flow_mode !== nextProps.workspace.recent_flow_mode || prevProps.workspace.recent_flow_percent !== nextProps.workspace.recent_flow_percent || prevProps.workspace.recent_flow_effective_end_at !== nextProps.workspace.recent_flow_effective_end_at || prevProps.workspace.incoming_wip_current !== nextProps.workspace.incoming_wip_current || prevProps.workspace.incoming_wip_buffer_name !== nextProps.workspace.incoming_wip_buffer_name || prevProps.workspace.trend !== nextProps.workspace.trend || prevProps.workspace.performance_score !== nextProps.workspace.performance_score || prevProps.workspace.pph !== nextProps.workspace.pph) {
|
|
33765
34056
|
return false;
|
|
33766
34057
|
}
|
|
33767
34058
|
if (prevProps.workspace.workspace_uuid !== nextProps.workspace.workspace_uuid || prevProps.workspace.workspace_name !== nextProps.workspace.workspace_name || prevProps.workspace.line_id !== nextProps.workspace.line_id) {
|
|
@@ -33779,6 +34070,9 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33779
34070
|
if (prevProps.compact !== nextProps.compact) {
|
|
33780
34071
|
return false;
|
|
33781
34072
|
}
|
|
34073
|
+
if (prevProps.displayMinuteBucket !== nextProps.displayMinuteBucket) {
|
|
34074
|
+
return false;
|
|
34075
|
+
}
|
|
33782
34076
|
if (prevProps.hlsUrl !== nextProps.hlsUrl || prevProps.shouldPlay !== nextProps.shouldPlay) {
|
|
33783
34077
|
return false;
|
|
33784
34078
|
}
|
|
@@ -34062,6 +34356,7 @@ var VideoGridView = React141__namespace.default.memo(({
|
|
|
34062
34356
|
stream_source: isR2Stream ? "r2" : "media_config"
|
|
34063
34357
|
});
|
|
34064
34358
|
}, []);
|
|
34359
|
+
const displayMinuteBucket = Math.floor(Date.now() / 6e4);
|
|
34065
34360
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative overflow-hidden h-full w-full ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "h-full w-full p-3 sm:p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
34066
34361
|
"div",
|
|
34067
34362
|
{
|
|
@@ -34151,6 +34446,7 @@ var VideoGridView = React141__namespace.default.memo(({
|
|
|
34151
34446
|
),
|
|
34152
34447
|
lastSeenLabel: card.lastSeenLabel,
|
|
34153
34448
|
useRAF: effectiveUseRAF,
|
|
34449
|
+
displayMinuteBucket,
|
|
34154
34450
|
compact: !selectedLine,
|
|
34155
34451
|
onMouseEnter: onWorkspaceHover ? () => onWorkspaceHover(card.workspaceId) : void 0,
|
|
34156
34452
|
onMouseLeave: onWorkspaceHoverEnd ? () => onWorkspaceHoverEnd(card.workspaceId) : void 0
|
|
@@ -39280,45 +39576,56 @@ var FileManagerFilters = ({
|
|
|
39280
39576
|
});
|
|
39281
39577
|
const [loadingPercentile, setLoadingPercentile] = React141.useState(false);
|
|
39282
39578
|
const resolvedTargetCycleTime = targetCycleTime && targetCycleTime > 0 ? targetCycleTime : null;
|
|
39283
|
-
const
|
|
39284
|
-
const
|
|
39285
|
-
|
|
39286
|
-
|
|
39287
|
-
|
|
39288
|
-
|
|
39289
|
-
|
|
39290
|
-
|
|
39291
|
-
|
|
39292
|
-
|
|
39579
|
+
const getIdleTimeClassification = React141.useCallback((clipId) => {
|
|
39580
|
+
const classification = mergedClipClassifications[clipId];
|
|
39581
|
+
return classification || null;
|
|
39582
|
+
}, [mergedClipClassifications]);
|
|
39583
|
+
const getRootCauseConfig = React141.useCallback((classification) => {
|
|
39584
|
+
if (!classification || classification.status === "processing") {
|
|
39585
|
+
return null;
|
|
39586
|
+
}
|
|
39587
|
+
const presentation = getIdleReasonPresentation({
|
|
39588
|
+
label: classification.label,
|
|
39589
|
+
displayName: classification.displayName,
|
|
39590
|
+
paletteToken: classification.paletteToken,
|
|
39591
|
+
iconToken: classification.iconToken,
|
|
39592
|
+
isKnown: classification.isKnown
|
|
39593
|
+
});
|
|
39293
39594
|
return {
|
|
39294
|
-
color:
|
|
39295
|
-
bgColor:
|
|
39296
|
-
borderColor:
|
|
39297
|
-
Icon:
|
|
39298
|
-
iconColor:
|
|
39595
|
+
color: presentation.textClass,
|
|
39596
|
+
bgColor: presentation.bgClass,
|
|
39597
|
+
borderColor: presentation.borderClass,
|
|
39598
|
+
Icon: presentation.Icon,
|
|
39599
|
+
iconColor: presentation.textClass,
|
|
39600
|
+
displayName: presentation.displayName
|
|
39299
39601
|
};
|
|
39300
|
-
};
|
|
39301
|
-
const normalizeIdleReasonLabel = React141.useCallback((label) => {
|
|
39302
|
-
return label.replace(/_/g, " ").trim();
|
|
39303
39602
|
}, []);
|
|
39304
|
-
const getIdleTimeRootCause = React141.useCallback((clipId) => {
|
|
39305
|
-
const classification = mergedClipClassifications[clipId];
|
|
39306
|
-
if (!classification) return "processing";
|
|
39307
|
-
if (classification.status === "processing") return "processing";
|
|
39308
|
-
return classification.label || "processing";
|
|
39309
|
-
}, [mergedClipClassifications]);
|
|
39310
39603
|
const idleReasonOptions = React141.useMemo(() => {
|
|
39311
39604
|
const idleClips = clipMetadata["idle_time"] || [];
|
|
39312
|
-
const uniqueReasons = /* @__PURE__ */ new
|
|
39605
|
+
const uniqueReasons = /* @__PURE__ */ new Map();
|
|
39313
39606
|
idleClips.forEach((clip) => {
|
|
39314
39607
|
const clipId = clip.clipId || clip.id;
|
|
39315
39608
|
if (!clipId) return;
|
|
39316
|
-
const
|
|
39317
|
-
if (!
|
|
39318
|
-
|
|
39609
|
+
const classification = getIdleTimeClassification(clipId);
|
|
39610
|
+
if (!classification || classification.status === "processing" || !classification.label) {
|
|
39611
|
+
return;
|
|
39612
|
+
}
|
|
39613
|
+
if (!uniqueReasons.has(classification.label)) {
|
|
39614
|
+
uniqueReasons.set(classification.label, {
|
|
39615
|
+
label: classification.label,
|
|
39616
|
+
displayName: classification.displayName || classification.label.replace(/_/g, " "),
|
|
39617
|
+
paletteToken: classification.paletteToken,
|
|
39618
|
+
iconToken: classification.iconToken,
|
|
39619
|
+
isKnown: classification.isKnown
|
|
39620
|
+
});
|
|
39621
|
+
}
|
|
39319
39622
|
});
|
|
39320
|
-
return Array.from(uniqueReasons).sort((a, b) => a.localeCompare(b));
|
|
39321
|
-
}, [clipMetadata,
|
|
39623
|
+
return Array.from(uniqueReasons.values()).sort((a, b) => a.displayName.localeCompare(b.displayName));
|
|
39624
|
+
}, [clipMetadata, getIdleTimeClassification]);
|
|
39625
|
+
const selectedIdleReasonOption = React141.useMemo(
|
|
39626
|
+
() => idleReasonOptions.find((reason) => reason.label === idleLabelFilter) || null,
|
|
39627
|
+
[idleReasonOptions, idleLabelFilter]
|
|
39628
|
+
);
|
|
39322
39629
|
const getClipBadge = React141.useCallback((node) => {
|
|
39323
39630
|
if (node.categoryId === "idle_time" || node.categoryId === "low_value") {
|
|
39324
39631
|
return { text: "Idle", className: "bg-red-100 text-red-700" };
|
|
@@ -39390,6 +39697,10 @@ var FileManagerFilters = ({
|
|
|
39390
39697
|
seededClassifications[clip.clipId] = {
|
|
39391
39698
|
status: clip.classification_status,
|
|
39392
39699
|
label: clip.classification_label || void 0,
|
|
39700
|
+
displayName: clip.classification_display_name || void 0,
|
|
39701
|
+
paletteToken: clip.classification_palette_token || void 0,
|
|
39702
|
+
iconToken: clip.classification_icon_token || void 0,
|
|
39703
|
+
isKnown: clip.classification_is_known ?? void 0,
|
|
39393
39704
|
confidence: clip.classification_confidence ?? void 0
|
|
39394
39705
|
};
|
|
39395
39706
|
}
|
|
@@ -39773,7 +40084,7 @@ var FileManagerFilters = ({
|
|
|
39773
40084
|
return slot ? slot.label : value;
|
|
39774
40085
|
}, [timeSlots]);
|
|
39775
40086
|
const isClipInTimeRange = React141.useCallback((clipTimestamp) => {
|
|
39776
|
-
if (!
|
|
40087
|
+
if (!startTime || !endTime) {
|
|
39777
40088
|
return true;
|
|
39778
40089
|
}
|
|
39779
40090
|
try {
|
|
@@ -39799,9 +40110,8 @@ var FileManagerFilters = ({
|
|
|
39799
40110
|
let filteredClips = categoryClips.filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
39800
40111
|
if (category.id === "idle_time" && idleLabelFilter) {
|
|
39801
40112
|
filteredClips = filteredClips.filter((clip) => {
|
|
39802
|
-
const
|
|
39803
|
-
|
|
39804
|
-
return normalizedRootCause === idleLabelFilter;
|
|
40113
|
+
const classification = getIdleTimeClassification(clip.clipId || clip.id);
|
|
40114
|
+
return classification?.label === idleLabelFilter;
|
|
39805
40115
|
});
|
|
39806
40116
|
}
|
|
39807
40117
|
const displayCount = isTimeFilterActive || category.id === "idle_time" && idleLabelFilter ? filteredClips.length : categoryCount;
|
|
@@ -39831,8 +40141,9 @@ var FileManagerFilters = ({
|
|
|
39831
40141
|
clipPosition: index + 1,
|
|
39832
40142
|
// Store 1-based position
|
|
39833
40143
|
cycleTimeSeconds: cycleTime,
|
|
39834
|
-
duration: clip.duration
|
|
40144
|
+
duration: clip.duration,
|
|
39835
40145
|
// Store duration for custom badge rendering
|
|
40146
|
+
cycleItemCount: clip.cycle_item_count ?? null
|
|
39836
40147
|
};
|
|
39837
40148
|
});
|
|
39838
40149
|
regularCategoryNodes.push({
|
|
@@ -40088,14 +40399,14 @@ var FileManagerFilters = ({
|
|
|
40088
40399
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 mr-3 ${node.type === "category" || node.type === "percentile-category" ? "p-2 rounded-lg shadow-sm group-hover:scale-110 transition-transform duration-200" : "p-0.5"} ${colorClasses && (node.type === "category" || node.type === "percentile-category") ? `${colorClasses.bg} border border-white/60` : ""}`, children: node.type === "video" && (node.categoryId === "idle_time" || node.categoryId === "low_value") ? (
|
|
40089
40400
|
// Show root cause icon for idle time clips
|
|
40090
40401
|
(() => {
|
|
40091
|
-
const
|
|
40092
|
-
if (
|
|
40402
|
+
const classification = getIdleTimeClassification(node.clipId || node.id);
|
|
40403
|
+
if (!classification || classification.status === "processing") {
|
|
40093
40404
|
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-3.5 w-3.5 text-purple-500", strokeWidth: 2.5 });
|
|
40094
40405
|
}
|
|
40095
40406
|
if (!idleTimeVlmEnabled && node.categoryId === "idle_time") {
|
|
40096
40407
|
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-3.5 w-3.5 text-purple-500", strokeWidth: 2.5 });
|
|
40097
40408
|
}
|
|
40098
|
-
const config = getRootCauseConfig(
|
|
40409
|
+
const config = getRootCauseConfig(classification);
|
|
40099
40410
|
if (config) {
|
|
40100
40411
|
const IconComponent = config.Icon;
|
|
40101
40412
|
return /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 ${config.iconColor}`, strokeWidth: 2.5 });
|
|
@@ -40117,10 +40428,10 @@ var FileManagerFilters = ({
|
|
|
40117
40428
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `inline-flex items-center px-2 py-0.5 rounded-md border text-[10px] font-bold ${isLong ? "bg-purple-50 text-purple-700 border-purple-200" : "bg-gray-50 text-gray-600 border-gray-200"}`, children: isLong ? "Long" : "Short" });
|
|
40118
40429
|
}
|
|
40119
40430
|
const clipId = node.clipId || node.id;
|
|
40120
|
-
const
|
|
40121
|
-
const isProcessing =
|
|
40122
|
-
const
|
|
40123
|
-
const
|
|
40431
|
+
const classification = getIdleTimeClassification(clipId);
|
|
40432
|
+
const isProcessing = !classification || classification.status === "processing";
|
|
40433
|
+
const config = isProcessing ? null : getRootCauseConfig(classification);
|
|
40434
|
+
const displayLabel = config?.displayName || "Analyzing...";
|
|
40124
40435
|
const bgClass = config ? config.bgColor : "bg-slate-50";
|
|
40125
40436
|
const textClass = config ? config.color : "text-slate-700";
|
|
40126
40437
|
const borderClass = config ? config.borderColor : "border-slate-200";
|
|
@@ -40130,7 +40441,13 @@ var FileManagerFilters = ({
|
|
|
40130
40441
|
// Show badge for other clips
|
|
40131
40442
|
(() => {
|
|
40132
40443
|
const badge = getClipBadge(node);
|
|
40133
|
-
return /* @__PURE__ */ jsxRuntime.
|
|
40444
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1.5", children: [
|
|
40445
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${badge.className}`, children: badge.text }),
|
|
40446
|
+
node.categoryId === "cycle_completion" && node.cycleItemCount && node.cycleItemCount > 1 ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200", children: [
|
|
40447
|
+
"x",
|
|
40448
|
+
node.cycleItemCount
|
|
40449
|
+
] }) : null
|
|
40450
|
+
] });
|
|
40134
40451
|
})()
|
|
40135
40452
|
) })
|
|
40136
40453
|
] }),
|
|
@@ -40218,7 +40535,7 @@ var FileManagerFilters = ({
|
|
|
40218
40535
|
idleLabelFilter && activeFilter === "idle_time" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2 text-xs text-purple-600 bg-purple-50/60 px-3 py-1.5 rounded-lg border border-purple-100", children: [
|
|
40219
40536
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
40220
40537
|
"Reason: ",
|
|
40221
|
-
idleLabelFilter.replace(/_/g, " ")
|
|
40538
|
+
selectedIdleReasonOption?.displayName || idleLabelFilter.replace(/_/g, " ")
|
|
40222
40539
|
] }),
|
|
40223
40540
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
40224
40541
|
"button",
|
|
@@ -40267,21 +40584,31 @@ var FileManagerFilters = ({
|
|
|
40267
40584
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
40268
40585
|
"Loading idle reasons..."
|
|
40269
40586
|
] }) : idleReasonOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-4 text-sm text-slate-500", children: "No classified idle reasons found yet." }) : idleReasonOptions.map((reason) => {
|
|
40270
|
-
const config = getRootCauseConfig(
|
|
40587
|
+
const config = getRootCauseConfig({
|
|
40588
|
+
status: "classified",
|
|
40589
|
+
label: reason.label,
|
|
40590
|
+
displayName: reason.displayName,
|
|
40591
|
+
paletteToken: reason.paletteToken,
|
|
40592
|
+
iconToken: reason.iconToken,
|
|
40593
|
+
isKnown: reason.isKnown
|
|
40594
|
+
});
|
|
40595
|
+
if (!config) {
|
|
40596
|
+
return null;
|
|
40597
|
+
}
|
|
40271
40598
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
40272
40599
|
"button",
|
|
40273
40600
|
{
|
|
40274
40601
|
onClick: () => {
|
|
40275
|
-
setIdleLabelFilter(reason);
|
|
40602
|
+
setIdleLabelFilter(reason.label);
|
|
40276
40603
|
setShowIdleLabelFilterModal(false);
|
|
40277
40604
|
},
|
|
40278
|
-
className: `w-full px-3 py-2 text-left text-sm rounded-lg transition-colors flex items-center gap-2 mb-1 ${idleLabelFilter === reason ? "bg-purple-50 text-purple-700 font-medium" : "text-slate-700 hover:bg-slate-50"}`,
|
|
40605
|
+
className: `w-full px-3 py-2 text-left text-sm rounded-lg transition-colors flex items-center gap-2 mb-1 ${idleLabelFilter === reason.label ? "bg-purple-50 text-purple-700 font-medium" : "text-slate-700 hover:bg-slate-50"}`,
|
|
40279
40606
|
children: [
|
|
40280
40607
|
/* @__PURE__ */ jsxRuntime.jsx(config.Icon, { className: `h-3.5 w-3.5 ${config.iconColor}` }),
|
|
40281
|
-
reason
|
|
40608
|
+
reason.displayName
|
|
40282
40609
|
]
|
|
40283
40610
|
},
|
|
40284
|
-
reason
|
|
40611
|
+
reason.label
|
|
40285
40612
|
);
|
|
40286
40613
|
}) })
|
|
40287
40614
|
]
|
|
@@ -40396,33 +40723,14 @@ var FileManagerFilters = ({
|
|
|
40396
40723
|
slot.value
|
|
40397
40724
|
)) })
|
|
40398
40725
|
] })
|
|
40399
|
-
] }) })
|
|
40400
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-t border-slate-200 bg-white rounded-b-xl", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
40401
|
-
"button",
|
|
40402
|
-
{
|
|
40403
|
-
onClick: () => {
|
|
40404
|
-
if (startTime && endTime) {
|
|
40405
|
-
setIsTimeFilterActive(true);
|
|
40406
|
-
}
|
|
40407
|
-
setShowTimeFilterModal(false);
|
|
40408
|
-
setStartSearchTerm("");
|
|
40409
|
-
setEndSearchTerm("");
|
|
40410
|
-
},
|
|
40411
|
-
disabled: !startTime || !endTime,
|
|
40412
|
-
className: `
|
|
40413
|
-
w-full px-4 py-2 text-sm font-semibold rounded-lg transition-all
|
|
40414
|
-
${startTime && endTime ? "bg-blue-600 text-white hover:bg-blue-700 active:scale-[0.98]" : "bg-slate-200 text-slate-400 cursor-not-allowed"}
|
|
40415
|
-
`,
|
|
40416
|
-
children: "Apply"
|
|
40417
|
-
}
|
|
40418
|
-
) })
|
|
40726
|
+
] }) })
|
|
40419
40727
|
]
|
|
40420
40728
|
}
|
|
40421
40729
|
)
|
|
40422
40730
|
] }),
|
|
40423
40731
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 flex-1 min-h-0 overflow-y-auto scrollbar-thin", children: [
|
|
40424
40732
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: filterTree.map((node) => renderNode(node)) }),
|
|
40425
|
-
filterTree.length === 0 &&
|
|
40733
|
+
filterTree.length === 0 && (startTime || endTime) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
40426
40734
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-12 w-12 mx-auto" }) }),
|
|
40427
40735
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips found" }),
|
|
40428
40736
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500 mb-4", children: "No clips match the selected time range" }),
|
|
@@ -40432,18 +40740,19 @@ var FileManagerFilters = ({
|
|
|
40432
40740
|
onClick: () => {
|
|
40433
40741
|
setStartTime("");
|
|
40434
40742
|
setEndTime("");
|
|
40743
|
+
setIsTimeFilterActive(false);
|
|
40435
40744
|
},
|
|
40436
40745
|
className: "inline-flex items-center px-4 py-2 bg-blue-50 text-blue-600 text-sm font-medium rounded-lg hover:bg-blue-100 transition-colors duration-200",
|
|
40437
40746
|
children: "Clear time filter"
|
|
40438
40747
|
}
|
|
40439
40748
|
)
|
|
40440
40749
|
] }),
|
|
40441
|
-
filterTree.length === 0 && !
|
|
40750
|
+
filterTree.length === 0 && !startTime && !endTime && categories.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
40442
40751
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HelpCircle, { className: "h-12 w-12 mx-auto" }) }),
|
|
40443
40752
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clip types available" }),
|
|
40444
40753
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500", children: "Loading clip categories..." })
|
|
40445
40754
|
] }),
|
|
40446
|
-
filterTree.length === 0 && !
|
|
40755
|
+
filterTree.length === 0 && !startTime && !endTime && categories.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
40447
40756
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-12 w-12 mx-auto" }) }),
|
|
40448
40757
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips available" }),
|
|
40449
40758
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500", children: "No clips found for the selected time period" })
|
|
@@ -40847,6 +41156,34 @@ function useClipsRealtimeUpdates({
|
|
|
40847
41156
|
hasNewClips: newClipsNotification !== null && newClipsNotification.count > 0
|
|
40848
41157
|
};
|
|
40849
41158
|
}
|
|
41159
|
+
var parseFiniteNumber2 = (value) => {
|
|
41160
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
41161
|
+
return value;
|
|
41162
|
+
}
|
|
41163
|
+
if (typeof value === "string") {
|
|
41164
|
+
const parsed = Number(value);
|
|
41165
|
+
if (Number.isFinite(parsed)) {
|
|
41166
|
+
return parsed;
|
|
41167
|
+
}
|
|
41168
|
+
}
|
|
41169
|
+
return null;
|
|
41170
|
+
};
|
|
41171
|
+
var getMultiCycleItemCount = (clip) => {
|
|
41172
|
+
if (!clip || clip.categoryId !== "cycle_completion") {
|
|
41173
|
+
return null;
|
|
41174
|
+
}
|
|
41175
|
+
const cycleItemCount = parseFiniteNumber2(clip.cycle_item_count);
|
|
41176
|
+
return cycleItemCount !== null && cycleItemCount > 1 ? cycleItemCount : null;
|
|
41177
|
+
};
|
|
41178
|
+
var OVERLAY_ICON_COLOR_BY_PALETTE = {
|
|
41179
|
+
red: "text-red-300",
|
|
41180
|
+
amber: "text-amber-300",
|
|
41181
|
+
blue: "text-blue-300",
|
|
41182
|
+
violet: "text-violet-300",
|
|
41183
|
+
emerald: "text-emerald-300",
|
|
41184
|
+
cyan: "text-cyan-300",
|
|
41185
|
+
slate: "text-slate-200"
|
|
41186
|
+
};
|
|
40850
41187
|
var BottlenecksContent = ({
|
|
40851
41188
|
workspaceId,
|
|
40852
41189
|
workspaceName,
|
|
@@ -41587,6 +41924,10 @@ var BottlenecksContent = ({
|
|
|
41587
41924
|
classificationUpdates[clipId] = {
|
|
41588
41925
|
status,
|
|
41589
41926
|
label: clip.classification_label || void 0,
|
|
41927
|
+
displayName: clip.classification_display_name || void 0,
|
|
41928
|
+
paletteToken: clip.classification_palette_token || void 0,
|
|
41929
|
+
iconToken: clip.classification_icon_token || void 0,
|
|
41930
|
+
isKnown: clip.classification_is_known ?? void 0,
|
|
41590
41931
|
confidence: clip.classification_confidence ?? void 0
|
|
41591
41932
|
};
|
|
41592
41933
|
});
|
|
@@ -42371,79 +42712,13 @@ var BottlenecksContent = ({
|
|
|
42371
42712
|
return () => window.removeEventListener("keydown", handleEscape);
|
|
42372
42713
|
}
|
|
42373
42714
|
}, [isFullscreen, exitFullscreen]);
|
|
42374
|
-
const
|
|
42375
|
-
"Machine Breakdown": {
|
|
42376
|
-
color: "text-white",
|
|
42377
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42378
|
-
borderColor: "border-transparent",
|
|
42379
|
-
Icon: lucideReact.AlertTriangle,
|
|
42380
|
-
iconColor: "text-red-500",
|
|
42381
|
-
// Standard red for high visibility on dark
|
|
42382
|
-
dotColor: "bg-red-600"
|
|
42383
|
-
},
|
|
42384
|
-
"Other": {
|
|
42385
|
-
color: "text-white",
|
|
42386
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42387
|
-
borderColor: "border-transparent",
|
|
42388
|
-
Icon: lucideReact.HelpCircle,
|
|
42389
|
-
iconColor: "text-gray-400",
|
|
42390
|
-
dotColor: "bg-gray-500"
|
|
42391
|
-
},
|
|
42392
|
-
"Power Outage": {
|
|
42393
|
-
color: "text-white",
|
|
42394
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42395
|
-
borderColor: "border-transparent",
|
|
42396
|
-
Icon: lucideReact.Zap,
|
|
42397
|
-
iconColor: "text-red-400",
|
|
42398
|
-
// Lighter red
|
|
42399
|
-
dotColor: "bg-red-500"
|
|
42400
|
-
},
|
|
42401
|
-
"Worker Absent": {
|
|
42402
|
-
color: "text-white",
|
|
42403
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42404
|
-
borderColor: "border-transparent",
|
|
42405
|
-
Icon: lucideReact.UserX,
|
|
42406
|
-
iconColor: "text-red-400",
|
|
42407
|
-
// Lighter red
|
|
42408
|
-
dotColor: "bg-red-500"
|
|
42409
|
-
},
|
|
42410
|
-
"Material Shortage": {
|
|
42411
|
-
color: "text-white",
|
|
42412
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42413
|
-
borderColor: "border-transparent",
|
|
42414
|
-
Icon: lucideReact.Package,
|
|
42415
|
-
iconColor: "text-red-300",
|
|
42416
|
-
// Even lighter red
|
|
42417
|
-
dotColor: "bg-red-400"
|
|
42418
|
-
},
|
|
42419
|
-
"Quality Issue": {
|
|
42420
|
-
color: "text-white",
|
|
42421
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42422
|
-
borderColor: "border-transparent",
|
|
42423
|
-
Icon: lucideReact.XCircle,
|
|
42424
|
-
iconColor: "text-red-300",
|
|
42425
|
-
// Even lighter red
|
|
42426
|
-
dotColor: "bg-red-400"
|
|
42427
|
-
},
|
|
42428
|
-
"Scheduled Maintenance": {
|
|
42429
|
-
color: "text-white",
|
|
42430
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42431
|
-
borderColor: "border-transparent",
|
|
42432
|
-
Icon: lucideReact.Wrench,
|
|
42433
|
-
iconColor: "text-red-200",
|
|
42434
|
-
// Very light red
|
|
42435
|
-
dotColor: "bg-red-300"
|
|
42436
|
-
}
|
|
42437
|
-
};
|
|
42438
|
-
const getIdleTimeRootCause = React141.useCallback((video) => {
|
|
42715
|
+
const getIdleTimeClassification = React141.useCallback((video) => {
|
|
42439
42716
|
if (video.type !== "idle_time") return null;
|
|
42440
42717
|
const videoId = video.id || video.clipId;
|
|
42441
|
-
if (!videoId) return
|
|
42718
|
+
if (!videoId) return null;
|
|
42442
42719
|
const classification = clipClassifications[videoId];
|
|
42443
|
-
console.log(`[
|
|
42444
|
-
|
|
42445
|
-
if (classification.status === "processing") return "processing";
|
|
42446
|
-
return classification.label || "processing";
|
|
42720
|
+
console.log(`[getIdleTimeClassification] Looking up ${videoId}: `, classification);
|
|
42721
|
+
return classification || null;
|
|
42447
42722
|
}, [clipClassifications]);
|
|
42448
42723
|
const getIdleTimeConfidence = React141.useCallback((video) => {
|
|
42449
42724
|
if (video.type !== "idle_time") return null;
|
|
@@ -42454,36 +42729,35 @@ var BottlenecksContent = ({
|
|
|
42454
42729
|
if (classification.status === "processing") return null;
|
|
42455
42730
|
return classification.confidence ?? null;
|
|
42456
42731
|
}, [clipClassifications]);
|
|
42457
|
-
const
|
|
42458
|
-
|
|
42459
|
-
}, []);
|
|
42460
|
-
const getRootCauseConfig = React141.useCallback((rootCause) => {
|
|
42461
|
-
if (!rootCause) return null;
|
|
42462
|
-
if (rootCause === "processing") {
|
|
42732
|
+
const getRootCauseConfig = React141.useCallback((classification) => {
|
|
42733
|
+
if (!classification || classification.status === "processing") {
|
|
42463
42734
|
return {
|
|
42464
42735
|
color: "text-white",
|
|
42465
42736
|
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42466
|
-
borderColor: "border-
|
|
42737
|
+
borderColor: "border-white/10",
|
|
42467
42738
|
Icon: lucideReact.Clock,
|
|
42468
|
-
iconColor: "text-purple-
|
|
42469
|
-
dotColor: "bg-
|
|
42739
|
+
iconColor: "text-purple-300",
|
|
42740
|
+
dotColor: "bg-purple-400",
|
|
42470
42741
|
displayName: "Analyzing..."
|
|
42471
42742
|
};
|
|
42472
42743
|
}
|
|
42473
|
-
const
|
|
42474
|
-
|
|
42475
|
-
|
|
42476
|
-
|
|
42744
|
+
const presentation = getIdleReasonPresentation({
|
|
42745
|
+
label: classification.label,
|
|
42746
|
+
displayName: classification.displayName,
|
|
42747
|
+
paletteToken: classification.paletteToken,
|
|
42748
|
+
iconToken: classification.iconToken,
|
|
42749
|
+
isKnown: classification.isKnown
|
|
42750
|
+
});
|
|
42477
42751
|
return {
|
|
42478
42752
|
color: "text-white",
|
|
42479
42753
|
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42480
|
-
borderColor: "border-
|
|
42481
|
-
Icon:
|
|
42482
|
-
iconColor:
|
|
42483
|
-
dotColor:
|
|
42484
|
-
displayName:
|
|
42754
|
+
borderColor: "border-white/10",
|
|
42755
|
+
Icon: presentation.Icon,
|
|
42756
|
+
iconColor: OVERLAY_ICON_COLOR_BY_PALETTE[presentation.paletteToken] || OVERLAY_ICON_COLOR_BY_PALETTE.slate,
|
|
42757
|
+
dotColor: presentation.bgClass,
|
|
42758
|
+
displayName: presentation.displayName
|
|
42485
42759
|
};
|
|
42486
|
-
}, [
|
|
42760
|
+
}, []);
|
|
42487
42761
|
const getClipTypeLabel = React141.useCallback((video) => {
|
|
42488
42762
|
if (!video) return "";
|
|
42489
42763
|
const currentFilter = activeFilterRef.current;
|
|
@@ -42648,15 +42922,15 @@ var BottlenecksContent = ({
|
|
|
42648
42922
|
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? currentVideo.type === "idle_time" ? (
|
|
42649
42923
|
// Show full colored badge for idle time
|
|
42650
42924
|
(() => {
|
|
42651
|
-
const
|
|
42925
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42652
42926
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42653
|
-
const config = getRootCauseConfig(
|
|
42927
|
+
const config = getRootCauseConfig(classification);
|
|
42654
42928
|
if (!config) return null;
|
|
42655
42929
|
const IconComponent = config.Icon;
|
|
42656
42930
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
42657
|
-
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 left-3 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center gap-1.5 px-2.5 py-1.5
|
|
42658
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42659
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-medium text-xs ${config.color}`, children: config.displayName ||
|
|
42931
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 left-3 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex max-w-[18rem] items-center gap-1.5 rounded-md border px-2.5 py-1.5 shadow-lg ${config.bgColor} ${config.borderColor}`, children: [
|
|
42932
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42933
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `truncate font-medium text-xs ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
42660
42934
|
] }) }),
|
|
42661
42935
|
idleTimeVlmEnabled && confidence !== null && (() => {
|
|
42662
42936
|
const confidencePercent = confidence * 100;
|
|
@@ -42691,9 +42965,9 @@ var BottlenecksContent = ({
|
|
|
42691
42965
|
currentVideo.type === "idle_time" ? (
|
|
42692
42966
|
// Show full colored badge for idle time
|
|
42693
42967
|
(() => {
|
|
42694
|
-
const
|
|
42968
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42695
42969
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42696
|
-
const config = getRootCauseConfig(
|
|
42970
|
+
const config = getRootCauseConfig(classification);
|
|
42697
42971
|
if (!config) return null;
|
|
42698
42972
|
const IconComponent = config.Icon;
|
|
42699
42973
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -42702,9 +42976,9 @@ var BottlenecksContent = ({
|
|
|
42702
42976
|
(confidence * 100).toFixed(0),
|
|
42703
42977
|
"%"
|
|
42704
42978
|
] }) }) }),
|
|
42705
|
-
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 right-3 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center gap-1.5 px-2.5 py-1.5
|
|
42706
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42707
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-medium text-xs ${config.color}`, children:
|
|
42979
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 right-3 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex max-w-[18rem] items-center gap-1.5 rounded-md border px-2.5 py-1.5 shadow-lg ${config.bgColor} ${config.borderColor}`, children: [
|
|
42980
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42981
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `truncate font-medium text-xs ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
42708
42982
|
] }) })
|
|
42709
42983
|
] });
|
|
42710
42984
|
})()
|
|
@@ -42744,6 +43018,7 @@ var BottlenecksContent = ({
|
|
|
42744
43018
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No clips found" })
|
|
42745
43019
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: triageClips.map((clip, index) => {
|
|
42746
43020
|
const isIdleTime = clip.categoryId === "idle_time";
|
|
43021
|
+
const cycleItemCount = getMultiCycleItemCount(clip);
|
|
42747
43022
|
const timeString = isIdleTime && clip.idle_start_time && clip.idle_end_time ? formatIdleTimeRange(clip.idle_start_time, clip.idle_end_time, timezone) : new Date(clip.clip_timestamp).toLocaleTimeString("en-US", {
|
|
42748
43023
|
hour12: true,
|
|
42749
43024
|
hour: "numeric",
|
|
@@ -42796,15 +43071,15 @@ var BottlenecksContent = ({
|
|
|
42796
43071
|
// Idle time clips - show root cause label below time
|
|
42797
43072
|
(() => {
|
|
42798
43073
|
const clipId = clip.id || clip.clipId;
|
|
42799
|
-
const
|
|
43074
|
+
const classification = getIdleTimeClassification({
|
|
42800
43075
|
id: clipId,
|
|
42801
43076
|
type: "idle_time",
|
|
42802
43077
|
creation_timestamp: clip.clip_timestamp
|
|
42803
43078
|
});
|
|
42804
|
-
console.log(`[BottlenecksContent] Sidebar clip ${clipId}:
|
|
42805
|
-
const config = getRootCauseConfig(
|
|
43079
|
+
console.log(`[BottlenecksContent] Sidebar clip ${clipId}: classification=`, clipClassifications[clipId]);
|
|
43080
|
+
const config = getRootCauseConfig(classification);
|
|
42806
43081
|
if (!config) {
|
|
42807
|
-
console.log(`[BottlenecksContent] No config found for
|
|
43082
|
+
console.log(`[BottlenecksContent] No config found for classification on clip: ${clipId}`);
|
|
42808
43083
|
return null;
|
|
42809
43084
|
}
|
|
42810
43085
|
const IconComponent = config.Icon;
|
|
@@ -42819,7 +43094,7 @@ var BottlenecksContent = ({
|
|
|
42819
43094
|
] }) })
|
|
42820
43095
|
] }),
|
|
42821
43096
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pl-6", children: idleTimeVlmEnabled ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center px-2 py-0.5 rounded-md border text-xs font-medium bg-gray-50 text-gray-700 border-gray-200", children: (() => {
|
|
42822
|
-
const displayText = config.displayName ||
|
|
43097
|
+
const displayText = config.displayName || "Analyzing...";
|
|
42823
43098
|
console.log(`[BottlenecksContent] Displaying label: "${displayText}" for clip ${clipId}`);
|
|
42824
43099
|
return displayText;
|
|
42825
43100
|
})() }) : (() => {
|
|
@@ -42839,7 +43114,13 @@ var BottlenecksContent = ({
|
|
|
42839
43114
|
clip.duration ? `${clip.duration.toFixed(1)}s` : "N/A",
|
|
42840
43115
|
")"
|
|
42841
43116
|
] }) }),
|
|
42842
|
-
/* @__PURE__ */ jsxRuntime.
|
|
43117
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
43118
|
+
cycleItemCount ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "px-2 py-1 text-xs font-semibold rounded border border-blue-200 bg-blue-100 text-blue-700", children: [
|
|
43119
|
+
"x",
|
|
43120
|
+
cycleItemCount
|
|
43121
|
+
] }) : null,
|
|
43122
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `px-2 py-1 text-xs font-semibold rounded ${badgeColor}`, children: badgeText })
|
|
43123
|
+
] })
|
|
42843
43124
|
] })
|
|
42844
43125
|
)
|
|
42845
43126
|
},
|
|
@@ -42932,15 +43213,15 @@ var BottlenecksContent = ({
|
|
|
42932
43213
|
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? currentVideo.type === "idle_time" ? (
|
|
42933
43214
|
// Show full colored badge for idle time
|
|
42934
43215
|
(() => {
|
|
42935
|
-
const
|
|
43216
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42936
43217
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42937
|
-
const config = getRootCauseConfig(
|
|
43218
|
+
const config = getRootCauseConfig(classification);
|
|
42938
43219
|
if (!config) return null;
|
|
42939
43220
|
const IconComponent = config.Icon;
|
|
42940
43221
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
42941
|
-
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 left-4 z-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center gap-2 px-3 py-2
|
|
42942
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-4 w-4 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42943
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-medium text-sm ${config.color}`, children:
|
|
43222
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 left-4 z-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex max-w-[20rem] items-center gap-2 rounded-md border px-3 py-2 shadow-lg ${config.bgColor} ${config.borderColor}`, children: [
|
|
43223
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-4 w-4 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
43224
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `truncate font-medium text-sm ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
42944
43225
|
] }) }),
|
|
42945
43226
|
idleTimeVlmEnabled && confidence !== null && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-4 z-50", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center gap-1.5 px-3 py-2 rounded-lg bg-black/70 backdrop-blur-sm shadow-lg border border-white/10", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium text-sm text-white", children: [
|
|
42946
43227
|
"AI Confidence: ",
|
|
@@ -42962,9 +43243,9 @@ var BottlenecksContent = ({
|
|
|
42962
43243
|
] }) }) : currentVideo.type === "idle_time" ? (
|
|
42963
43244
|
// Show full colored badge for idle time
|
|
42964
43245
|
(() => {
|
|
42965
|
-
const
|
|
43246
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42966
43247
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42967
|
-
const config = getRootCauseConfig(
|
|
43248
|
+
const config = getRootCauseConfig(classification);
|
|
42968
43249
|
if (!config) return null;
|
|
42969
43250
|
const IconComponent = config.Icon;
|
|
42970
43251
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -42973,9 +43254,9 @@ var BottlenecksContent = ({
|
|
|
42973
43254
|
(confidence * 100).toFixed(0),
|
|
42974
43255
|
"%"
|
|
42975
43256
|
] }) }) }),
|
|
42976
|
-
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-20 z-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex items-center gap-2 px-3 py-2
|
|
42977
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-4 w-4 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42978
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-medium text-sm ${config.color}`, children:
|
|
43257
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-4 right-20 z-50", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `inline-flex max-w-[20rem] items-center gap-2 rounded-md border px-3 py-2 shadow-lg ${config.bgColor} ${config.borderColor}`, children: [
|
|
43258
|
+
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-4 w-4 flex-shrink-0 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
43259
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `truncate font-medium text-sm ${config.color}`, children: config.displayName || "Analyzing..." })
|
|
42979
43260
|
] }) })
|
|
42980
43261
|
] });
|
|
42981
43262
|
})()
|
|
@@ -44924,16 +45205,6 @@ var LineHistoryCalendar = ({
|
|
|
44924
45205
|
] });
|
|
44925
45206
|
};
|
|
44926
45207
|
var LineHistoryCalendar_default = LineHistoryCalendar;
|
|
44927
|
-
var STATIC_COLORS = {
|
|
44928
|
-
"Operator Absent": "#dc2626",
|
|
44929
|
-
// red-600 - Critical/Urgent
|
|
44930
|
-
"No Material": "#f59e0b",
|
|
44931
|
-
// amber-500 - Warning/Supply Chain
|
|
44932
|
-
"Machine Downtime": "#3b82f6",
|
|
44933
|
-
// blue-500 - Scheduled/Technical
|
|
44934
|
-
"Operator Idle": "#8b5cf6"
|
|
44935
|
-
// violet-500 - Low Priority/Behavioral
|
|
44936
|
-
};
|
|
44937
45208
|
var PRODUCTIVE_COLOR = "#00AB45";
|
|
44938
45209
|
var IDLE_COLOR = "#e5e7eb";
|
|
44939
45210
|
var formatDuration = (seconds) => {
|
|
@@ -44956,19 +45227,21 @@ var formatDuration = (seconds) => {
|
|
|
44956
45227
|
}
|
|
44957
45228
|
return parts.join(" ");
|
|
44958
45229
|
};
|
|
44959
|
-
var getColorForEntry = (
|
|
44960
|
-
const normalized = name.trim().toLowerCase();
|
|
45230
|
+
var getColorForEntry = (entry) => {
|
|
45231
|
+
const normalized = entry.name.trim().toLowerCase();
|
|
44961
45232
|
if (normalized === "productive" || normalized === "productive time") {
|
|
44962
45233
|
return PRODUCTIVE_COLOR;
|
|
44963
45234
|
}
|
|
44964
45235
|
if (normalized === "idle" || normalized === "idle time") {
|
|
44965
45236
|
return IDLE_COLOR;
|
|
44966
45237
|
}
|
|
44967
|
-
|
|
44968
|
-
|
|
44969
|
-
|
|
44970
|
-
|
|
44971
|
-
|
|
45238
|
+
return getIdleReasonHexColor({
|
|
45239
|
+
label: entry.reasonKey || entry.name,
|
|
45240
|
+
displayName: entry.displayName || entry.name,
|
|
45241
|
+
paletteToken: entry.paletteToken,
|
|
45242
|
+
iconToken: entry.iconToken,
|
|
45243
|
+
isKnown: entry.isKnown
|
|
45244
|
+
});
|
|
44972
45245
|
};
|
|
44973
45246
|
var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
|
|
44974
45247
|
if (active && payload && payload.length) {
|
|
@@ -44982,8 +45255,8 @@ var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
|
|
|
44982
45255
|
const hasContributors = contributors.length > 0;
|
|
44983
45256
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white p-3 border border-gray-100 shadow-lg rounded-lg text-xs z-50 min-w-[280px]", children: [
|
|
44984
45257
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 pb-2 mb-2 border-b border-slate-100", children: [
|
|
44985
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2.5 h-2.5 rounded-full flex-shrink-0", style: { backgroundColor: payload[0].payload.fill || getColorForEntry(payload[0].
|
|
44986
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-slate-800 text-[13px]", children: payload[0].name.replace(/_/g, " ") })
|
|
45258
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2.5 h-2.5 rounded-full flex-shrink-0", style: { backgroundColor: payload[0].payload.fill || getColorForEntry(payload[0].payload) } }),
|
|
45259
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-slate-800 text-[13px]", children: datum?.displayName || payload[0].name.replace(/_/g, " ") })
|
|
44987
45260
|
] }),
|
|
44988
45261
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 pb-1", children: [
|
|
44989
45262
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
@@ -45044,7 +45317,8 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45044
45317
|
isLoading = false,
|
|
45045
45318
|
error = null,
|
|
45046
45319
|
hideTotalDuration = false,
|
|
45047
|
-
updateAnimation = "replay"
|
|
45320
|
+
updateAnimation = "replay",
|
|
45321
|
+
variant = "pie"
|
|
45048
45322
|
}) => {
|
|
45049
45323
|
const [activeData, setActiveData] = React141__namespace.default.useState([]);
|
|
45050
45324
|
React141__namespace.default.useEffect(() => {
|
|
@@ -45089,6 +45363,73 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45089
45363
|
if (!data || data.length === 0) {
|
|
45090
45364
|
return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { message: "No Idle Time reasons available" });
|
|
45091
45365
|
}
|
|
45366
|
+
if (variant === "bar") {
|
|
45367
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
45368
|
+
"div",
|
|
45369
|
+
{
|
|
45370
|
+
className: "w-full h-full flex items-center overflow-visible focus:outline-none",
|
|
45371
|
+
tabIndex: -1,
|
|
45372
|
+
onFocus: (e) => e.currentTarget.blur(),
|
|
45373
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
45374
|
+
recharts.BarChart,
|
|
45375
|
+
{
|
|
45376
|
+
data: activeData,
|
|
45377
|
+
layout: "vertical",
|
|
45378
|
+
margin: { top: 5, right: 30, left: 10, bottom: 5 },
|
|
45379
|
+
barCategoryGap: 8,
|
|
45380
|
+
barGap: 2,
|
|
45381
|
+
children: [
|
|
45382
|
+
/* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { strokeDasharray: "3 3", horizontal: false, vertical: true }),
|
|
45383
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
45384
|
+
recharts.XAxis,
|
|
45385
|
+
{
|
|
45386
|
+
type: "number",
|
|
45387
|
+
hide: false,
|
|
45388
|
+
domain: [0, 100],
|
|
45389
|
+
ticks: [0, 20, 40, 60, 80, 100],
|
|
45390
|
+
tickFormatter: (val) => `${val}%`,
|
|
45391
|
+
tick: { fontSize: 10, fill: "#6b7280" },
|
|
45392
|
+
axisLine: { stroke: "#e5e7eb" },
|
|
45393
|
+
tickLine: false
|
|
45394
|
+
}
|
|
45395
|
+
),
|
|
45396
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
45397
|
+
recharts.YAxis,
|
|
45398
|
+
{
|
|
45399
|
+
type: "category",
|
|
45400
|
+
dataKey: "name",
|
|
45401
|
+
tick: { fontSize: 11, fill: "#4b5563" },
|
|
45402
|
+
tickFormatter: (val) => typeof val === "string" ? val.replace(/_/g, " ") : val,
|
|
45403
|
+
width: 90,
|
|
45404
|
+
axisLine: false,
|
|
45405
|
+
tickLine: false
|
|
45406
|
+
}
|
|
45407
|
+
),
|
|
45408
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
45409
|
+
recharts.Tooltip,
|
|
45410
|
+
{
|
|
45411
|
+
cursor: { fill: "rgba(0,0,0,0.04)" },
|
|
45412
|
+
content: /* @__PURE__ */ jsxRuntime.jsx(CustomTooltip, { hideTotalDuration })
|
|
45413
|
+
}
|
|
45414
|
+
),
|
|
45415
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
45416
|
+
recharts.Bar,
|
|
45417
|
+
{
|
|
45418
|
+
dataKey: "value",
|
|
45419
|
+
radius: [0, 4, 4, 0],
|
|
45420
|
+
animationDuration: 1500,
|
|
45421
|
+
animationEasing: "ease-out",
|
|
45422
|
+
isAnimationActive: true,
|
|
45423
|
+
barSize: 20,
|
|
45424
|
+
children: activeData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(recharts.Cell, { fill: getColorForEntry(entry) }, `cell-${index}`))
|
|
45425
|
+
}
|
|
45426
|
+
)
|
|
45427
|
+
]
|
|
45428
|
+
}
|
|
45429
|
+
) })
|
|
45430
|
+
}
|
|
45431
|
+
);
|
|
45432
|
+
}
|
|
45092
45433
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
45093
45434
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
45094
45435
|
.recharts-wrapper:focus,
|
|
@@ -45150,7 +45491,7 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45150
45491
|
children: activeData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
45151
45492
|
recharts.Cell,
|
|
45152
45493
|
{
|
|
45153
|
-
fill: getColorForEntry(entry
|
|
45494
|
+
fill: getColorForEntry(entry),
|
|
45154
45495
|
strokeWidth: 0
|
|
45155
45496
|
},
|
|
45156
45497
|
`cell-${index}`
|
|
@@ -45167,10 +45508,10 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45167
45508
|
"span",
|
|
45168
45509
|
{
|
|
45169
45510
|
className: "inline-block w-2.5 h-2.5 rounded-full mr-1.5 mt-0.5 flex-shrink-0",
|
|
45170
|
-
style: { backgroundColor: getColorForEntry(entry
|
|
45511
|
+
style: { backgroundColor: getColorForEntry(entry) }
|
|
45171
45512
|
}
|
|
45172
45513
|
),
|
|
45173
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600 leading-tight text-[11px] sm:text-xs break-words", children: entry.name.replace(/_/g, " ") })
|
|
45514
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600 leading-tight text-[11px] sm:text-xs break-words", children: entry.displayName || entry.name.replace(/_/g, " ") })
|
|
45174
45515
|
] }, `item-${index}`)) }) })
|
|
45175
45516
|
]
|
|
45176
45517
|
}
|
|
@@ -45295,7 +45636,6 @@ var LineMonthlyHistory = ({
|
|
|
45295
45636
|
const { isIdleTimeVlmEnabled } = useIdleTimeVlmConfig();
|
|
45296
45637
|
const idleTimeVlmEnabled = isIdleTimeVlmEnabled(lineId);
|
|
45297
45638
|
const isUptimeMode = monitoringMode === "uptime";
|
|
45298
|
-
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
45299
45639
|
const chartKey = React141.useMemo(() => `${lineId}-${month}-${year}-${selectedShiftId}-${rangeStart}-${rangeEnd}`, [lineId, month, year, selectedShiftId, rangeStart, rangeEnd]);
|
|
45300
45640
|
const monthBounds = React141.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
45301
45641
|
const normalizedRange = React141.useMemo(() => {
|
|
@@ -45343,20 +45683,20 @@ var LineMonthlyHistory = ({
|
|
|
45343
45683
|
{ efficiency: 0, underperforming: 0, totalWorkspaces: 0, count: 0 }
|
|
45344
45684
|
);
|
|
45345
45685
|
const avgEfficiency = averages.count > 0 ? averages.efficiency / averages.count : 0;
|
|
45346
|
-
const
|
|
45686
|
+
const outputAverages = (analysisMonthlyData || []).reduce(
|
|
45347
45687
|
(acc, day) => {
|
|
45348
45688
|
const shiftData = getShiftData2(day, selectedShiftId);
|
|
45349
45689
|
if (!shiftData || !hasRealData(shiftData)) {
|
|
45350
45690
|
return acc;
|
|
45351
45691
|
}
|
|
45352
|
-
const status = getEfficiencyColor(shiftData.avg_efficiency || 0, effectiveLegend);
|
|
45353
45692
|
return {
|
|
45354
|
-
|
|
45355
|
-
|
|
45693
|
+
output: acc.output + (shiftData.output || 0),
|
|
45694
|
+
count: acc.count + 1
|
|
45356
45695
|
};
|
|
45357
45696
|
},
|
|
45358
|
-
{
|
|
45697
|
+
{ output: 0, count: 0 }
|
|
45359
45698
|
);
|
|
45699
|
+
const avgOutput = outputAverages.count > 0 ? outputAverages.output / outputAverages.count : 0;
|
|
45360
45700
|
const uptimeSummary = React141.useMemo(() => {
|
|
45361
45701
|
if (!isUptimeMode) return null;
|
|
45362
45702
|
const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter((shiftData) => shiftData && hasRealData(shiftData)).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
|
|
@@ -45389,6 +45729,10 @@ var LineMonthlyHistory = ({
|
|
|
45389
45729
|
const efficiencyImproved = efficiencyDelta >= 0;
|
|
45390
45730
|
const EfficiencyTrendIcon = efficiencyImproved ? lucideReact.ArrowUp : lucideReact.ArrowDown;
|
|
45391
45731
|
const efficiencyTrendText = `${Math.abs(efficiencyDelta).toFixed(1)}%`;
|
|
45732
|
+
const outputDelta = trendSummary?.avg_daily_output?.delta_pp ?? 0;
|
|
45733
|
+
const outputImproved = outputDelta >= 0;
|
|
45734
|
+
const OutputTrendIcon = outputImproved ? lucideReact.ArrowUp : lucideReact.ArrowDown;
|
|
45735
|
+
const outputTrendText = `${Math.abs(outputDelta).toFixed(1)}%`;
|
|
45392
45736
|
const utilizationDelta = efficiencyDelta;
|
|
45393
45737
|
const utilizationImproved = utilizationDelta >= 0;
|
|
45394
45738
|
const UtilizationTrendIcon = utilizationImproved ? lucideReact.ArrowUp : lucideReact.ArrowDown;
|
|
@@ -45673,12 +46017,17 @@ var LineMonthlyHistory = ({
|
|
|
45673
46017
|
] })
|
|
45674
46018
|
] }),
|
|
45675
46019
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
45676
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-bold text-gray-700 mb-2", children: "
|
|
45677
|
-
/* @__PURE__ */ jsxRuntime.
|
|
45678
|
-
|
|
45679
|
-
"
|
|
45680
|
-
|
|
45681
|
-
|
|
46020
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-bold text-gray-700 mb-2", children: "Avg. Output" }),
|
|
46021
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
46022
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xl font-bold text-gray-900", children: Math.round(avgOutput).toLocaleString() }),
|
|
46023
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1 ${outputImproved ? "bg-emerald-50 text-emerald-600" : "bg-red-50 text-red-600"} px-1.5 py-0.5 rounded-full text-[10px] font-medium whitespace-nowrap flex-shrink-0`, children: [
|
|
46024
|
+
/* @__PURE__ */ jsxRuntime.jsx(OutputTrendIcon, { className: "w-3 h-3" }),
|
|
46025
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
46026
|
+
outputTrendText,
|
|
46027
|
+
" vs last month"
|
|
46028
|
+
] })
|
|
46029
|
+
] })
|
|
46030
|
+
] })
|
|
45682
46031
|
] })
|
|
45683
46032
|
] }),
|
|
45684
46033
|
isUptimeMode ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `grid grid-cols-1 ${idleTimeVlmEnabled ? "sm:grid-cols-2" : "sm:grid-cols-1"} gap-2 sm:gap-3 lg:gap-4`, children: [
|
|
@@ -46197,11 +46546,6 @@ var LineMonthlyPdfGenerator = ({
|
|
|
46197
46546
|
doc.text("Working Days:", 25, kpiStartY + kpiSpacing * 2);
|
|
46198
46547
|
doc.setFont("helvetica", "bold");
|
|
46199
46548
|
doc.text(`${outputMetrics.totalDays} days`, 120, kpiStartY + kpiSpacing * 2);
|
|
46200
|
-
createKPIBox(kpiStartY + kpiSpacing * 3);
|
|
46201
|
-
doc.setFont("helvetica", "normal");
|
|
46202
|
-
doc.text("Underperforming Days:", 25, kpiStartY + kpiSpacing * 3);
|
|
46203
|
-
doc.setFont("helvetica", "bold");
|
|
46204
|
-
doc.text(`${outputMetrics.underperformingDays} of ${outputMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 3);
|
|
46205
46549
|
}
|
|
46206
46550
|
} else {
|
|
46207
46551
|
doc.setFontSize(12);
|
|
@@ -47779,7 +48123,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
47779
48123
|
availableShifts,
|
|
47780
48124
|
monthlyDataLoading = false,
|
|
47781
48125
|
className = "",
|
|
47782
|
-
trendSummary
|
|
48126
|
+
trendSummary,
|
|
48127
|
+
isAssemblyWorkspace = false
|
|
47783
48128
|
}) => {
|
|
47784
48129
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
47785
48130
|
const isUptimeMode = monitoringMode === "uptime";
|
|
@@ -48018,12 +48363,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48018
48363
|
}, [analysisMonthlyData, selectedShiftId, isUptimeMode, shiftWorkSeconds]);
|
|
48019
48364
|
const efficiencyDelta = trendSummary?.avg_efficiency?.delta_pp ?? 0;
|
|
48020
48365
|
const efficiencyImproved = efficiencyDelta >= 0;
|
|
48021
|
-
const outputDeltaRaw = trendSummary?.avg_daily_output?.delta_pp ?? 0;
|
|
48022
48366
|
const cycleDeltaRaw = trendSummary?.avg_cycle_time?.delta_seconds ?? 0;
|
|
48023
|
-
const outputPrev = trendSummary?.avg_daily_output?.previous ?? 0;
|
|
48024
48367
|
const cyclePrev = trendSummary?.avg_cycle_time?.previous ?? 0;
|
|
48025
|
-
const outputDelta = outputPrev ? outputDeltaRaw / outputPrev * 100 : 0;
|
|
48026
|
-
const outputImproved = outputDelta >= 0;
|
|
48027
48368
|
const cycleDelta = cyclePrev ? cycleDeltaRaw / cyclePrev * 100 : 0;
|
|
48028
48369
|
const cycleWorsened = cycleDelta > 0;
|
|
48029
48370
|
const utilizationDelta = efficiencyDelta;
|
|
@@ -48103,7 +48444,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48103
48444
|
shift.id
|
|
48104
48445
|
)) }) }),
|
|
48105
48446
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [
|
|
48106
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6", children: [
|
|
48447
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-4 sm:p-6 flex flex-col", children: [
|
|
48107
48448
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-2", children: WEEKDAYS3.map((day, idx) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-medium text-gray-500 dark:text-gray-400 text-center", children: day }, day)) }),
|
|
48108
48449
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-2 mt-6", children: calendarData.calendar.map((day, index) => {
|
|
48109
48450
|
const dayNumber = index >= calendarData.startOffset ? index - calendarData.startOffset + 1 : null;
|
|
@@ -48191,8 +48532,32 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48191
48532
|
) }, index);
|
|
48192
48533
|
}) })
|
|
48193
48534
|
] }),
|
|
48194
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
48195
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-
|
|
48535
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 h-full", children: [
|
|
48536
|
+
isAssemblyWorkspace && !isUptimeMode ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-2", children: [
|
|
48537
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48538
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: "Avg Idle Time" }),
|
|
48539
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
48540
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl font-bold text-gray-900", children: formatIdleTime(metrics2?.avgIdleTime ?? 0) }),
|
|
48541
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1 ${idleImproved ? "bg-emerald-50 text-emerald-600" : "bg-red-50 text-red-600"} px-2 py-0.5 rounded-full text-[10px] font-medium whitespace-nowrap flex-shrink-0`, children: [
|
|
48542
|
+
idleImproved ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "w-3 h-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-3 h-3" }),
|
|
48543
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: idleTrendText })
|
|
48544
|
+
] })
|
|
48545
|
+
] })
|
|
48546
|
+
] }),
|
|
48547
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48548
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: "Avg Cycle Time" }),
|
|
48549
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
48550
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-2xl font-bold text-gray-900", children: [
|
|
48551
|
+
metrics2?.avgCycleTime ?? 0,
|
|
48552
|
+
"s"
|
|
48553
|
+
] }),
|
|
48554
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1 ${cycleWorsened ? "bg-red-50 text-red-600" : "bg-emerald-50 text-emerald-600"} px-2 py-0.5 rounded-full text-[10px] font-medium whitespace-nowrap flex-shrink-0`, children: [
|
|
48555
|
+
cycleWorsened ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-3 h-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "w-3 h-3" }),
|
|
48556
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: `${Math.abs(cycleDelta).toFixed(1)}% vs last month` })
|
|
48557
|
+
] })
|
|
48558
|
+
] })
|
|
48559
|
+
] })
|
|
48560
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `grid grid-cols-1 gap-4 ${isUptimeMode ? "md:grid-cols-3" : "md:grid-cols-2"}`, children: [
|
|
48196
48561
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48197
48562
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: isUptimeMode ? "Avg Utilization" : "Avg Efficiency" }),
|
|
48198
48563
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
@@ -48206,16 +48571,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48206
48571
|
] })
|
|
48207
48572
|
] })
|
|
48208
48573
|
] }),
|
|
48209
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48210
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children:
|
|
48574
|
+
isUptimeMode && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48575
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: "Avg Idle Time" }),
|
|
48211
48576
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
48212
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl font-bold text-gray-900", children:
|
|
48213
|
-
|
|
48577
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl font-bold text-gray-900", children: formatIdleTime(metrics2?.avgIdleTime ?? 0) }),
|
|
48578
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1 ${idleImproved ? "bg-emerald-50 text-emerald-600" : "bg-red-50 text-red-600"} px-2 py-0.5 rounded-full text-[10px] font-medium whitespace-nowrap flex-shrink-0`, children: [
|
|
48214
48579
|
idleImproved ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "w-3 h-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-3 h-3" }),
|
|
48215
48580
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: idleTrendText })
|
|
48216
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex items-center gap-1 ${outputImproved ? "bg-emerald-50 text-emerald-600" : "bg-red-50 text-red-600"} px-2 py-0.5 rounded-full text-[10px] font-medium whitespace-nowrap flex-shrink-0`, children: [
|
|
48217
|
-
outputImproved ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-3 h-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "w-3 h-3" }),
|
|
48218
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: `${Math.abs(outputDelta).toFixed(1)}% vs last month` })
|
|
48219
48581
|
] })
|
|
48220
48582
|
] })
|
|
48221
48583
|
] }),
|
|
@@ -48237,9 +48599,9 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48237
48599
|
] })
|
|
48238
48600
|
] }),
|
|
48239
48601
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `grid grid-cols-1 ${idleTimeVlmEnabled ? "sm:grid-cols-2" : "sm:grid-cols-1"} gap-4`, children: [
|
|
48240
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4", children: [
|
|
48602
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col", children: [
|
|
48241
48603
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: isUptimeMode ? "Utilization" : "Time Utilization" }),
|
|
48242
|
-
pieChartData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full
|
|
48604
|
+
pieChartData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full flex items-center overflow-hidden h-[160px]", children: [
|
|
48243
48605
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 h-full min-w-0 relative flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full aspect-square max-h-full", style: { maxWidth: "min(100%, 280px)", containerType: "inline-size" }, children: [
|
|
48244
48606
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.PieChart, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
48245
48607
|
recharts.Pie,
|
|
@@ -48312,7 +48674,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48312
48674
|
] }) })
|
|
48313
48675
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[160px]", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-400", children: "No data available" }) })
|
|
48314
48676
|
] }),
|
|
48315
|
-
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 h-full", children: [
|
|
48677
|
+
idleTimeVlmEnabled && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 h-full flex flex-col", children: [
|
|
48316
48678
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: "Idle Time Breakdown" }),
|
|
48317
48679
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[160px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
48318
48680
|
IdleTimeReasonChart,
|
|
@@ -48324,7 +48686,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48324
48686
|
) })
|
|
48325
48687
|
] })
|
|
48326
48688
|
] }),
|
|
48327
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex-1", children: [
|
|
48689
|
+
(!isAssemblyWorkspace || isUptimeMode) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex-1", children: [
|
|
48328
48690
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: isUptimeMode ? "Daily Utilization" : "Daily Output" }),
|
|
48329
48691
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "220px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
48330
48692
|
recharts.BarChart,
|
|
@@ -48522,7 +48884,7 @@ var WorkspaceWhatsAppShareButton = ({
|
|
|
48522
48884
|
}
|
|
48523
48885
|
);
|
|
48524
48886
|
};
|
|
48525
|
-
var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiencyLegend }) => {
|
|
48887
|
+
var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiencyLegend, hourlyCycleTimes }) => {
|
|
48526
48888
|
const [isGenerating, setIsGenerating] = React141.useState(false);
|
|
48527
48889
|
const entityConfig = useEntityConfig();
|
|
48528
48890
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
@@ -48530,6 +48892,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48530
48892
|
setIsGenerating(true);
|
|
48531
48893
|
try {
|
|
48532
48894
|
const isUptimeMode = workspace.monitoring_mode === "uptime";
|
|
48895
|
+
const isAssemblyCycleMode = !isUptimeMode && workspace.line_assembly_enabled === true && workspace.action_type === "assembly";
|
|
48533
48896
|
const shiftMinutes = getShiftDurationMinutes(workspace.shift_start, workspace.shift_end);
|
|
48534
48897
|
const shiftSeconds = shiftMinutes ? shiftMinutes * 60 : 0;
|
|
48535
48898
|
const idleSeconds = Math.max(workspace.idle_time || 0, 0);
|
|
@@ -48590,9 +48953,38 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48590
48953
|
minute: "2-digit",
|
|
48591
48954
|
hour12: true
|
|
48592
48955
|
});
|
|
48956
|
+
const shiftEndTime = (/* @__PURE__ */ new Date(`2000-01-01 ${workspace.shift_end}`)).toLocaleTimeString("en-IN", {
|
|
48957
|
+
hour: "2-digit",
|
|
48958
|
+
minute: "2-digit",
|
|
48959
|
+
hour12: true
|
|
48960
|
+
});
|
|
48961
|
+
const parseTimeToMinutes3 = (timeValue) => {
|
|
48962
|
+
const [hourPart, minutePart] = timeValue.split(":").map(Number);
|
|
48963
|
+
const hour = Number.isFinite(hourPart) ? hourPart : 0;
|
|
48964
|
+
const minute = Number.isFinite(minutePart) ? minutePart : 0;
|
|
48965
|
+
return hour * 60 + minute;
|
|
48966
|
+
};
|
|
48967
|
+
const toShiftUtcMs = (dateKey, timeValue) => {
|
|
48968
|
+
const [yearPart, monthPart, dayPart] = dateKey.split("-").map(Number);
|
|
48969
|
+
const year = Number.isFinite(yearPart) ? yearPart : 1970;
|
|
48970
|
+
const month = Number.isFinite(monthPart) ? monthPart : 1;
|
|
48971
|
+
const day = Number.isFinite(dayPart) ? dayPart : 1;
|
|
48972
|
+
const [hourPart, minutePart] = timeValue.split(":").map(Number);
|
|
48973
|
+
const hour = Number.isFinite(hourPart) ? hourPart : 0;
|
|
48974
|
+
const minute = Number.isFinite(minutePart) ? minutePart : 0;
|
|
48975
|
+
const IST_OFFSET_MINUTES = 330;
|
|
48976
|
+
return Date.UTC(year, month - 1, day, hour, minute) - IST_OFFSET_MINUTES * 60 * 1e3;
|
|
48977
|
+
};
|
|
48978
|
+
const shiftStartMinutes = parseTimeToMinutes3(workspace.shift_start);
|
|
48979
|
+
const shiftEndMinutes = parseTimeToMinutes3(workspace.shift_end);
|
|
48980
|
+
const wrapsMidnight = shiftEndMinutes <= shiftStartMinutes;
|
|
48981
|
+
const shiftStartUtcMs = toShiftUtcMs(workspace.date, workspace.shift_start);
|
|
48982
|
+
const shiftEndUtcMs = toShiftUtcMs(workspace.date, workspace.shift_end) + (wrapsMidnight ? 24 * 60 * 60 * 1e3 : 0);
|
|
48983
|
+
const isShiftInProgress = Date.now() >= shiftStartUtcMs && Date.now() < shiftEndUtcMs;
|
|
48984
|
+
const reportPeriodEndTime = isShiftInProgress ? currentTime : shiftEndTime;
|
|
48593
48985
|
doc.setFontSize(12);
|
|
48594
48986
|
doc.setTextColor(80, 80, 80);
|
|
48595
|
-
doc.text(`Report Period: ${shiftStartTime} - ${
|
|
48987
|
+
doc.text(`Report Period: ${shiftStartTime} - ${reportPeriodEndTime}`, 20, 79);
|
|
48596
48988
|
doc.setTextColor(0, 0, 0);
|
|
48597
48989
|
doc.setDrawColor(180, 180, 180);
|
|
48598
48990
|
doc.setLineWidth(0.8);
|
|
@@ -48606,10 +48998,8 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48606
48998
|
};
|
|
48607
48999
|
const perfOverviewStartY = 93;
|
|
48608
49000
|
const hasIdleTimeReason = idleTimeReasons && idleTimeReasons.length > 0;
|
|
48609
|
-
|
|
48610
|
-
|
|
48611
|
-
perfOverviewHeight = hasIdleTimeReason ? 70 : 60;
|
|
48612
|
-
}
|
|
49001
|
+
const perfOverviewRows = isUptimeMode ? 3 : isAssemblyCycleMode ? 2 : 4;
|
|
49002
|
+
const perfOverviewHeight = 30 + perfOverviewRows * 10 + (hasIdleTimeReason ? 10 : 0);
|
|
48613
49003
|
doc.setFillColor(245, 245, 245);
|
|
48614
49004
|
doc.roundedRect(15, perfOverviewStartY, 180, perfOverviewHeight, 3, 3, "F");
|
|
48615
49005
|
doc.setFontSize(18);
|
|
@@ -48637,6 +49027,19 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48637
49027
|
doc.text("Stoppages:", 25, kpiStartY + kpiSpacing * 2);
|
|
48638
49028
|
doc.setFont("helvetica", "bold");
|
|
48639
49029
|
doc.text(`${workspace.total_actions}`, 120, kpiStartY + kpiSpacing * 2);
|
|
49030
|
+
} else if (isAssemblyCycleMode) {
|
|
49031
|
+
createKPIBox(kpiStartY);
|
|
49032
|
+
doc.setFontSize(11);
|
|
49033
|
+
doc.setFont("helvetica", "normal");
|
|
49034
|
+
doc.text("Average Cycle Time:", 25, kpiStartY);
|
|
49035
|
+
doc.setFont("helvetica", "bold");
|
|
49036
|
+
doc.text(`${(workspace.avg_cycle_time || 0).toFixed(1)}s`, 120, kpiStartY);
|
|
49037
|
+
createKPIBox(kpiStartY + kpiSpacing);
|
|
49038
|
+
doc.setFont("helvetica", "normal");
|
|
49039
|
+
doc.text("Total Idle Time:", 25, kpiStartY + kpiSpacing);
|
|
49040
|
+
doc.setFont("helvetica", "bold");
|
|
49041
|
+
const idleTimeFormatted = formatIdleTime(workspace.idle_time);
|
|
49042
|
+
doc.text(idleTimeFormatted, 120, kpiStartY + kpiSpacing);
|
|
48640
49043
|
} else {
|
|
48641
49044
|
createKPIBox(kpiStartY);
|
|
48642
49045
|
doc.setFontSize(11);
|
|
@@ -48673,17 +49076,11 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48673
49076
|
const reasonText = `${reasonName} (${topReason.value.toFixed(1)}%)`;
|
|
48674
49077
|
doc.text(reasonText, 120, reasonY);
|
|
48675
49078
|
}
|
|
48676
|
-
|
|
48677
|
-
if (isUptimeMode) {
|
|
48678
|
-
separatorBeforeHourlyY -= 10;
|
|
48679
|
-
}
|
|
49079
|
+
const separatorBeforeHourlyY = perfOverviewStartY + perfOverviewHeight + 10;
|
|
48680
49080
|
doc.setDrawColor(180, 180, 180);
|
|
48681
49081
|
doc.setLineWidth(0.8);
|
|
48682
49082
|
doc.line(20, separatorBeforeHourlyY, 190, separatorBeforeHourlyY);
|
|
48683
|
-
|
|
48684
|
-
if (isUptimeMode) {
|
|
48685
|
-
hourlyPerfStartY -= 10;
|
|
48686
|
-
}
|
|
49083
|
+
const hourlyPerfStartY = separatorBeforeHourlyY + 5;
|
|
48687
49084
|
const uptimeSeries = isUptimeMode ? buildUptimeSeries({
|
|
48688
49085
|
idleTimeHourly: workspace.idle_time_hourly,
|
|
48689
49086
|
shiftStart: workspace.shift_start,
|
|
@@ -48701,8 +49098,9 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48701
49098
|
const uptimePercent = total > 0 ? Math.round(activeMinutes / total * 100) : 0;
|
|
48702
49099
|
return { activeMinutes, idleMinutes, uptimePercent };
|
|
48703
49100
|
}) : [];
|
|
48704
|
-
const hourlyData = isUptimeMode ? hourlyUptime : workspace.hourly_action_counts || [];
|
|
49101
|
+
const hourlyData = isUptimeMode ? hourlyUptime : isAssemblyCycleMode ? hourlyCycleTimes && hourlyCycleTimes.length > 0 ? hourlyCycleTimes : workspace.hourly_action_counts || [] : workspace.hourly_action_counts || [];
|
|
48705
49102
|
const hourlyTarget = workspace.pph_threshold;
|
|
49103
|
+
const cycleTarget = workspace.ideal_cycle_time || 0;
|
|
48706
49104
|
const pageHeight = doc.internal.pageSize.height;
|
|
48707
49105
|
const maxContentY = pageHeight - 15;
|
|
48708
49106
|
const baseTableStartY = hourlyPerfStartY + 31;
|
|
@@ -48727,12 +49125,16 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48727
49125
|
doc.setFont("helvetica", "bold");
|
|
48728
49126
|
doc.setTextColor(40, 40, 40);
|
|
48729
49127
|
const hourlyTitleY = hourlyPerfStartY + 10;
|
|
48730
|
-
doc.text(
|
|
49128
|
+
doc.text(
|
|
49129
|
+
isUptimeMode ? "Hourly Utilization" : isAssemblyCycleMode ? "Hourly Cycle Time" : "Hourly Performance",
|
|
49130
|
+
20,
|
|
49131
|
+
hourlyTitleY
|
|
49132
|
+
);
|
|
48731
49133
|
doc.setTextColor(0, 0, 0);
|
|
48732
49134
|
const headerY = titleFontSize === 16 ? hourlyPerfStartY + 18 : hourlyPerfStartY + 20;
|
|
48733
49135
|
const gridTopY = headerY - 5;
|
|
48734
49136
|
const headerBottomY = gridTopY + 8;
|
|
48735
|
-
const colBoundaries = isUptimeMode ? [20, 105, 190] : [20, 70, 100, 130, 155, 190];
|
|
49137
|
+
const colBoundaries = isUptimeMode ? [20, 105, 190] : isAssemblyCycleMode ? [20, 85, 125, 165, 190] : [20, 70, 100, 130, 155, 190];
|
|
48736
49138
|
const totalRows = hourlyData.length;
|
|
48737
49139
|
const gridBottomY = headerBottomY + totalRows * rowHeight;
|
|
48738
49140
|
const tableHeight = gridBottomY - gridTopY;
|
|
@@ -48753,6 +49155,10 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48753
49155
|
doc.text("Time Range", 25, headerTextY);
|
|
48754
49156
|
if (isUptimeMode) {
|
|
48755
49157
|
doc.text("Utilization", 147, headerTextY);
|
|
49158
|
+
} else if (isAssemblyCycleMode) {
|
|
49159
|
+
doc.text("Standard", 90, headerTextY);
|
|
49160
|
+
doc.text("Average", 130, headerTextY);
|
|
49161
|
+
doc.text("Status", 170, headerTextY);
|
|
48756
49162
|
} else {
|
|
48757
49163
|
doc.text("Output", 75, headerTextY);
|
|
48758
49164
|
doc.text("Target", 105, headerTextY);
|
|
@@ -48801,6 +49207,25 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48801
49207
|
if (isUptimeMode) {
|
|
48802
49208
|
const utilizationStr = dataCollected ? `${uptimePercent}%` : "TBD";
|
|
48803
49209
|
doc.text(utilizationStr, 147, yPos);
|
|
49210
|
+
} else if (isAssemblyCycleMode) {
|
|
49211
|
+
const actualCycleTime = Number(outputValue) || 0;
|
|
49212
|
+
const standardCycleStr = `${cycleTarget.toFixed(1)}s`;
|
|
49213
|
+
const actualCycleStr = dataCollected ? `${actualCycleTime.toFixed(1)}s` : "TBD";
|
|
49214
|
+
doc.text(standardCycleStr, 90, yPos);
|
|
49215
|
+
doc.text(actualCycleStr, 130, yPos);
|
|
49216
|
+
if (!dataCollected) {
|
|
49217
|
+
doc.setTextColor(100, 100, 100);
|
|
49218
|
+
doc.text("-", 170, yPos);
|
|
49219
|
+
} else if (actualCycleTime > 0 && actualCycleTime <= cycleTarget) {
|
|
49220
|
+
doc.setTextColor(0, 171, 69);
|
|
49221
|
+
doc.setFont("ZapfDingbats", "normal");
|
|
49222
|
+
doc.text("4", 170, yPos);
|
|
49223
|
+
doc.setFont("helvetica", "normal");
|
|
49224
|
+
} else {
|
|
49225
|
+
doc.setTextColor(227, 67, 41);
|
|
49226
|
+
doc.text("\xD7", 170, yPos);
|
|
49227
|
+
}
|
|
49228
|
+
doc.setTextColor(0, 0, 0);
|
|
48804
49229
|
} else {
|
|
48805
49230
|
doc.text(outputStr, 75, yPos);
|
|
48806
49231
|
doc.text(targetStr, 105, yPos);
|
|
@@ -48872,7 +49297,8 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
48872
49297
|
shiftConfig,
|
|
48873
49298
|
efficiencyLegend,
|
|
48874
49299
|
className,
|
|
48875
|
-
compact = false
|
|
49300
|
+
compact = false,
|
|
49301
|
+
isAssemblyWorkspace = false
|
|
48876
49302
|
}) => {
|
|
48877
49303
|
const [isGenerating, setIsGenerating] = React141.useState(false);
|
|
48878
49304
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
@@ -48995,6 +49421,7 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
48995
49421
|
avgOutput: filteredShifts.reduce((sum, shift) => sum + shift.output, 0) / filteredShifts.length,
|
|
48996
49422
|
avgCycleTime: filteredShifts.reduce((sum, shift) => sum + shift.cycleTime, 0) / filteredShifts.length,
|
|
48997
49423
|
avgPph: filteredShifts.reduce((sum, shift) => sum + shift.pph, 0) / filteredShifts.length,
|
|
49424
|
+
avgIdleTime: filteredShifts.reduce((sum, shift) => sum + shift.idleTime, 0) / filteredShifts.length,
|
|
48998
49425
|
totalDays: filteredShifts.length,
|
|
48999
49426
|
underperformingDays: filteredShifts.filter((shift) => shift.efficiency < effectiveLegend.green_min).length
|
|
49000
49427
|
} : null;
|
|
@@ -49006,7 +49433,8 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49006
49433
|
doc.roundedRect(22, y - 7, 165, 12, 2, 2, "S");
|
|
49007
49434
|
};
|
|
49008
49435
|
doc.setFillColor(245, 245, 245);
|
|
49009
|
-
|
|
49436
|
+
const isAssemblyWorkspaceAndNotUptime = !isUptimeMode && isAssemblyWorkspace;
|
|
49437
|
+
doc.roundedRect(15, 95, 180, isAssemblyWorkspaceAndNotUptime ? 40 : 70, 3, 3, "F");
|
|
49010
49438
|
doc.setFontSize(18);
|
|
49011
49439
|
doc.setFont("helvetica", "bold");
|
|
49012
49440
|
doc.setTextColor(40, 40, 40);
|
|
@@ -49045,32 +49473,41 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49045
49473
|
doc.text(`${uptimeMetrics.underperformingDays} of ${uptimeMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 4);
|
|
49046
49474
|
} else {
|
|
49047
49475
|
const outputMetrics = monthlyMetrics;
|
|
49048
|
-
|
|
49049
|
-
|
|
49050
|
-
|
|
49051
|
-
|
|
49052
|
-
|
|
49053
|
-
|
|
49054
|
-
|
|
49055
|
-
|
|
49056
|
-
|
|
49057
|
-
|
|
49058
|
-
|
|
49059
|
-
|
|
49060
|
-
|
|
49061
|
-
|
|
49062
|
-
|
|
49063
|
-
|
|
49064
|
-
|
|
49065
|
-
|
|
49066
|
-
|
|
49067
|
-
|
|
49068
|
-
|
|
49069
|
-
|
|
49070
|
-
|
|
49071
|
-
|
|
49072
|
-
|
|
49073
|
-
|
|
49476
|
+
if (!isAssemblyWorkspace) {
|
|
49477
|
+
createKPIBox(kpiStartY);
|
|
49478
|
+
doc.setFontSize(11);
|
|
49479
|
+
doc.setFont("helvetica", "normal");
|
|
49480
|
+
doc.text("Average Efficiency:", 25, kpiStartY);
|
|
49481
|
+
doc.setFont("helvetica", "bold");
|
|
49482
|
+
doc.text(`${outputMetrics.avgEfficiency.toFixed(1)}% (Target: ${Math.round(effectiveLegend.green_min)}%)`, 120, kpiStartY);
|
|
49483
|
+
createKPIBox(kpiStartY + kpiSpacing);
|
|
49484
|
+
doc.setFont("helvetica", "normal");
|
|
49485
|
+
doc.text("Average PPH:", 25, kpiStartY + kpiSpacing);
|
|
49486
|
+
doc.setFont("helvetica", "bold");
|
|
49487
|
+
doc.text(`${outputMetrics.avgPph.toFixed(1)} per hour`, 120, kpiStartY + kpiSpacing);
|
|
49488
|
+
createKPIBox(kpiStartY + kpiSpacing * 2);
|
|
49489
|
+
doc.setFont("helvetica", "normal");
|
|
49490
|
+
doc.text("Working Days:", 25, kpiStartY + kpiSpacing * 2);
|
|
49491
|
+
doc.setFont("helvetica", "bold");
|
|
49492
|
+
doc.text(`${outputMetrics.totalDays} days`, 120, kpiStartY + kpiSpacing * 2);
|
|
49493
|
+
createKPIBox(kpiStartY + kpiSpacing * 3);
|
|
49494
|
+
doc.setFont("helvetica", "normal");
|
|
49495
|
+
doc.text("Underperforming Days:", 25, kpiStartY + kpiSpacing * 3);
|
|
49496
|
+
doc.setFont("helvetica", "bold");
|
|
49497
|
+
doc.text(`${outputMetrics.underperformingDays} of ${outputMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 3);
|
|
49498
|
+
} else {
|
|
49499
|
+
createKPIBox(kpiStartY);
|
|
49500
|
+
doc.setFontSize(11);
|
|
49501
|
+
doc.setFont("helvetica", "normal");
|
|
49502
|
+
doc.text("Average Cycle Time:", 25, kpiStartY);
|
|
49503
|
+
doc.setFont("helvetica", "bold");
|
|
49504
|
+
doc.text(`${Math.round(outputMetrics.avgCycleTime)}s`, 120, kpiStartY);
|
|
49505
|
+
createKPIBox(kpiStartY + kpiSpacing);
|
|
49506
|
+
doc.setFont("helvetica", "normal");
|
|
49507
|
+
doc.text("Average Idle Time:", 25, kpiStartY + kpiSpacing);
|
|
49508
|
+
doc.setFont("helvetica", "bold");
|
|
49509
|
+
doc.text(formatIdleTime(outputMetrics.avgIdleTime ?? 0), 120, kpiStartY + kpiSpacing);
|
|
49510
|
+
}
|
|
49074
49511
|
}
|
|
49075
49512
|
} else {
|
|
49076
49513
|
doc.setFontSize(12);
|
|
@@ -49081,29 +49518,33 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49081
49518
|
}
|
|
49082
49519
|
doc.setDrawColor(180, 180, 180);
|
|
49083
49520
|
doc.setLineWidth(0.8);
|
|
49084
|
-
|
|
49521
|
+
const separatorY = isAssemblyWorkspaceAndNotUptime ? 150 : 180;
|
|
49522
|
+
doc.line(20, separatorY, 190, separatorY);
|
|
49085
49523
|
doc.setFillColor(245, 245, 245);
|
|
49086
|
-
|
|
49524
|
+
const dailySectionY = isAssemblyWorkspaceAndNotUptime ? 155 : 185;
|
|
49525
|
+
doc.roundedRect(15, dailySectionY, 180, 85, 3, 3, "F");
|
|
49087
49526
|
doc.setFontSize(18);
|
|
49088
49527
|
doc.setFont("helvetica", "bold");
|
|
49089
49528
|
doc.setTextColor(40, 40, 40);
|
|
49090
|
-
doc.text(isUptimeMode ? "Daily Utilization Summary" : "Daily Performance Summary", 20,
|
|
49529
|
+
doc.text(isUptimeMode ? "Daily Utilization Summary" : "Daily Performance Summary", 20, dailySectionY + 10);
|
|
49091
49530
|
doc.setTextColor(0, 0, 0);
|
|
49092
49531
|
if (validDays.length > 0) {
|
|
49093
49532
|
doc.setFontSize(10);
|
|
49094
49533
|
doc.setFont("helvetica", "bold");
|
|
49095
49534
|
doc.setFillColor(240, 240, 240);
|
|
49096
|
-
|
|
49097
|
-
doc.
|
|
49098
|
-
|
|
49099
|
-
doc.text(
|
|
49100
|
-
doc.text(isUptimeMode ? "
|
|
49101
|
-
doc.text("
|
|
49535
|
+
const tableHeaderY = dailySectionY + 15;
|
|
49536
|
+
doc.roundedRect(20, tableHeaderY, 170, 7, 1, 1, "F");
|
|
49537
|
+
const textY = tableHeaderY + 5;
|
|
49538
|
+
doc.text("Date", 25, textY);
|
|
49539
|
+
doc.text(isUptimeMode ? "Productive" : isAssemblyWorkspace ? "Cycle Time" : "Actual", 60, textY);
|
|
49540
|
+
doc.text(isUptimeMode ? "Idle" : isAssemblyWorkspace ? "Target CT" : "Standard", 95, textY);
|
|
49541
|
+
doc.text(isUptimeMode ? "Utilization" : "Efficiency", 135, textY);
|
|
49542
|
+
doc.text("Status", 170, textY);
|
|
49102
49543
|
doc.setLineWidth(0.2);
|
|
49103
49544
|
doc.setDrawColor(220, 220, 220);
|
|
49104
|
-
doc.line(20,
|
|
49545
|
+
doc.line(20, textY + 3, 190, textY + 3);
|
|
49105
49546
|
doc.setFont("helvetica", "normal");
|
|
49106
|
-
let yPos =
|
|
49547
|
+
let yPos = textY + 10;
|
|
49107
49548
|
const recentDays = validDays.slice(-10).reverse();
|
|
49108
49549
|
recentDays.forEach((dayData, index) => {
|
|
49109
49550
|
if (yPos > 260) return;
|
|
@@ -49137,8 +49578,13 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49137
49578
|
}
|
|
49138
49579
|
doc.setTextColor(0, 0, 0);
|
|
49139
49580
|
} else {
|
|
49140
|
-
|
|
49141
|
-
|
|
49581
|
+
if (isAssemblyWorkspace) {
|
|
49582
|
+
doc.text(`${shift.cycleTime.toFixed(1)}`, 60, yPos);
|
|
49583
|
+
doc.text(`${shift.pphThreshold > 0 ? (3600 / shift.pphThreshold).toFixed(1) : "-"}`, 95, yPos);
|
|
49584
|
+
} else {
|
|
49585
|
+
doc.text(`${shift.output}`, 60, yPos);
|
|
49586
|
+
doc.text(`${shift.targetOutput}`, 95, yPos);
|
|
49587
|
+
}
|
|
49142
49588
|
doc.text(`${shift.efficiency.toFixed(1)}%`, 135, yPos);
|
|
49143
49589
|
if (shift.efficiency >= effectiveLegend.green_min) {
|
|
49144
49590
|
doc.setTextColor(0, 171, 69);
|
|
@@ -49153,12 +49599,12 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49153
49599
|
});
|
|
49154
49600
|
doc.setLineWidth(0.2);
|
|
49155
49601
|
doc.setDrawColor(220, 220, 220);
|
|
49156
|
-
doc.roundedRect(20,
|
|
49602
|
+
doc.roundedRect(20, tableHeaderY, 170, yPos - tableHeaderY - 3, 1, 1, "S");
|
|
49157
49603
|
} else {
|
|
49158
49604
|
doc.setFontSize(12);
|
|
49159
49605
|
doc.setFont("helvetica", "normal");
|
|
49160
49606
|
doc.setTextColor(100, 100, 100);
|
|
49161
|
-
doc.text("No daily data available for this month", 25,
|
|
49607
|
+
doc.text("No daily data available for this month", 25, dailySectionY + 30);
|
|
49162
49608
|
doc.setTextColor(0, 0, 0);
|
|
49163
49609
|
}
|
|
49164
49610
|
doc.setFontSize(9);
|
|
@@ -49191,46 +49637,64 @@ var WorkspaceCycleTimeMetricCards = ({
|
|
|
49191
49637
|
workspace,
|
|
49192
49638
|
className,
|
|
49193
49639
|
legend,
|
|
49194
|
-
layout: layout2 = "grid"
|
|
49640
|
+
layout: layout2 = "grid",
|
|
49641
|
+
isAssemblyWorkspace = false,
|
|
49642
|
+
idleTimeData
|
|
49195
49643
|
}) => {
|
|
49196
49644
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
49197
49645
|
const efficiencyValue = workspace.avg_efficiency || 0;
|
|
49198
49646
|
const efficiencyTarget = effectiveLegend.green_min;
|
|
49199
49647
|
const efficiencyColor = getEfficiencyHexColor(efficiencyValue, effectiveLegend);
|
|
49200
|
-
const hideEfficiencyCard = shouldHideWorkspaceEfficiencyCard(workspace);
|
|
49201
|
-
const
|
|
49648
|
+
const hideEfficiencyCard = isAssemblyWorkspace || shouldHideWorkspaceEfficiencyCard(workspace);
|
|
49649
|
+
const totalCards = 2 + (hideEfficiencyCard ? 0 : 1) + (idleTimeData ? 1 : 0);
|
|
49650
|
+
let gridColsClass = "lg:grid-cols-3";
|
|
49651
|
+
if (totalCards === 4) gridColsClass = "lg:grid-cols-4";
|
|
49652
|
+
else if (totalCards === 2) gridColsClass = "lg:grid-cols-2";
|
|
49653
|
+
const containerClassName = layout2 === "stack" ? `space-y-4 ${className || ""}` : `grid grid-cols-1 gap-4 sm:gap-3 sm:grid-cols-2 ${gridColsClass} w-full h-full min-h-0 ${className || ""}`;
|
|
49202
49654
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClassName, children: [
|
|
49203
|
-
!hideEfficiencyCard && /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
49204
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-
|
|
49205
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49206
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-5xl font-bold", style: { color: efficiencyColor }, children: [
|
|
49655
|
+
!hideEfficiencyCard && /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm border border-gray-200 h-full min-h-[150px] sm:min-h-0 rounded-xl", children: [
|
|
49656
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-1 pt-5 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-[15px] font-bold text-center text-gray-900 tracking-wide", children: "Efficiency" }) }),
|
|
49657
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardContent2, { className: "flex-1 flex flex-col items-center justify-center pb-6", children: [
|
|
49658
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-5xl font-bold tracking-tight", style: { color: efficiencyColor }, children: [
|
|
49207
49659
|
efficiencyValue.toFixed(1),
|
|
49208
49660
|
"%"
|
|
49209
49661
|
] }),
|
|
49210
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-
|
|
49662
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 mt-1 font-medium tracking-wide", children: [
|
|
49211
49663
|
"Target: ",
|
|
49212
49664
|
Math.round(efficiencyTarget),
|
|
49213
49665
|
"%"
|
|
49214
49666
|
] })
|
|
49215
|
-
] })
|
|
49667
|
+
] })
|
|
49216
49668
|
] }),
|
|
49217
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
49218
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-
|
|
49219
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49220
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-
|
|
49221
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-
|
|
49669
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm border border-gray-200 h-full min-h-[150px] sm:min-h-0 rounded-xl", children: [
|
|
49670
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-1 pt-5 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-[15px] font-bold text-center text-gray-900 tracking-wide", children: "Cycle Time (s)" }) }),
|
|
49671
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardContent2, { className: "flex-1 flex flex-col items-center justify-center pb-6", children: [
|
|
49672
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold tracking-tight ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-[#34C759]"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
49673
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 mt-1 font-medium tracking-wide", children: [
|
|
49222
49674
|
"Standard: ",
|
|
49223
49675
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
49224
49676
|
"s"
|
|
49225
49677
|
] })
|
|
49226
|
-
] })
|
|
49678
|
+
] })
|
|
49227
49679
|
] }),
|
|
49228
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
49229
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-
|
|
49230
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49231
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-
|
|
49232
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-
|
|
49233
|
-
] })
|
|
49680
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm border border-gray-200 h-full min-h-[150px] sm:min-h-0 rounded-xl", children: [
|
|
49681
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-1 pt-5 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-[15px] font-bold text-center text-gray-900 tracking-wide", children: "Idle Time" }) }),
|
|
49682
|
+
/* @__PURE__ */ jsxRuntime.jsxs(CardContent2, { className: "flex-1 flex flex-col items-center justify-center pb-6", children: [
|
|
49683
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold tracking-tight ${!workspace.idle_time || workspace.idle_time <= 0 ? "text-[#34C759]" : workspace.idle_time <= 300 ? "text-yellow-500" : "text-red-500"}`, children: formatIdleTime(workspace.idle_time) }),
|
|
49684
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mt-1 font-medium tracking-wide", children: "Total idle time" })
|
|
49685
|
+
] })
|
|
49686
|
+
] }),
|
|
49687
|
+
idleTimeData && /* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm border border-gray-200 h-full min-h-[150px] sm:min-h-0 rounded-xl", children: [
|
|
49688
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-1 pt-5 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-[15px] font-bold text-center text-gray-900 tracking-wide", children: "Idle Time Breakdown" }) }),
|
|
49689
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 p-2 flex items-center justify-center h-full sm:h-auto min-h-[120px] sm:min-h-[100px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
49690
|
+
IdleTimeReasonChart,
|
|
49691
|
+
{
|
|
49692
|
+
data: idleTimeData.chartData,
|
|
49693
|
+
isLoading: idleTimeData.isLoading,
|
|
49694
|
+
error: idleTimeData.error,
|
|
49695
|
+
variant: "bar"
|
|
49696
|
+
}
|
|
49697
|
+
) })
|
|
49234
49698
|
] })
|
|
49235
49699
|
] });
|
|
49236
49700
|
};
|
|
@@ -49368,13 +49832,13 @@ var getWorkspaceStyles = (position, isPlaceholder = false) => {
|
|
|
49368
49832
|
${isPlaceholder ? "cursor-default" : ""}`;
|
|
49369
49833
|
};
|
|
49370
49834
|
var formatPercentRange = (min, max) => {
|
|
49371
|
-
const
|
|
49835
|
+
const format9 = (value) => Number.isInteger(value) ? `${value}` : value.toFixed(1);
|
|
49372
49836
|
if (min >= 100 || max >= 100) {
|
|
49373
|
-
return `${
|
|
49837
|
+
return `${format9(min)}+%`;
|
|
49374
49838
|
}
|
|
49375
|
-
return `${
|
|
49839
|
+
return `${format9(min)}-${format9(max)}%`;
|
|
49376
49840
|
};
|
|
49377
|
-
var
|
|
49841
|
+
var Legend5 = ({
|
|
49378
49842
|
useBottleneckLabel = false,
|
|
49379
49843
|
legend,
|
|
49380
49844
|
metricLabel = "Efficiency"
|
|
@@ -49560,7 +50024,7 @@ var WorkspaceGrid = React141__namespace.default.memo(({
|
|
|
49560
50024
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative w-full h-full overflow-hidden ${className}`, children: [
|
|
49561
50025
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-0 left-2 sm:left-4 right-2 sm:right-8 z-20", children: [
|
|
49562
50026
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row items-center justify-between py-1 sm:py-1.5 gap-2", children: [
|
|
49563
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
50027
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, useBottleneckLabel: hasFlowBuffers, metricLabel: legendMetricLabel }) }),
|
|
49564
50028
|
mapViewEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
49565
50029
|
"button",
|
|
49566
50030
|
{
|
|
@@ -49577,7 +50041,7 @@ var WorkspaceGrid = React141__namespace.default.memo(({
|
|
|
49577
50041
|
}
|
|
49578
50042
|
)
|
|
49579
50043
|
] }),
|
|
49580
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden mt-1 mr-32", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
50044
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden mt-1 mr-32", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, useBottleneckLabel: hasFlowBuffers, metricLabel: legendMetricLabel }) })
|
|
49581
50045
|
] }),
|
|
49582
50046
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-14 sm:top-16 left-0 right-0 bottom-0", children: /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { mode: "wait", children: viewMode === "video" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
49583
50047
|
motion.div,
|
|
@@ -50088,7 +50552,7 @@ var KPISection = React141.memo(({
|
|
|
50088
50552
|
value: showSkeleton ? "" : kpis.efficiency.value,
|
|
50089
50553
|
change: effChange,
|
|
50090
50554
|
trend: effTrend,
|
|
50091
|
-
trendLabel: "
|
|
50555
|
+
trendLabel: "vs yesterday",
|
|
50092
50556
|
trendMode: "pill",
|
|
50093
50557
|
suffix: "%",
|
|
50094
50558
|
showZeroChange: true,
|
|
@@ -52324,7 +52788,7 @@ var SideNavBar = React141.memo(({
|
|
|
52324
52788
|
setIsAlertsOpen(willOpen);
|
|
52325
52789
|
setIsSettingsOpen(false);
|
|
52326
52790
|
if (willOpen) {
|
|
52327
|
-
trackCoreEvent("Alerts
|
|
52791
|
+
trackCoreEvent("Alerts page clicked", { source: "side_nav" });
|
|
52328
52792
|
void refreshAlertsSummary();
|
|
52329
52793
|
}
|
|
52330
52794
|
},
|
|
@@ -52479,7 +52943,7 @@ var SideNavBar = React141.memo(({
|
|
|
52479
52943
|
{
|
|
52480
52944
|
onClick: () => {
|
|
52481
52945
|
setIsAlertsOpen(true);
|
|
52482
|
-
trackCoreEvent("Alerts
|
|
52946
|
+
trackCoreEvent("Alerts page clicked", { source: "side_nav_mobile" });
|
|
52483
52947
|
void refreshAlertsSummary();
|
|
52484
52948
|
onMobileMenuClose?.();
|
|
52485
52949
|
},
|
|
@@ -59689,7 +60153,8 @@ var MonthlyRangeFilter = ({
|
|
|
59689
60153
|
onMonthNavigate,
|
|
59690
60154
|
className,
|
|
59691
60155
|
variant = "default",
|
|
59692
|
-
showLabel = true
|
|
60156
|
+
showLabel = true,
|
|
60157
|
+
singleDateOnly = false
|
|
59693
60158
|
}) => {
|
|
59694
60159
|
const todayKey = React141.useMemo(
|
|
59695
60160
|
() => dateFnsTz.formatInTimeZone(/* @__PURE__ */ new Date(), timezone || "UTC", "yyyy-MM-dd"),
|
|
@@ -59777,6 +60242,12 @@ var MonthlyRangeFilter = ({
|
|
|
59777
60242
|
}
|
|
59778
60243
|
setActivePreset("Custom");
|
|
59779
60244
|
setPendingChangeMeta({ source: "custom" });
|
|
60245
|
+
if (singleDateOnly) {
|
|
60246
|
+
setRangeStart(day);
|
|
60247
|
+
setRangeEnd(day);
|
|
60248
|
+
setSelecting(false);
|
|
60249
|
+
return;
|
|
60250
|
+
}
|
|
59780
60251
|
if (!selecting || !rangeStart) {
|
|
59781
60252
|
setRangeStart(day);
|
|
59782
60253
|
setRangeEnd(null);
|
|
@@ -59811,6 +60282,13 @@ var MonthlyRangeFilter = ({
|
|
|
59811
60282
|
};
|
|
59812
60283
|
const handleApply = () => {
|
|
59813
60284
|
if (rangeStart) {
|
|
60285
|
+
if (singleDateOnly) {
|
|
60286
|
+
const selected = dateFns.startOfDay(rangeStart) > dateFns.startOfDay(today) ? dateFns.startOfDay(today) : dateFns.startOfDay(rangeStart);
|
|
60287
|
+
const dateKey = dateFns.format(selected, "yyyy-MM-dd");
|
|
60288
|
+
onChange({ startKey: dateKey, endKey: dateKey }, pendingChangeMeta || { source: "custom" });
|
|
60289
|
+
setIsOpen(false);
|
|
60290
|
+
return;
|
|
60291
|
+
}
|
|
59814
60292
|
const boundedStart = dateFns.startOfDay(rangeStart) > dateFns.startOfDay(today) ? dateFns.startOfDay(today) : dateFns.startOfDay(rangeStart);
|
|
59815
60293
|
const candidateEnd = rangeEnd || rangeStart;
|
|
59816
60294
|
const boundedEnd = dateFns.startOfDay(candidateEnd) > dateFns.startOfDay(today) ? dateFns.startOfDay(today) : dateFns.startOfDay(candidateEnd);
|
|
@@ -59905,7 +60383,7 @@ var MonthlyRangeFilter = ({
|
|
|
59905
60383
|
"overflow-hidden bg-white animate-in fade-in zoom-in-95 duration-200 flex",
|
|
59906
60384
|
isInline ? "relative mt-2 w-full rounded-xl border border-gray-200" : "absolute right-0 z-50 mt-2 w-[520px] rounded-xl border border-gray-100 shadow-2xl"
|
|
59907
60385
|
), children: [
|
|
59908
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-40 bg-
|
|
60386
|
+
!singleDateOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-40 bg-gray-50 border-r border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
59909
60387
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
59910
60388
|
presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59911
60389
|
"button",
|
|
@@ -59914,7 +60392,7 @@ var MonthlyRangeFilter = ({
|
|
|
59914
60392
|
onClick: () => handlePresetClick(preset),
|
|
59915
60393
|
className: clsx(
|
|
59916
60394
|
"w-full text-left px-3 py-2 text-sm rounded-lg transition-all duration-200",
|
|
59917
|
-
activePreset === preset.label ? "bg-
|
|
60395
|
+
activePreset === preset.label ? "bg-blue-50 text-blue-600 font-semibold" : "text-gray-600 hover:bg-gray-100/80"
|
|
59918
60396
|
),
|
|
59919
60397
|
children: preset.label
|
|
59920
60398
|
},
|
|
@@ -59927,7 +60405,7 @@ var MonthlyRangeFilter = ({
|
|
|
59927
60405
|
onClick: () => setActivePreset("Custom"),
|
|
59928
60406
|
className: clsx(
|
|
59929
60407
|
"w-full text-left px-3 py-2 text-sm rounded-lg transition-all duration-200",
|
|
59930
|
-
activePreset === "Custom" ? "bg-
|
|
60408
|
+
activePreset === "Custom" ? "bg-blue-50 text-blue-600 font-semibold" : "text-gray-600 hover:bg-gray-100/80"
|
|
59931
60409
|
),
|
|
59932
60410
|
children: "Custom"
|
|
59933
60411
|
}
|
|
@@ -59949,7 +60427,7 @@ var MonthlyRangeFilter = ({
|
|
|
59949
60427
|
type: "button",
|
|
59950
60428
|
onClick: handleApply,
|
|
59951
60429
|
disabled: !rangeStart,
|
|
59952
|
-
className: "w-full py-2.5 bg-
|
|
60430
|
+
className: "w-full py-2.5 bg-blue-600 text-white text-sm font-semibold rounded-lg hover:bg-blue-700 transition-all disabled:opacity-50 disabled:cursor-not-allowed",
|
|
59953
60431
|
children: "Apply"
|
|
59954
60432
|
}
|
|
59955
60433
|
)
|
|
@@ -59999,9 +60477,9 @@ var MonthlyRangeFilter = ({
|
|
|
59999
60477
|
const dayNum = day.getDate();
|
|
60000
60478
|
const isFutureDay = dateFns.startOfDay(day) > dateFns.startOfDay(today);
|
|
60001
60479
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
60002
|
-
inRange && !isStart && !isEnd && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 -inset-x-0.5 bg-
|
|
60003
|
-
inRange && isStart && !isSingleDaySelection && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 left-1/2 bg-
|
|
60004
|
-
inRange && isEnd && !isSingleDaySelection && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 right-1/2 bg-
|
|
60480
|
+
inRange && !isStart && !isEnd && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 -inset-x-0.5 bg-blue-50 z-0" }),
|
|
60481
|
+
inRange && isStart && !isSingleDaySelection && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 left-1/2 bg-blue-50 z-0" }),
|
|
60482
|
+
inRange && isEnd && !isSingleDaySelection && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 left-0 right-1/2 bg-blue-50 z-0" }),
|
|
60005
60483
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60006
60484
|
"button",
|
|
60007
60485
|
{
|
|
@@ -60010,19 +60488,47 @@ var MonthlyRangeFilter = ({
|
|
|
60010
60488
|
disabled: isFutureDay,
|
|
60011
60489
|
className: clsx(
|
|
60012
60490
|
"h-10 w-full flex items-center justify-center text-sm font-semibold transition-all duration-150 relative z-10",
|
|
60013
|
-
|
|
60491
|
+
// Future day NOT in range
|
|
60492
|
+
isFutureDay && !inRange && "text-gray-300 cursor-not-allowed",
|
|
60014
60493
|
// Not in range
|
|
60015
|
-
!isFutureDay && !inRange && "text-gray-700 hover:bg-gray-
|
|
60494
|
+
!isFutureDay && !inRange && "text-gray-700 hover:bg-gray-100 rounded-lg",
|
|
60016
60495
|
// Middle of range
|
|
60017
|
-
inRange && !isStart && !isEnd &&
|
|
60496
|
+
inRange && !isStart && !isEnd && clsx(
|
|
60497
|
+
"text-blue-600",
|
|
60498
|
+
isFutureDay && "cursor-not-allowed opacity-60"
|
|
60499
|
+
),
|
|
60018
60500
|
// Start/End of range or Single selection
|
|
60019
|
-
(isStart || isEnd) &&
|
|
60501
|
+
(isStart || isEnd) && clsx(
|
|
60502
|
+
"bg-blue-600 text-white rounded-lg shadow-sm",
|
|
60503
|
+
isFutureDay && "cursor-not-allowed opacity-80"
|
|
60504
|
+
)
|
|
60020
60505
|
),
|
|
60021
60506
|
children: dayNum
|
|
60022
60507
|
}
|
|
60023
60508
|
)
|
|
60024
60509
|
] }, day.toISOString());
|
|
60025
|
-
}) })
|
|
60510
|
+
}) }),
|
|
60511
|
+
singleDateOnly && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 flex items-center justify-end gap-2 border-t border-gray-100 pt-3", children: [
|
|
60512
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60513
|
+
"button",
|
|
60514
|
+
{
|
|
60515
|
+
type: "button",
|
|
60516
|
+
onClick: handleReset,
|
|
60517
|
+
className: "px-3 py-1.5 text-sm font-medium text-gray-500 hover:text-gray-700 transition-colors",
|
|
60518
|
+
children: "Reset"
|
|
60519
|
+
}
|
|
60520
|
+
),
|
|
60521
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60522
|
+
"button",
|
|
60523
|
+
{
|
|
60524
|
+
type: "button",
|
|
60525
|
+
onClick: handleApply,
|
|
60526
|
+
disabled: !rangeStart,
|
|
60527
|
+
className: "px-4 py-1.5 bg-blue-600 text-white text-sm font-semibold rounded-lg hover:bg-blue-700 transition-all disabled:opacity-50 disabled:cursor-not-allowed",
|
|
60528
|
+
children: "Apply"
|
|
60529
|
+
}
|
|
60530
|
+
)
|
|
60531
|
+
] })
|
|
60026
60532
|
] })
|
|
60027
60533
|
] })
|
|
60028
60534
|
] });
|
|
@@ -61799,7 +62305,36 @@ var getMonthDateInfo = (timezone) => {
|
|
|
61799
62305
|
const monthEndDate = dateFnsTz.fromZonedTime(`${monthEndKey}T23:59:59`, timezone);
|
|
61800
62306
|
return { startDate, endDate, monthEndDate };
|
|
61801
62307
|
};
|
|
61802
|
-
var
|
|
62308
|
+
var createKpisOverviewUrl = ({
|
|
62309
|
+
tab,
|
|
62310
|
+
date,
|
|
62311
|
+
shift
|
|
62312
|
+
}) => {
|
|
62313
|
+
const params = new URLSearchParams();
|
|
62314
|
+
if (tab) {
|
|
62315
|
+
params.set("tab", tab);
|
|
62316
|
+
}
|
|
62317
|
+
if (date) {
|
|
62318
|
+
params.set("date", date);
|
|
62319
|
+
}
|
|
62320
|
+
if (typeof shift === "number" && Number.isFinite(shift)) {
|
|
62321
|
+
params.set("shift", shift.toString());
|
|
62322
|
+
}
|
|
62323
|
+
const queryString = params.toString();
|
|
62324
|
+
return queryString ? `/kpis?${queryString}` : "/kpis";
|
|
62325
|
+
};
|
|
62326
|
+
var getZonedDateAtMidday = (dateKey, timezone) => dateFnsTz.fromZonedTime(`${dateKey}T12:00:00`, timezone);
|
|
62327
|
+
var formatDateKey = (dateKey, timezone, options) => {
|
|
62328
|
+
try {
|
|
62329
|
+
return new Intl.DateTimeFormat("en-US", {
|
|
62330
|
+
...options,
|
|
62331
|
+
timeZone: timezone
|
|
62332
|
+
}).format(getZonedDateAtMidday(dateKey, timezone));
|
|
62333
|
+
} catch {
|
|
62334
|
+
return dateKey;
|
|
62335
|
+
}
|
|
62336
|
+
};
|
|
62337
|
+
var LeaderboardCountdown = ({ targetDate, format: format9, finishedLabel = "Finished", placeholder = "--", onFinished }) => {
|
|
61803
62338
|
const [time2, setTime] = React141.useState("");
|
|
61804
62339
|
const hasFinishedRef = React141.useRef(false);
|
|
61805
62340
|
React141.useEffect(() => {
|
|
@@ -61821,7 +62356,7 @@ var LeaderboardCountdown = ({ targetDate, format: format8, finishedLabel = "Fini
|
|
|
61821
62356
|
}
|
|
61822
62357
|
return;
|
|
61823
62358
|
}
|
|
61824
|
-
if (
|
|
62359
|
+
if (format9 === "days") {
|
|
61825
62360
|
const days = Math.floor(diff / (1e3 * 60 * 60 * 24));
|
|
61826
62361
|
const hours = Math.floor(diff % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60));
|
|
61827
62362
|
setTime(`${days} days ${hours} hours`);
|
|
@@ -61836,7 +62371,7 @@ var LeaderboardCountdown = ({ targetDate, format: format8, finishedLabel = "Fini
|
|
|
61836
62371
|
tick();
|
|
61837
62372
|
const interval = setInterval(tick, 1e3);
|
|
61838
62373
|
return () => clearInterval(interval);
|
|
61839
|
-
}, [targetDate,
|
|
62374
|
+
}, [targetDate, format9, finishedLabel, placeholder, onFinished]);
|
|
61840
62375
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: time2 });
|
|
61841
62376
|
};
|
|
61842
62377
|
var LinesLeaderboard = ({
|
|
@@ -61854,7 +62389,9 @@ var LinesLeaderboard = ({
|
|
|
61854
62389
|
shiftEndDate,
|
|
61855
62390
|
monthEndDate,
|
|
61856
62391
|
viewType,
|
|
61857
|
-
setViewType
|
|
62392
|
+
setViewType,
|
|
62393
|
+
timezone: _timezone,
|
|
62394
|
+
isHistoricalDaily
|
|
61858
62395
|
}) => {
|
|
61859
62396
|
const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
|
|
61860
62397
|
const assignedLineIdSet = React141__namespace.default.useMemo(
|
|
@@ -61947,10 +62484,10 @@ var LinesLeaderboard = ({
|
|
|
61947
62484
|
}
|
|
61948
62485
|
}, [timeRange, leaderboardData, isLoadingToday, isLoadingMonthly]);
|
|
61949
62486
|
const topThree = leaderboardData.slice(0, 3);
|
|
61950
|
-
leaderboardData.slice(3);
|
|
61951
62487
|
const countdownTarget = timeRange === "monthly" ? monthEndDate : shiftEndDate;
|
|
61952
62488
|
const countdownFormat = timeRange === "monthly" ? "days" : "clock";
|
|
61953
62489
|
const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
|
|
62490
|
+
const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
|
|
61954
62491
|
const handleCountdownFinished = React141__namespace.default.useCallback(() => {
|
|
61955
62492
|
trackCoreEvent("Leaderboard Countdown Finished", {
|
|
61956
62493
|
countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
|
|
@@ -62024,7 +62561,7 @@ var LinesLeaderboard = ({
|
|
|
62024
62561
|
}
|
|
62025
62562
|
)
|
|
62026
62563
|
] }),
|
|
62027
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:absolute md:right-0 md:top-1/2 md:-translate-y-1/2 flex items-center gap-
|
|
62564
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:absolute md:right-0 md:top-1/2 md:-translate-y-1/2 flex flex-wrap items-center justify-center md:justify-end gap-2", children: showCountdown && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2.5 px-4 py-2 bg-white rounded-full shadow-sm border border-gray-100", children: [
|
|
62028
62565
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-4 h-4 text-orange-500" }),
|
|
62029
62566
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
62030
62567
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider", children: "Ends in" }),
|
|
@@ -62145,7 +62682,7 @@ var LinesLeaderboard = ({
|
|
|
62145
62682
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-900", children: item.supervisorName })
|
|
62146
62683
|
] }) }),
|
|
62147
62684
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 whitespace-nowrap text-sm text-gray-500", children: item.line.line_name }),
|
|
62148
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 whitespace-nowrap text-right", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-end", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-
|
|
62685
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 whitespace-nowrap text-right", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col items-end", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-gray-900", children: formatEfficiency(item.efficiency) }) }) })
|
|
62149
62686
|
]
|
|
62150
62687
|
},
|
|
62151
62688
|
item.id
|
|
@@ -62319,6 +62856,9 @@ var KPIsOverviewView = ({
|
|
|
62319
62856
|
const [activeTab, setActiveTab] = React141.useState("today");
|
|
62320
62857
|
const [timeRange, setTimeRange] = React141.useState("today");
|
|
62321
62858
|
const [viewType, setViewType] = React141.useState("operator");
|
|
62859
|
+
const [selectedLeaderboardDate, setSelectedLeaderboardDate] = React141.useState("");
|
|
62860
|
+
const [selectedLeaderboardShiftId, setSelectedLeaderboardShiftId] = React141.useState(0);
|
|
62861
|
+
const [hasHydratedLeaderboardRouteState, setHasHydratedLeaderboardRouteState] = React141.useState(false);
|
|
62322
62862
|
const [loading, setLoading] = React141.useState(true);
|
|
62323
62863
|
const [error, setError] = React141.useState(null);
|
|
62324
62864
|
const [topPerformer, setTopPerformer] = React141.useState({
|
|
@@ -62340,13 +62880,6 @@ var KPIsOverviewView = ({
|
|
|
62340
62880
|
const [monthlyError, setMonthlyError] = React141.useState(null);
|
|
62341
62881
|
const dailyRequestKeyRef = React141.useRef(null);
|
|
62342
62882
|
const monthlyRequestKeyRef = React141.useRef(null);
|
|
62343
|
-
React141.useEffect(() => {
|
|
62344
|
-
if (!router$1.isReady) return;
|
|
62345
|
-
const tab = router$1.query.tab;
|
|
62346
|
-
if (tab === "leaderboard") {
|
|
62347
|
-
setActiveTab("leaderboard");
|
|
62348
|
-
}
|
|
62349
|
-
}, [router$1.isReady, router$1.query.tab]);
|
|
62350
62883
|
const supabase = useSupabase();
|
|
62351
62884
|
const { user } = useAuth();
|
|
62352
62885
|
const dashboardConfig = useDashboardConfig();
|
|
@@ -62432,7 +62965,77 @@ var KPIsOverviewView = ({
|
|
|
62432
62965
|
() => getShiftEndDate(currentShiftDetails, configuredTimezone),
|
|
62433
62966
|
[currentShiftDetails, configuredTimezone]
|
|
62434
62967
|
);
|
|
62435
|
-
|
|
62968
|
+
React141__namespace.default.useMemo(() => {
|
|
62969
|
+
if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
|
|
62970
|
+
return shiftConfig.shifts.map((shift) => ({
|
|
62971
|
+
id: shift.shiftId,
|
|
62972
|
+
label: shift.shiftName || `Shift ${shift.shiftId}`,
|
|
62973
|
+
startTime: shift.startTime,
|
|
62974
|
+
endTime: shift.endTime
|
|
62975
|
+
}));
|
|
62976
|
+
}
|
|
62977
|
+
return [
|
|
62978
|
+
{ id: 0, label: "Day Shift", startTime: "06:00", endTime: "18:00" },
|
|
62979
|
+
{ id: 1, label: "Night Shift", startTime: "18:00", endTime: "06:00" }
|
|
62980
|
+
];
|
|
62981
|
+
}, [shiftConfig]);
|
|
62982
|
+
const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
|
|
62983
|
+
const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
|
|
62984
|
+
const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
|
|
62985
|
+
React141.useEffect(() => {
|
|
62986
|
+
if (!router$1.isReady) return;
|
|
62987
|
+
const tabQuery = router$1.query.tab;
|
|
62988
|
+
const dateQuery = router$1.query.date;
|
|
62989
|
+
const shiftQuery = router$1.query.shift;
|
|
62990
|
+
const parsedShiftQuery = typeof shiftQuery === "string" ? Number.parseInt(shiftQuery, 10) : Number.NaN;
|
|
62991
|
+
const hasHistoricalQuery = tabQuery === "leaderboard" && typeof dateQuery === "string" && Number.isFinite(parsedShiftQuery);
|
|
62992
|
+
setActiveTab(tabQuery === "leaderboard" ? "leaderboard" : "today");
|
|
62993
|
+
if (hasHistoricalQuery) {
|
|
62994
|
+
setSelectedLeaderboardDate(dateQuery);
|
|
62995
|
+
setSelectedLeaderboardShiftId(parsedShiftQuery);
|
|
62996
|
+
setTimeRange("today");
|
|
62997
|
+
} else {
|
|
62998
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
62999
|
+
setSelectedLeaderboardShiftId(currentShiftId);
|
|
63000
|
+
}
|
|
63001
|
+
setHasHydratedLeaderboardRouteState(true);
|
|
63002
|
+
}, [
|
|
63003
|
+
router$1.isReady,
|
|
63004
|
+
router$1.query.tab,
|
|
63005
|
+
router$1.query.date,
|
|
63006
|
+
router$1.query.shift,
|
|
63007
|
+
currentShiftDate,
|
|
63008
|
+
currentShiftId
|
|
63009
|
+
]);
|
|
63010
|
+
React141.useEffect(() => {
|
|
63011
|
+
if (!router$1.isReady || !hasHydratedLeaderboardRouteState) return;
|
|
63012
|
+
const expectedTab = activeTab === "leaderboard" ? "leaderboard" : void 0;
|
|
63013
|
+
const expectedDate = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily ? effectiveLeaderboardDate : void 0;
|
|
63014
|
+
const expectedShift = expectedDate !== void 0 ? effectiveLeaderboardShiftId.toString() : void 0;
|
|
63015
|
+
const currentTab = typeof router$1.query.tab === "string" ? router$1.query.tab : void 0;
|
|
63016
|
+
const currentDateQuery = typeof router$1.query.date === "string" ? router$1.query.date : void 0;
|
|
63017
|
+
const currentShiftQuery = typeof router$1.query.shift === "string" ? router$1.query.shift : void 0;
|
|
63018
|
+
if (currentTab === expectedTab && currentDateQuery === expectedDate && currentShiftQuery === expectedShift) {
|
|
63019
|
+
return;
|
|
63020
|
+
}
|
|
63021
|
+
void router$1.replace(
|
|
63022
|
+
createKpisOverviewUrl({
|
|
63023
|
+
tab: expectedTab === "leaderboard" ? "leaderboard" : void 0,
|
|
63024
|
+
date: expectedDate,
|
|
63025
|
+
shift: expectedShift !== void 0 ? Number.parseInt(expectedShift, 10) : void 0
|
|
63026
|
+
}),
|
|
63027
|
+
void 0,
|
|
63028
|
+
{ shallow: true }
|
|
63029
|
+
);
|
|
63030
|
+
}, [
|
|
63031
|
+
router$1,
|
|
63032
|
+
activeTab,
|
|
63033
|
+
timeRange,
|
|
63034
|
+
effectiveLeaderboardDate,
|
|
63035
|
+
effectiveLeaderboardShiftId,
|
|
63036
|
+
hasHydratedLeaderboardRouteState,
|
|
63037
|
+
isHistoricalLeaderboardDaily
|
|
63038
|
+
]);
|
|
62436
63039
|
const factoryViewId = entityConfig.factoryViewId || "factory";
|
|
62437
63040
|
const {
|
|
62438
63041
|
lineMetrics,
|
|
@@ -62607,10 +63210,10 @@ var KPIsOverviewView = ({
|
|
|
62607
63210
|
}, [supabase, resolvedCompanyId, leaderboardLinesForView, monthStartDate, monthEndDateKey, viewType]);
|
|
62608
63211
|
const fetchDailyLeaderboard = React141.useCallback(async () => {
|
|
62609
63212
|
if (!supabase || !resolvedCompanyId || leaderboardLinesForView.length === 0) return;
|
|
62610
|
-
if (!
|
|
63213
|
+
if (!effectiveLeaderboardDate) return;
|
|
62611
63214
|
const targetLineIds = leaderboardLinesForView.map((line) => line.id);
|
|
62612
63215
|
const lineIdsKey = targetLineIds.slice().sort().join(",");
|
|
62613
|
-
const requestKey = `${resolvedCompanyId}|${
|
|
63216
|
+
const requestKey = `${resolvedCompanyId}|${effectiveLeaderboardDate}|${effectiveLeaderboardShiftId}|${lineIdsKey}`;
|
|
62614
63217
|
if (dailyRequestKeyRef.current === requestKey) return;
|
|
62615
63218
|
dailyRequestKeyRef.current = requestKey;
|
|
62616
63219
|
setDailyLoading(true);
|
|
@@ -62618,8 +63221,8 @@ var KPIsOverviewView = ({
|
|
|
62618
63221
|
try {
|
|
62619
63222
|
const entries = await lineLeaderboardService.getDailyLineLeaderboard(supabase, {
|
|
62620
63223
|
companyId: resolvedCompanyId,
|
|
62621
|
-
date:
|
|
62622
|
-
shiftId:
|
|
63224
|
+
date: effectiveLeaderboardDate,
|
|
63225
|
+
shiftId: effectiveLeaderboardShiftId,
|
|
62623
63226
|
lineIds: targetLineIds,
|
|
62624
63227
|
lineMode: viewType === "machine" ? "uptime" : "output"
|
|
62625
63228
|
});
|
|
@@ -62637,7 +63240,14 @@ var KPIsOverviewView = ({
|
|
|
62637
63240
|
} finally {
|
|
62638
63241
|
setDailyLoading(false);
|
|
62639
63242
|
}
|
|
62640
|
-
}, [
|
|
63243
|
+
}, [
|
|
63244
|
+
supabase,
|
|
63245
|
+
resolvedCompanyId,
|
|
63246
|
+
leaderboardLinesForView,
|
|
63247
|
+
effectiveLeaderboardDate,
|
|
63248
|
+
effectiveLeaderboardShiftId,
|
|
63249
|
+
viewType
|
|
63250
|
+
]);
|
|
62641
63251
|
React141.useEffect(() => {
|
|
62642
63252
|
if (activeTab !== "leaderboard") return;
|
|
62643
63253
|
fetchMonthlyLeaderboard();
|
|
@@ -62726,6 +63336,12 @@ var KPIsOverviewView = ({
|
|
|
62726
63336
|
trackProps.status = isEfficiencyOnTrack(kpis.efficiency?.value) ? "On Track" : "Behind";
|
|
62727
63337
|
}
|
|
62728
63338
|
trackCoreEvent("Line Card Clicked", trackProps);
|
|
63339
|
+
if (activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily) {
|
|
63340
|
+
navigation.navigate(
|
|
63341
|
+
`/kpis/${line.id}?date=${encodeURIComponent(effectiveLeaderboardDate)}&shift=${effectiveLeaderboardShiftId}`
|
|
63342
|
+
);
|
|
63343
|
+
return;
|
|
63344
|
+
}
|
|
62729
63345
|
navigation.navigate(`/kpis/${line.id}`);
|
|
62730
63346
|
};
|
|
62731
63347
|
const handleBackClick = React141.useCallback(() => {
|
|
@@ -62751,21 +63367,24 @@ var KPIsOverviewView = ({
|
|
|
62751
63367
|
});
|
|
62752
63368
|
setActiveTab(newTab);
|
|
62753
63369
|
}, [activeTab, leaderboardLines.length, lines.length]);
|
|
62754
|
-
const formatLocalDate2 = (
|
|
62755
|
-
|
|
63370
|
+
const formatLocalDate2 = React141.useCallback((dateKey) => {
|
|
63371
|
+
return formatDateKey(dateKey, configuredTimezone, {
|
|
62756
63372
|
year: "numeric",
|
|
62757
63373
|
month: "long",
|
|
62758
63374
|
day: "numeric"
|
|
62759
|
-
};
|
|
62760
|
-
|
|
62761
|
-
};
|
|
63375
|
+
});
|
|
63376
|
+
}, [configuredTimezone]);
|
|
62762
63377
|
const getMonthRange = () => {
|
|
62763
|
-
const
|
|
62764
|
-
const
|
|
62765
|
-
const
|
|
62766
|
-
|
|
62767
|
-
|
|
62768
|
-
|
|
63378
|
+
const zonedNow = dateFnsTz.toZonedTime(/* @__PURE__ */ new Date(), configuredTimezone);
|
|
63379
|
+
const startOfMonthKey = buildDateKey(zonedNow.getFullYear(), zonedNow.getMonth(), 1);
|
|
63380
|
+
const endOfMonthKey = buildDateKey(
|
|
63381
|
+
zonedNow.getFullYear(),
|
|
63382
|
+
zonedNow.getMonth(),
|
|
63383
|
+
new Date(zonedNow.getFullYear(), zonedNow.getMonth() + 1, 0).getDate()
|
|
63384
|
+
);
|
|
63385
|
+
const startLabel = formatDateKey(startOfMonthKey, configuredTimezone, { month: "short", day: "numeric" });
|
|
63386
|
+
const endLabel = formatDateKey(endOfMonthKey, configuredTimezone, { month: "short", day: "numeric" });
|
|
63387
|
+
return `${startLabel} - ${endLabel}, ${zonedNow.getFullYear()}`;
|
|
62769
63388
|
};
|
|
62770
63389
|
const isMonthlyMode = activeTab === "leaderboard" && timeRange === "monthly";
|
|
62771
63390
|
const isLeaderboardLoading = timeRange === "today" ? dailyLoading : monthlyLoading;
|
|
@@ -62774,8 +63393,13 @@ var KPIsOverviewView = ({
|
|
|
62774
63393
|
const showTopPerformerImage = Boolean(topPerformer.imageUrl) && !topPerformerImageError;
|
|
62775
63394
|
typeof topPerformer.efficiency === "number" && Number.isFinite(topPerformer.efficiency);
|
|
62776
63395
|
topPerformerLoading ? "--" : typeof topPerformer.efficiency === "number" && Number.isFinite(topPerformer.efficiency) ? `${topPerformer.efficiency.toFixed(1)}%` : "--";
|
|
63396
|
+
const showHistoricalLeaderboardHeader = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily;
|
|
63397
|
+
const headerDateKey = activeTab === "leaderboard" && timeRange === "today" ? effectiveLeaderboardDate : monthEndDateKey;
|
|
63398
|
+
const headerShiftId = showHistoricalLeaderboardHeader ? effectiveLeaderboardShiftId : currentShiftDetails.shiftId;
|
|
63399
|
+
const headerShiftName = getShiftNameById(headerShiftId, configuredTimezone, shiftConfig).replace(/ Shift$/i, "");
|
|
63400
|
+
const headerDateLabel = isMonthlyMode ? getMonthRange() : formatLocalDate2(headerDateKey);
|
|
62777
63401
|
const getShiftIcon = (shiftId) => {
|
|
62778
|
-
const shiftNameLower =
|
|
63402
|
+
const shiftNameLower = getShiftNameById(shiftId, configuredTimezone, shiftConfig).toLowerCase();
|
|
62779
63403
|
if (shiftNameLower.includes("day") || shiftNameLower.includes("morning") || shiftId === 0) {
|
|
62780
63404
|
return /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "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" }) });
|
|
62781
63405
|
}
|
|
@@ -62878,18 +63502,26 @@ var KPIsOverviewView = ({
|
|
|
62878
63502
|
),
|
|
62879
63503
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
62880
63504
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold text-gray-900", children: activeTab === "leaderboard" ? "Leaderboard" : "Overview" }),
|
|
62881
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63505
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63506
|
+
"div",
|
|
63507
|
+
{
|
|
63508
|
+
className: `h-2 w-2 rounded-full ring-2 ${showHistoricalLeaderboardHeader ? "bg-amber-500 ring-amber-500/20" : "bg-emerald-500 animate-pulse ring-emerald-500/20"}`
|
|
63509
|
+
}
|
|
63510
|
+
)
|
|
62882
63511
|
] }) }),
|
|
62883
63512
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12" })
|
|
62884
63513
|
] }),
|
|
62885
63514
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-2", children: [
|
|
62886
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `inline-flex items-center bg-gray-100 rounded-full ${isMonthlyMode ? "px-4 py-1.5 ring-1 ring-gray-200 shadow-sm" : "px-2.5 py-1"}`, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-medium text-gray-700 ${isMonthlyMode ? "text-sm" : "text-xs"}`, children:
|
|
63515
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `inline-flex items-center bg-gray-100 rounded-full ${isMonthlyMode ? "px-4 py-1.5 ring-1 ring-gray-200 shadow-sm" : "px-2.5 py-1"}`, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-medium text-gray-700 ${isMonthlyMode ? "text-sm" : "text-xs"}`, children: headerDateLabel }) }),
|
|
62887
63516
|
!isMonthlyMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
62888
63517
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
|
|
62889
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(
|
|
62890
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children:
|
|
63518
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(headerShiftId) }),
|
|
63519
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-700", children: headerShiftName })
|
|
62891
63520
|
] }),
|
|
62892
|
-
/* @__PURE__ */ jsxRuntime.
|
|
63521
|
+
showHistoricalLeaderboardHeader ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-amber-50 text-amber-700 rounded-full", children: [
|
|
63522
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-3 h-3" }),
|
|
63523
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium", children: "Historical" })
|
|
63524
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex items-center px-2.5 py-1 bg-green-100 rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-green-700", children: /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {}) }) })
|
|
62893
63525
|
] })
|
|
62894
63526
|
] }),
|
|
62895
63527
|
activeTab !== "leaderboard" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 bg-white shadow-md hover:shadow-lg transition-all duration-300 ease-out hover:scale-[1.01] relative rounded-2xl border border-amber-100 pl-2 pr-4 py-1.5 flex items-center justify-between group", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 min-w-0", children: [
|
|
@@ -62990,7 +63622,12 @@ var KPIsOverviewView = ({
|
|
|
62990
63622
|
) }),
|
|
62991
63623
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
62992
63624
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl md:text-3xl lg:text-4xl font-semibold text-gray-900 tracking-tight", children: activeTab === "leaderboard" ? "Leaderboard" : "Overview" }),
|
|
62993
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63625
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63626
|
+
"div",
|
|
63627
|
+
{
|
|
63628
|
+
className: `h-2.5 w-2.5 rounded-full ring-4 flex-shrink-0 ${showHistoricalLeaderboardHeader ? "bg-amber-500 ring-amber-500/10" : "bg-emerald-500 animate-pulse ring-emerald-500/10"}`
|
|
63629
|
+
}
|
|
63630
|
+
)
|
|
62994
63631
|
] }),
|
|
62995
63632
|
!topPerformerLoading && activeTab !== "leaderboard" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 z-10", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-2xl border border-amber-200 shadow-md pl-1.5 pr-4 py-1.5 flex items-center gap-4 transition-all hover:shadow-lg hover:border-amber-300 group", children: [
|
|
62996
63633
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
@@ -63060,7 +63697,7 @@ var KPIsOverviewView = ({
|
|
|
63060
63697
|
] }) })
|
|
63061
63698
|
] }),
|
|
63062
63699
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-blue-50/50 px-4 py-2 rounded-xl border border-blue-100/50 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center gap-6", children: [
|
|
63063
|
-
!isMonthlyMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63700
|
+
!isMonthlyMode && !showHistoricalLeaderboardHeader && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63064
63701
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-blue-700", children: [
|
|
63065
63702
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4 opacity-70", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) }),
|
|
63066
63703
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-semibold tabular-nums", children: /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {}) })
|
|
@@ -63069,16 +63706,23 @@ var KPIsOverviewView = ({
|
|
|
63069
63706
|
] }),
|
|
63070
63707
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-blue-600", children: [
|
|
63071
63708
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: `w-4 h-4 opacity-70 ${isMonthlyMode ? "scale-110" : ""}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" }) }),
|
|
63072
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${isMonthlyMode ? "text-base font-medium" : "text-sm font-medium"}`, children:
|
|
63709
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `${isMonthlyMode ? "text-base font-medium" : "text-sm font-medium"}`, children: headerDateLabel })
|
|
63073
63710
|
] }),
|
|
63074
63711
|
!isMonthlyMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63075
63712
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-200" }),
|
|
63076
63713
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-blue-600", children: [
|
|
63077
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-70", children: getShiftIcon(
|
|
63714
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-70", children: getShiftIcon(headerShiftId) }),
|
|
63078
63715
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold uppercase tracking-wider", children: [
|
|
63079
|
-
|
|
63716
|
+
headerShiftName,
|
|
63080
63717
|
" Shift"
|
|
63081
63718
|
] })
|
|
63719
|
+
] }),
|
|
63720
|
+
showHistoricalLeaderboardHeader && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63721
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-200" }),
|
|
63722
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 px-2.5 py-1 bg-amber-50 text-amber-700 rounded-full border border-amber-200", children: [
|
|
63723
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-3.5 h-3.5" }),
|
|
63724
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold uppercase tracking-wider", children: "Historical" })
|
|
63725
|
+
] })
|
|
63082
63726
|
] })
|
|
63083
63727
|
] })
|
|
63084
63728
|
] }) }),
|
|
@@ -63101,19 +63745,52 @@ var KPIsOverviewView = ({
|
|
|
63101
63745
|
}
|
|
63102
63746
|
)
|
|
63103
63747
|
] }),
|
|
63104
|
-
|
|
63105
|
-
"
|
|
63106
|
-
|
|
63107
|
-
|
|
63108
|
-
|
|
63109
|
-
|
|
63110
|
-
|
|
63111
|
-
|
|
63112
|
-
|
|
63113
|
-
|
|
63114
|
-
|
|
63115
|
-
|
|
63116
|
-
|
|
63748
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
63749
|
+
activeTab === "leaderboard" && timeRange === "today" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
63750
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
63751
|
+
MonthlyRangeFilter_default,
|
|
63752
|
+
{
|
|
63753
|
+
month: parseDateKeyToDate(effectiveLeaderboardDate).getMonth(),
|
|
63754
|
+
year: parseDateKeyToDate(effectiveLeaderboardDate).getFullYear(),
|
|
63755
|
+
timezone: configuredTimezone,
|
|
63756
|
+
value: {
|
|
63757
|
+
startKey: effectiveLeaderboardDate,
|
|
63758
|
+
endKey: effectiveLeaderboardDate
|
|
63759
|
+
},
|
|
63760
|
+
onChange: (range) => {
|
|
63761
|
+
setSelectedLeaderboardDate(range.startKey);
|
|
63762
|
+
},
|
|
63763
|
+
showLabel: false,
|
|
63764
|
+
singleDateOnly: true
|
|
63765
|
+
}
|
|
63766
|
+
),
|
|
63767
|
+
isHistoricalLeaderboardDaily && /* @__PURE__ */ jsxRuntime.jsx(
|
|
63768
|
+
"button",
|
|
63769
|
+
{
|
|
63770
|
+
type: "button",
|
|
63771
|
+
onClick: () => {
|
|
63772
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
63773
|
+
setSelectedLeaderboardShiftId(currentShiftId);
|
|
63774
|
+
},
|
|
63775
|
+
className: "text-xs font-medium text-blue-600 hover:text-blue-700 whitespace-nowrap",
|
|
63776
|
+
children: "Return to Live"
|
|
63777
|
+
}
|
|
63778
|
+
)
|
|
63779
|
+
] }),
|
|
63780
|
+
(activeTab === "leaderboard" || activeTab === "today") && showViewTypeDropdown && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
63781
|
+
"select",
|
|
63782
|
+
{
|
|
63783
|
+
value: viewType,
|
|
63784
|
+
onChange: (e) => setViewType(e.target.value),
|
|
63785
|
+
className: "appearance-none pl-3 pr-8 py-1.5 text-sm font-medium bg-white border border-gray-200 hover:border-gray-300 rounded-lg text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all cursor-pointer shadow-sm",
|
|
63786
|
+
style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.5rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
|
|
63787
|
+
children: [
|
|
63788
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "operator", children: "Workforce" }),
|
|
63789
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "machine", children: "Machine" })
|
|
63790
|
+
]
|
|
63791
|
+
}
|
|
63792
|
+
) })
|
|
63793
|
+
] })
|
|
63117
63794
|
] })
|
|
63118
63795
|
] })
|
|
63119
63796
|
] }) }),
|
|
@@ -63158,7 +63835,9 @@ var KPIsOverviewView = ({
|
|
|
63158
63835
|
shiftEndDate,
|
|
63159
63836
|
monthEndDate,
|
|
63160
63837
|
viewType,
|
|
63161
|
-
setViewType
|
|
63838
|
+
setViewType,
|
|
63839
|
+
timezone: configuredTimezone,
|
|
63840
|
+
isHistoricalDaily: isHistoricalLeaderboardDaily
|
|
63162
63841
|
}
|
|
63163
63842
|
) })
|
|
63164
63843
|
) })
|
|
@@ -64700,51 +65379,41 @@ var ClipsCostView = () => {
|
|
|
64700
65379
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[120px]" })
|
|
64701
65380
|
] }) })
|
|
64702
65381
|
] }) }),
|
|
64703
|
-
/* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 p-4 sm:p-6 lg:p-8 max-w-
|
|
65382
|
+
/* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex-1 p-4 sm:p-6 lg:p-8 max-w-5xl mx-auto w-full", children: error ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 bg-red-50 border border-red-200 rounded-lg flex items-start gap-3 text-red-700 animate-in fade-in slide-in-from-top-2 max-w-2xl mx-auto", children: [
|
|
64704
65383
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-5 w-5 flex-shrink-0 mt-0.5" }),
|
|
64705
65384
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
64706
65385
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-medium", children: "Error loading usage data" }),
|
|
64707
65386
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mt-1 text-red-600", children: error })
|
|
64708
65387
|
] })
|
|
64709
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
64710
|
-
/* @__PURE__ */ jsxRuntime.jsx(Card2, { className: "overflow-hidden shadow-sm border-gray-200 bg-white", children: /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "p-
|
|
64711
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-
|
|
64712
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-
|
|
64713
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-
|
|
64714
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-
|
|
64715
|
-
|
|
64716
|
-
|
|
64717
|
-
|
|
64718
|
-
|
|
65388
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-8 grid grid-cols-1 lg:grid-cols-3 gap-6 animate-in fade-in slide-in-from-bottom-4 duration-500", children: [
|
|
65389
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lg:col-span-2", children: /* @__PURE__ */ jsxRuntime.jsx(Card2, { className: "overflow-hidden shadow-sm border-gray-200 bg-white h-full flex flex-col justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "p-10 lg:p-14", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center text-center", children: [
|
|
65390
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 bg-blue-50/50 rounded-2xl mb-6 ring-1 ring-blue-100/50", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Film, { className: "h-10 w-10 text-blue-600", strokeWidth: 1.5 }) }),
|
|
65391
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-base font-semibold text-gray-600 uppercase tracking-widest mb-3", children: "Current Month Usage" }),
|
|
65392
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-400 mb-6", children: formatMonthLabel(data?.monthStart) }),
|
|
65393
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-baseline gap-2 mb-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-7xl font-bold text-gray-900 tabular-nums tracking-tighter", children: formatNumber(data?.monthlyClassifications || 0) }) }),
|
|
65394
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 mt-4", children: "Clips analyzed and processed by our AI pipeline" })
|
|
65395
|
+
] }) }) }) }),
|
|
65396
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "lg:col-span-1", children: /* @__PURE__ */ jsxRuntime.jsx(Card2, { className: "overflow-hidden shadow-sm border-gray-200 bg-white h-full", children: /* @__PURE__ */ jsxRuntime.jsxs(CardContent2, { className: "p-6 lg:p-8 flex flex-col h-full", children: [
|
|
65397
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-semibold text-gray-900 mb-6 uppercase tracking-widest", children: "Previous Months" }),
|
|
65398
|
+
(data?.historicalMonthlyClassifications?.length || 0) === 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center text-center py-8", children: [
|
|
65399
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3 bg-gray-50 rounded-full mb-3", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Film, { className: "h-6 w-6 text-gray-400", strokeWidth: 1.5 }) }),
|
|
65400
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No historical month usage yet." })
|
|
65401
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-3 flex-1 overflow-y-auto pr-2", children: data?.historicalMonthlyClassifications.map((item) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
64719
65402
|
"div",
|
|
64720
65403
|
{
|
|
64721
|
-
className: "flex items-center justify-between rounded-
|
|
65404
|
+
className: "group flex items-center justify-between rounded-xl border border-gray-100 bg-gray-50/50 hover:bg-white hover:border-gray-200 hover:shadow-sm px-4 py-3.5 transition-all duration-200",
|
|
64722
65405
|
children: [
|
|
64723
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-
|
|
64724
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-
|
|
65406
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-600 group-hover:text-gray-900 transition-colors", children: formatMonthLabel(item.monthStart) }),
|
|
65407
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-semibold text-gray-900 tabular-nums", children: formatNumber(item.classifications) })
|
|
64725
65408
|
]
|
|
64726
65409
|
},
|
|
64727
65410
|
item.monthStart
|
|
64728
65411
|
)) })
|
|
64729
|
-
] }) })
|
|
65412
|
+
] }) }) })
|
|
64730
65413
|
] }) })
|
|
64731
65414
|
] });
|
|
64732
65415
|
};
|
|
64733
65416
|
var ClipsCostView_default = ClipsCostView;
|
|
64734
|
-
|
|
64735
|
-
// src/lib/constants/actions.ts
|
|
64736
|
-
var ACTION_NAMES = {
|
|
64737
|
-
/** Assembly operations */
|
|
64738
|
-
ASSEMBLY: "Assembly",
|
|
64739
|
-
/** Packaging operations */
|
|
64740
|
-
PACKAGING: "Packaging",
|
|
64741
|
-
/** Inspection operations */
|
|
64742
|
-
INSPECTION: "Inspection",
|
|
64743
|
-
/** Testing operations */
|
|
64744
|
-
TESTING: "Testing",
|
|
64745
|
-
/** Quality control operations */
|
|
64746
|
-
QUALITY_CONTROL: "Quality Control"
|
|
64747
|
-
};
|
|
64748
65417
|
var calculateShiftHours = (startTime, endTime, breaks = []) => {
|
|
64749
65418
|
if (!startTime || !endTime) return 8;
|
|
64750
65419
|
const [startHour, startMinute] = startTime.split(":").map(Number);
|
|
@@ -65326,9 +65995,9 @@ var ShiftsView = ({
|
|
|
65326
65995
|
const actionIds = Array.from(
|
|
65327
65996
|
new Set(currentThresholds.map((threshold) => threshold.action_id).filter(Boolean))
|
|
65328
65997
|
);
|
|
65329
|
-
const
|
|
65998
|
+
const actionMetadataById = /* @__PURE__ */ new Map();
|
|
65330
65999
|
if (actionIds.length > 0) {
|
|
65331
|
-
const { data: actionRows, error: actionsError } = await supabase.from("actions").select("id, action_name").in("id", actionIds);
|
|
66000
|
+
const { data: actionRows, error: actionsError } = await supabase.from("actions").select("id, action_name, action_family").in("id", actionIds);
|
|
65332
66001
|
if (actionsError) {
|
|
65333
66002
|
console.warn(
|
|
65334
66003
|
`[ShiftsView] Failed to resolve action names for line ${lineId}, shift ${shift.shiftId}: ${actionsError.message}`
|
|
@@ -65336,7 +66005,13 @@ var ShiftsView = ({
|
|
|
65336
66005
|
} else {
|
|
65337
66006
|
(actionRows || []).forEach((actionRow) => {
|
|
65338
66007
|
if (actionRow.id && actionRow.action_name) {
|
|
65339
|
-
|
|
66008
|
+
actionMetadataById.set(actionRow.id, {
|
|
66009
|
+
action_name: actionRow.action_name,
|
|
66010
|
+
action_family: normalizeActionFamily({
|
|
66011
|
+
actionFamily: actionRow.action_family,
|
|
66012
|
+
actionName: actionRow.action_name
|
|
66013
|
+
})
|
|
66014
|
+
});
|
|
65340
66015
|
}
|
|
65341
66016
|
});
|
|
65342
66017
|
}
|
|
@@ -65357,7 +66032,7 @@ var ShiftsView = ({
|
|
|
65357
66032
|
nextDayOutput = dayOutputToKeep;
|
|
65358
66033
|
nextPPH = newShiftHours > 0 ? Math.round(dayOutputToKeep / newShiftHours) : 0;
|
|
65359
66034
|
}
|
|
65360
|
-
const resolvedActionName = (typeof threshold.action_name === "string" && threshold.action_name.trim().length > 0 ? threshold.action_name :
|
|
66035
|
+
const resolvedActionName = (typeof threshold.action_name === "string" && threshold.action_name.trim().length > 0 ? threshold.action_name : actionMetadataById.get(threshold.action_id)?.action_name) || ACTION_NAMES.ASSEMBLY;
|
|
65361
66036
|
return {
|
|
65362
66037
|
line_id: threshold.line_id || lineId,
|
|
65363
66038
|
shift_id: shift.shiftId,
|
|
@@ -65378,18 +66053,20 @@ var ShiftsView = ({
|
|
|
65378
66053
|
`Failed to update action thresholds for line ${lineId}, shift ${shift.shiftId}: ${thresholdsUpsertError.message}`
|
|
65379
66054
|
);
|
|
65380
66055
|
}
|
|
65381
|
-
const
|
|
65382
|
-
Array.from(
|
|
66056
|
+
const outputActionIds = new Set(
|
|
66057
|
+
Array.from(actionMetadataById.entries()).filter(([, action]) => action.action_family === ACTION_FAMILIES.OUTPUT).map(([actionId]) => actionId)
|
|
65383
66058
|
);
|
|
65384
|
-
const
|
|
65385
|
-
if (
|
|
65386
|
-
return
|
|
66059
|
+
const outputThresholds = recalculatedThresholds.filter((threshold) => {
|
|
66060
|
+
if (outputActionIds.has(threshold.action_id)) return true;
|
|
66061
|
+
return normalizeActionFamily({
|
|
66062
|
+
actionName: threshold.action_name
|
|
66063
|
+
}) === ACTION_FAMILIES.OUTPUT;
|
|
65387
66064
|
});
|
|
65388
|
-
const thresholdDayOutput =
|
|
66065
|
+
const thresholdDayOutput = outputThresholds.reduce(
|
|
65389
66066
|
(sum, threshold) => sum + (Number(threshold.total_day_output) || 0),
|
|
65390
66067
|
0
|
|
65391
66068
|
);
|
|
65392
|
-
const thresholdPPH =
|
|
66069
|
+
const thresholdPPH = outputThresholds.reduce(
|
|
65393
66070
|
(sum, threshold) => sum + (Number(threshold.pph_threshold) || 0),
|
|
65394
66071
|
0
|
|
65395
66072
|
);
|
|
@@ -66600,7 +67277,7 @@ var TargetsViewUI = ({
|
|
|
66600
67277
|
"aria-label": `Action type for ${formattedName}`,
|
|
66601
67278
|
children: [
|
|
66602
67279
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "assembly", className: "py-2", children: "Assembly" }),
|
|
66603
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
67280
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "output", className: "py-2", children: ACTION_NAMES.OUTPUT })
|
|
66604
67281
|
]
|
|
66605
67282
|
}
|
|
66606
67283
|
) }),
|
|
@@ -66671,7 +67348,7 @@ var TargetsViewUI = ({
|
|
|
66671
67348
|
"aria-label": `Action type for ${formattedName}`,
|
|
66672
67349
|
children: [
|
|
66673
67350
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "assembly", children: "Assembly" }),
|
|
66674
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
67351
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "output", children: ACTION_NAMES.OUTPUT })
|
|
66675
67352
|
]
|
|
66676
67353
|
}
|
|
66677
67354
|
)
|
|
@@ -66876,14 +67553,20 @@ var TargetsView = ({
|
|
|
66876
67553
|
throw new Error("Failed to fetch bulk targets data");
|
|
66877
67554
|
}
|
|
66878
67555
|
const { data } = bulkResponse;
|
|
66879
|
-
const assemblyAction = Object.values(data.actions).find((a) =>
|
|
66880
|
-
|
|
66881
|
-
|
|
67556
|
+
const assemblyAction = data.actions[ACTION_FAMILIES.ASSEMBLY] || Object.values(data.actions).find((a) => normalizeActionFamily({
|
|
67557
|
+
actionFamily: a.action_family,
|
|
67558
|
+
actionName: a.action_name
|
|
67559
|
+
}) === ACTION_FAMILIES.ASSEMBLY);
|
|
67560
|
+
const outputAction = data.actions[ACTION_FAMILIES.OUTPUT] || Object.values(data.actions).find((a) => normalizeActionFamily({
|
|
67561
|
+
actionFamily: a.action_family,
|
|
67562
|
+
actionName: a.action_name
|
|
67563
|
+
}) === ACTION_FAMILIES.OUTPUT);
|
|
67564
|
+
if (!assemblyAction || !outputAction) {
|
|
66882
67565
|
throw new Error("Could not find required actions in bulk response");
|
|
66883
67566
|
}
|
|
66884
67567
|
const actionIdsData = {
|
|
66885
67568
|
assembly: assemblyAction.id,
|
|
66886
|
-
|
|
67569
|
+
output: outputAction.id
|
|
66887
67570
|
};
|
|
66888
67571
|
setActionIds(actionIdsData);
|
|
66889
67572
|
const newAllShiftsData = {};
|
|
@@ -66928,12 +67611,16 @@ var TargetsView = ({
|
|
|
66928
67611
|
let actionType = "assembly";
|
|
66929
67612
|
let actionId = actionIdsData.assembly;
|
|
66930
67613
|
const effectiveActionId = threshold?.action_id ?? ws.action_id;
|
|
66931
|
-
|
|
66932
|
-
|
|
66933
|
-
|
|
66934
|
-
}
|
|
67614
|
+
const effectiveActionFamily = normalizeActionFamily({
|
|
67615
|
+
actionFamily: threshold?.action_family,
|
|
67616
|
+
actionType: ws.action_type
|
|
67617
|
+
});
|
|
67618
|
+
if (effectiveActionFamily === ACTION_FAMILIES.OUTPUT || effectiveActionId === outputAction.id || !effectiveActionId && ws.action_type === "output") {
|
|
67619
|
+
actionType = "output";
|
|
67620
|
+
actionId = effectiveActionId || outputAction.id;
|
|
67621
|
+
} else if (effectiveActionFamily === ACTION_FAMILIES.ASSEMBLY || effectiveActionId === assemblyAction.id || !effectiveActionId && ws.action_type === "assembly") {
|
|
66935
67622
|
actionType = "assembly";
|
|
66936
|
-
actionId = assemblyAction.id;
|
|
67623
|
+
actionId = effectiveActionId || assemblyAction.id;
|
|
66937
67624
|
}
|
|
66938
67625
|
return {
|
|
66939
67626
|
id: ws.id,
|
|
@@ -67205,7 +67892,9 @@ var TargetsView = ({
|
|
|
67205
67892
|
// Round to whole number
|
|
67206
67893
|
ideal_cycle_time: Number(ws.targetCycleTime) || 0,
|
|
67207
67894
|
total_day_output: Number(ws.targetDayOutput) || 0,
|
|
67208
|
-
action_name: ws.actionType === "assembly" ? ACTION_NAMES.ASSEMBLY : ACTION_NAMES.
|
|
67895
|
+
action_name: ws.actionType === "assembly" ? ACTION_NAMES.ASSEMBLY : ACTION_NAMES.OUTPUT,
|
|
67896
|
+
action_family: ws.actionType,
|
|
67897
|
+
display_name: ws.actionType === "assembly" ? ACTION_NAMES.ASSEMBLY : ACTION_NAMES.OUTPUT,
|
|
67209
67898
|
updated_by: currentEffectiveUserId,
|
|
67210
67899
|
// Use the potentially hardcoded ID
|
|
67211
67900
|
...skuEnabled && lineDataToSave.selectedSKU ? { sku_id: lineDataToSave.selectedSKU.id } : {}
|
|
@@ -67213,7 +67902,7 @@ var TargetsView = ({
|
|
|
67213
67902
|
console.log(`[handleSaveLine] workspaceThresholdUpdates for ${lineId}:`, workspaceThresholdUpdates);
|
|
67214
67903
|
await workspaceService.updateActionThresholds(workspaceThresholdUpdates);
|
|
67215
67904
|
console.log(`[handleSaveLine] Successfully updated action thresholds for ${lineId}`);
|
|
67216
|
-
const
|
|
67905
|
+
const outputWorkspaces = lineDataToSave.workspaces.filter((ws) => ws.actionType === "output");
|
|
67217
67906
|
let resolvedLineThresholdSkuId = lineDataToSave.selectedSKU?.id || null;
|
|
67218
67907
|
if (!resolvedLineThresholdSkuId) {
|
|
67219
67908
|
const { data: dummySkuRows, error: dummySkuError } = await supabase.from("skus").select("id").eq("line_id", lineId).eq("sku_definition", "dummy_definition").eq("is_active", true).limit(1);
|
|
@@ -67231,8 +67920,8 @@ var TargetsView = ({
|
|
|
67231
67920
|
date: currentDate,
|
|
67232
67921
|
shift_id: selectedShift,
|
|
67233
67922
|
product_code: lineDataToSave.productId,
|
|
67234
|
-
threshold_day_output:
|
|
67235
|
-
threshold_pph:
|
|
67923
|
+
threshold_day_output: outputWorkspaces.reduce((acc, ws) => acc + (Number(ws.targetDayOutput) || 0), 0),
|
|
67924
|
+
threshold_pph: outputWorkspaces.reduce((acc, ws) => acc + (ws.targetPPH ? Math.round(Number(ws.targetPPH)) : 0), 0),
|
|
67236
67925
|
// Round each PPH value
|
|
67237
67926
|
sku_id: resolvedLineThresholdSkuId
|
|
67238
67927
|
};
|
|
@@ -67760,6 +68449,7 @@ var WorkspaceDetailView = ({
|
|
|
67760
68449
|
avg_efficiency: Number(cachedOverviewMetrics.efficiency || 0),
|
|
67761
68450
|
total_actions: totalActions,
|
|
67762
68451
|
hourly_action_counts: [],
|
|
68452
|
+
hourly_cycle_times: [],
|
|
67763
68453
|
workspace_rank: 0,
|
|
67764
68454
|
total_workspaces: 0,
|
|
67765
68455
|
ideal_output_until_now: idealOutput,
|
|
@@ -67770,6 +68460,22 @@ var WorkspaceDetailView = ({
|
|
|
67770
68460
|
}, [cachedOverviewMetrics, shiftConfig?.shifts]);
|
|
67771
68461
|
const workspace = (isHistoricView ? historicMetrics : liveMetrics) || cachedDetailedMetrics || overviewFallback;
|
|
67772
68462
|
const detailedWorkspaceMetrics = (isHistoricView ? historicMetrics : liveMetrics) || cachedDetailedMetrics;
|
|
68463
|
+
const cycleTimeChartData = React141.useMemo(
|
|
68464
|
+
() => Array.isArray(workspace?.hourly_cycle_times) ? workspace.hourly_cycle_times.map((value) => {
|
|
68465
|
+
const numericValue = Number(value);
|
|
68466
|
+
return Number.isFinite(numericValue) ? numericValue : 0;
|
|
68467
|
+
}) : [],
|
|
68468
|
+
[workspace?.hourly_cycle_times]
|
|
68469
|
+
);
|
|
68470
|
+
const cycleTimeDatasetKey = React141.useMemo(
|
|
68471
|
+
() => [
|
|
68472
|
+
workspace?.workspace_id || workspaceId || "workspace",
|
|
68473
|
+
date || workspace?.date || "live",
|
|
68474
|
+
parsedShiftId ?? workspace?.shift_id ?? "current",
|
|
68475
|
+
"hourly"
|
|
68476
|
+
].join(":"),
|
|
68477
|
+
[workspace?.workspace_id, workspaceId, date, workspace?.date, parsedShiftId, workspace?.shift_id]
|
|
68478
|
+
);
|
|
67773
68479
|
const hasWorkspaceSnapshot = Boolean(workspace);
|
|
67774
68480
|
const loading = ((isHistoricView ? historicLoading : liveLoading) || isShiftConfigLoading) && !hasWorkspaceSnapshot;
|
|
67775
68481
|
const error = isHistoricView ? historicError : liveError;
|
|
@@ -68011,10 +68717,47 @@ var WorkspaceDetailView = ({
|
|
|
68011
68717
|
return filterDataByDateKeyRange(monthlyData, range);
|
|
68012
68718
|
}, [monthlyData, range]);
|
|
68013
68719
|
const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
|
|
68014
|
-
const
|
|
68720
|
+
const workspaceActionType = workspace && "action_type" in workspace ? workspace.action_type : void 0;
|
|
68721
|
+
const workspaceAssemblyEnabled = workspace && "line_assembly_enabled" in workspace ? workspace.line_assembly_enabled === true : false;
|
|
68722
|
+
const isAssemblyWorkspace = workspaceActionType === "assembly" || workspaceAssemblyEnabled;
|
|
68723
|
+
const shouldShowCycleTimeChart = !isUptimeMode && (showCycleTimeChart ?? isAssemblyWorkspace);
|
|
68015
68724
|
const showIdleBreakdownChart = !shouldShowCycleTimeChart && idleTimeVlmEnabled;
|
|
68016
68725
|
const idleClipDate = date || workspace?.date || calculatedOperationalDate || getOperationalDate(timezone);
|
|
68017
68726
|
const idleClipShiftId = parsedShiftId ?? workspace?.shift_id;
|
|
68727
|
+
const hourlyIdleMinutes = React141.useMemo(() => {
|
|
68728
|
+
if (!shouldShowCycleTimeChart || !workspace?.idle_time_hourly || !workspace?.shift_start) return [];
|
|
68729
|
+
const parseTimeToMinutes3 = (time2) => {
|
|
68730
|
+
const [h, m] = time2.split(":").map(Number);
|
|
68731
|
+
if (!Number.isFinite(h) || !Number.isFinite(m)) return 0;
|
|
68732
|
+
return h * 60 + m;
|
|
68733
|
+
};
|
|
68734
|
+
const startTotal = parseTimeToMinutes3(workspace.shift_start);
|
|
68735
|
+
const endTotalRaw = workspace.shift_end ? parseTimeToMinutes3(workspace.shift_end) : startTotal + 11 * 60;
|
|
68736
|
+
const endTotal = endTotalRaw <= startTotal ? endTotalRaw + 24 * 60 : endTotalRaw;
|
|
68737
|
+
const shiftDuration = Math.max(60, endTotal - startTotal);
|
|
68738
|
+
const totalHourSlots = Math.max(1, Math.ceil(shiftDuration / 60));
|
|
68739
|
+
const idleTimeHourlyObj = workspace.idle_time_hourly || {};
|
|
68740
|
+
const result = Array(totalHourSlots).fill(0);
|
|
68741
|
+
for (let i = 0; i < totalHourSlots; i++) {
|
|
68742
|
+
const startSlotMins = startTotal + i * 60;
|
|
68743
|
+
let endSlotMins = startSlotMins + 60;
|
|
68744
|
+
if (endSlotMins > endTotal) endSlotMins = endTotal;
|
|
68745
|
+
let idleCount = 0;
|
|
68746
|
+
for (let m = startSlotMins; m < endSlotMins; m++) {
|
|
68747
|
+
const hourKey = Math.floor(m / 60) % 24;
|
|
68748
|
+
const minuteKey = m % 60;
|
|
68749
|
+
const hourData = idleTimeHourlyObj[hourKey.toString()] || [];
|
|
68750
|
+
if (Array.isArray(hourData)) {
|
|
68751
|
+
const val = hourData[minuteKey];
|
|
68752
|
+
if (val === 1 || val === "1") {
|
|
68753
|
+
idleCount++;
|
|
68754
|
+
}
|
|
68755
|
+
}
|
|
68756
|
+
}
|
|
68757
|
+
result[i] = idleCount;
|
|
68758
|
+
}
|
|
68759
|
+
return result;
|
|
68760
|
+
}, [shouldShowCycleTimeChart, workspace?.idle_time_hourly, workspace?.shift_start, workspace?.shift_end]);
|
|
68018
68761
|
const shiftDurationMinutes = React141.useMemo(
|
|
68019
68762
|
() => getShiftDurationMinutes(workspace?.shift_start, workspace?.shift_end),
|
|
68020
68763
|
[workspace?.shift_start, workspace?.shift_end]
|
|
@@ -68087,7 +68830,7 @@ var WorkspaceDetailView = ({
|
|
|
68087
68830
|
}
|
|
68088
68831
|
}, [returnUrl]);
|
|
68089
68832
|
const handleBackNavigation = () => {
|
|
68090
|
-
if (
|
|
68833
|
+
if (isHistoricView) {
|
|
68091
68834
|
setActiveTab("monthly_history");
|
|
68092
68835
|
if (onNavigate) {
|
|
68093
68836
|
const params = new URLSearchParams();
|
|
@@ -68251,7 +68994,7 @@ var WorkspaceDetailView = ({
|
|
|
68251
68994
|
BackButtonMinimal,
|
|
68252
68995
|
{
|
|
68253
68996
|
onClick: handleBackNavigation,
|
|
68254
|
-
text: previousView === "line_monthly_history" ? "Back to Line History" : returnUrl && returnUrl.includes("monthly_history") ? "Back to Line History" : returnUrl && returnUrl.includes("/kpis/") ? "Back to KPIs" : returnUrl && returnUrl.includes("/leaderboard/") ? "Back to Leaderboard" :
|
|
68997
|
+
text: previousView === "line_monthly_history" ? "Back to Line History" : returnUrl && returnUrl.includes("monthly_history") ? "Back to Line History" : returnUrl && returnUrl.includes("/kpis/") ? "Back to KPIs" : returnUrl && returnUrl.includes("/leaderboard/") ? "Back to Leaderboard" : isHistoricView && activeTab !== "monthly_history" ? "Back to Monthly History" : "Back",
|
|
68255
68998
|
size: "default",
|
|
68256
68999
|
"aria-label": "Navigate back to previous page"
|
|
68257
69000
|
}
|
|
@@ -68428,7 +69171,8 @@ var WorkspaceDetailView = ({
|
|
|
68428
69171
|
{
|
|
68429
69172
|
workspace,
|
|
68430
69173
|
idleTimeReasons: idleTimeChartData,
|
|
68431
|
-
efficiencyLegend
|
|
69174
|
+
efficiencyLegend,
|
|
69175
|
+
hourlyCycleTimes: cycleTimeChartData
|
|
68432
69176
|
}
|
|
68433
69177
|
) }),
|
|
68434
69178
|
activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -68509,7 +69253,7 @@ var WorkspaceDetailView = ({
|
|
|
68509
69253
|
animate: "animate",
|
|
68510
69254
|
children: [
|
|
68511
69255
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-4", children: [
|
|
68512
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-
|
|
69256
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700", children: isUptimeMode ? "Machine Utilization" : shouldShowCycleTimeChart ? "Cycle time trend" : "Hourly Output" }),
|
|
68513
69257
|
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
68514
69258
|
"button",
|
|
68515
69259
|
{
|
|
@@ -68542,9 +69286,14 @@ var WorkspaceDetailView = ({
|
|
|
68542
69286
|
) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
68543
69287
|
CycleTimeOverTimeChart,
|
|
68544
69288
|
{
|
|
68545
|
-
data:
|
|
69289
|
+
data: cycleTimeChartData,
|
|
68546
69290
|
idealCycleTime: workspace.ideal_cycle_time || 0,
|
|
68547
|
-
shiftStart: workspace.shift_start || ""
|
|
69291
|
+
shiftStart: workspace.shift_start || "",
|
|
69292
|
+
shiftEnd: workspace.shift_end || "",
|
|
69293
|
+
xAxisMode: "hourly",
|
|
69294
|
+
datasetKey: cycleTimeDatasetKey,
|
|
69295
|
+
showIdleTime: showChartIdleTime,
|
|
69296
|
+
idleTimeData: hourlyIdleMinutes
|
|
68548
69297
|
}
|
|
68549
69298
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
68550
69299
|
HourlyOutputChart2,
|
|
@@ -68591,7 +69340,8 @@ var WorkspaceDetailView = ({
|
|
|
68591
69340
|
{
|
|
68592
69341
|
workspace,
|
|
68593
69342
|
legend: efficiencyLegend,
|
|
68594
|
-
layout: "stack"
|
|
69343
|
+
layout: "stack",
|
|
69344
|
+
idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0
|
|
68595
69345
|
}
|
|
68596
69346
|
) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, legend: efficiencyLegend, className: "flex-1" }) })
|
|
68597
69347
|
] }),
|
|
@@ -68636,7 +69386,7 @@ var WorkspaceDetailView = ({
|
|
|
68636
69386
|
animate: "animate",
|
|
68637
69387
|
children: [
|
|
68638
69388
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 mb-4 flex-none", children: [
|
|
68639
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-
|
|
69389
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700", children: isUptimeMode ? "Machine Utilization" : shouldShowCycleTimeChart ? "Cycle time trend" : "Hourly Output" }),
|
|
68640
69390
|
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
68641
69391
|
"button",
|
|
68642
69392
|
{
|
|
@@ -68665,9 +69415,14 @@ var WorkspaceDetailView = ({
|
|
|
68665
69415
|
) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
68666
69416
|
CycleTimeOverTimeChart,
|
|
68667
69417
|
{
|
|
68668
|
-
data:
|
|
69418
|
+
data: cycleTimeChartData,
|
|
68669
69419
|
idealCycleTime: workspace.ideal_cycle_time || 0,
|
|
68670
|
-
shiftStart: workspace.shift_start || ""
|
|
69420
|
+
shiftStart: workspace.shift_start || "",
|
|
69421
|
+
shiftEnd: workspace.shift_end || "",
|
|
69422
|
+
xAxisMode: "hourly",
|
|
69423
|
+
datasetKey: cycleTimeDatasetKey,
|
|
69424
|
+
showIdleTime: showChartIdleTime,
|
|
69425
|
+
idleTimeData: hourlyIdleMinutes
|
|
68671
69426
|
}
|
|
68672
69427
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
68673
69428
|
HourlyOutputChart2,
|
|
@@ -68719,7 +69474,8 @@ var WorkspaceDetailView = ({
|
|
|
68719
69474
|
workspace,
|
|
68720
69475
|
legend: efficiencyLegend,
|
|
68721
69476
|
layout: "grid",
|
|
68722
|
-
className: desktopBottomSectionClass
|
|
69477
|
+
className: desktopBottomSectionClass,
|
|
69478
|
+
idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0
|
|
68723
69479
|
}
|
|
68724
69480
|
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("flex min-h-0", desktopBottomSectionClass), children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, legend: efficiencyLegend, className: "flex-1" }) })
|
|
68725
69481
|
] })
|
|
@@ -68749,6 +69505,7 @@ var WorkspaceDetailView = ({
|
|
|
68749
69505
|
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
68750
69506
|
legend: efficiencyLegend,
|
|
68751
69507
|
trendSummary: workspaceMonthlyTrend,
|
|
69508
|
+
isAssemblyWorkspace,
|
|
68752
69509
|
onDateSelect: (selectedDate, shiftId) => {
|
|
68753
69510
|
if (onDateSelect) {
|
|
68754
69511
|
onDateSelect(selectedDate, shiftId);
|
|
@@ -74836,6 +75593,11 @@ var normalizeTrend = (value) => ({
|
|
|
74836
75593
|
});
|
|
74837
75594
|
var normalizeIdleBreakdown = (value) => (value || []).map((item) => ({
|
|
74838
75595
|
reason: item?.reason?.trim() || "Unknown",
|
|
75596
|
+
reason_key: item?.reason_key?.trim() || item?.reason?.trim() || "unknown",
|
|
75597
|
+
display_name: item?.display_name?.trim() || void 0,
|
|
75598
|
+
palette_token: item?.palette_token?.trim() || void 0,
|
|
75599
|
+
icon_token: item?.icon_token?.trim() || void 0,
|
|
75600
|
+
is_known: typeof item?.is_known === "boolean" ? item.is_known : null,
|
|
74839
75601
|
percentage: normalizeNumber(item?.percentage),
|
|
74840
75602
|
total_duration_seconds: normalizeNumber(item?.total_duration_seconds),
|
|
74841
75603
|
efficiency_loss_percentage: normalizeNumber(item?.efficiency_loss_percentage),
|
|
@@ -75887,7 +76649,12 @@ var IdleBreakdownCard = React141__namespace.default.memo(({
|
|
|
75887
76649
|
const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
|
|
75888
76650
|
const idleBreakdown = React141__namespace.default.useMemo(() => {
|
|
75889
76651
|
return idle.data.map((item) => ({
|
|
75890
|
-
name: item.reason?.trim() || "Unknown",
|
|
76652
|
+
name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
|
|
76653
|
+
reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
|
|
76654
|
+
displayName: item.display_name?.trim() || item.reason?.trim() || "Unknown",
|
|
76655
|
+
paletteToken: item.palette_token?.trim(),
|
|
76656
|
+
iconToken: item.icon_token?.trim(),
|
|
76657
|
+
isKnown: item.is_known ?? void 0,
|
|
75891
76658
|
value: toNumber3(item.percentage) || 0,
|
|
75892
76659
|
totalDurationSeconds: toNumber3(item.total_duration_seconds),
|
|
75893
76660
|
efficiencyLossPercentage: toNumber3(item.efficiency_loss_percentage),
|
|
@@ -77179,6 +77946,7 @@ var streamProxyConfig = {
|
|
|
77179
77946
|
}
|
|
77180
77947
|
};
|
|
77181
77948
|
|
|
77949
|
+
exports.ACTION_FAMILIES = ACTION_FAMILIES;
|
|
77182
77950
|
exports.ACTION_NAMES = ACTION_NAMES;
|
|
77183
77951
|
exports.AIAgentView = AIAgentView_default;
|
|
77184
77952
|
exports.AcceptInvite = AcceptInvite;
|
|
@@ -77291,7 +78059,7 @@ exports.LINE_1_UUID = LINE_1_UUID;
|
|
|
77291
78059
|
exports.LINE_2_UUID = LINE_2_UUID;
|
|
77292
78060
|
exports.LargeOutputProgressChart = LargeOutputProgressChart;
|
|
77293
78061
|
exports.LeaderboardDetailView = LeaderboardDetailView_default;
|
|
77294
|
-
exports.Legend =
|
|
78062
|
+
exports.Legend = Legend5;
|
|
77295
78063
|
exports.LineAssignmentDropdown = LineAssignmentDropdown;
|
|
77296
78064
|
exports.LineChart = LineChart;
|
|
77297
78065
|
exports.LineHistoryCalendar = LineHistoryCalendar;
|
|
@@ -77473,6 +78241,7 @@ exports.formatReasonLabel = formatReasonLabel;
|
|
|
77473
78241
|
exports.formatRelativeTime = formatRelativeTime;
|
|
77474
78242
|
exports.formatTimeInZone = formatTimeInZone;
|
|
77475
78243
|
exports.fromUrlFriendlyName = fromUrlFriendlyName;
|
|
78244
|
+
exports.getActionDisplayName = getActionDisplayName;
|
|
77476
78245
|
exports.getAllLineDisplayNames = getAllLineDisplayNames;
|
|
77477
78246
|
exports.getAllThreadMessages = getAllThreadMessages;
|
|
77478
78247
|
exports.getAllWorkspaceDisplayNamesAsync = getAllWorkspaceDisplayNamesAsync;
|
|
@@ -77511,7 +78280,6 @@ exports.getMonthKeyBounds = getMonthKeyBounds;
|
|
|
77511
78280
|
exports.getMonthWeekRanges = getMonthWeekRanges;
|
|
77512
78281
|
exports.getNextUpdateInterval = getNextUpdateInterval;
|
|
77513
78282
|
exports.getOperationalDate = getOperationalDate;
|
|
77514
|
-
exports.getReasonColor = getReasonColor;
|
|
77515
78283
|
exports.getRoleAssignmentKind = getRoleAssignmentKind;
|
|
77516
78284
|
exports.getRoleDescription = getRoleDescription;
|
|
77517
78285
|
exports.getRoleLabel = getRoleLabel;
|
|
@@ -77546,6 +78314,7 @@ exports.isFactoryScopedRole = isFactoryScopedRole;
|
|
|
77546
78314
|
exports.isFullMonthRange = isFullMonthRange;
|
|
77547
78315
|
exports.isLegacyConfiguration = isLegacyConfiguration;
|
|
77548
78316
|
exports.isPrefetchError = isPrefetchError;
|
|
78317
|
+
exports.isRecentFlowVideoGridMetricMode = isRecentFlowVideoGridMetricMode;
|
|
77549
78318
|
exports.isSafari = isSafari;
|
|
77550
78319
|
exports.isSupervisorRole = isSupervisorRole;
|
|
77551
78320
|
exports.isTransitionPeriod = isTransitionPeriod;
|
|
@@ -77556,14 +78325,17 @@ exports.isValidPrefetchParams = isValidPrefetchParams;
|
|
|
77556
78325
|
exports.isValidPrefetchStatus = isValidPrefetchStatus;
|
|
77557
78326
|
exports.isValidWorkspaceDetailedMetricsPayload = isValidWorkspaceDetailedMetricsPayload;
|
|
77558
78327
|
exports.isValidWorkspaceMetricsPayload = isValidWorkspaceMetricsPayload;
|
|
78328
|
+
exports.isWipGatedVideoGridMetricMode = isWipGatedVideoGridMetricMode;
|
|
77559
78329
|
exports.isWorkspaceDisplayNamesLoaded = isWorkspaceDisplayNamesLoaded;
|
|
77560
78330
|
exports.isWorkspaceDisplayNamesLoading = isWorkspaceDisplayNamesLoading;
|
|
77561
78331
|
exports.lineLeaderboardService = lineLeaderboardService;
|
|
77562
78332
|
exports.linesService = linesService;
|
|
77563
78333
|
exports.mergeWithDefaultConfig = mergeWithDefaultConfig;
|
|
77564
78334
|
exports.migrateLegacyConfiguration = migrateLegacyConfiguration;
|
|
78335
|
+
exports.normalizeActionFamily = normalizeActionFamily;
|
|
77565
78336
|
exports.normalizeDateKeyRange = normalizeDateKeyRange;
|
|
77566
78337
|
exports.normalizeRoleLevel = normalizeRoleLevel;
|
|
78338
|
+
exports.normalizeVideoGridMetricMode = normalizeVideoGridMetricMode;
|
|
77567
78339
|
exports.optifyeAgentClient = optifyeAgentClient;
|
|
77568
78340
|
exports.parseDateKeyToDate = parseDateKeyToDate;
|
|
77569
78341
|
exports.parseS3Uri = parseS3Uri;
|