@optifye/dashboard-core 6.11.12 → 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 +87 -24
- package/dist/index.d.ts +87 -24
- package/dist/index.js +1418 -694
- package/dist/index.mjs +1412 -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,40 @@ 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);
|
|
33566
|
-
var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
|
|
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
|
+
};
|
|
33567
33811
|
var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
33568
|
-
if (!
|
|
33812
|
+
if (!hasVideoGridRecentFlow(workspace) || !isVideoGridWipGated(workspace)) {
|
|
33569
33813
|
return false;
|
|
33570
33814
|
}
|
|
33571
33815
|
if (getVideoGridBaseColorState(workspace, legend) !== "red") {
|
|
@@ -33604,7 +33848,10 @@ var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
|
|
|
33604
33848
|
var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace);
|
|
33605
33849
|
var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
33606
33850
|
const baseColor = getVideoGridBaseColorState(workspace, legend);
|
|
33607
|
-
if (!
|
|
33851
|
+
if (!hasVideoGridRecentFlow(workspace)) {
|
|
33852
|
+
return baseColor;
|
|
33853
|
+
}
|
|
33854
|
+
if (!isVideoGridWipGated(workspace)) {
|
|
33608
33855
|
return baseColor;
|
|
33609
33856
|
}
|
|
33610
33857
|
if (baseColor !== "red") {
|
|
@@ -33626,11 +33873,11 @@ var getVideoGridLegendLabel = (workspaces) => {
|
|
|
33626
33873
|
if (visibleWorkspaces.length === 0) {
|
|
33627
33874
|
return MAP_GRID_LEGEND_LABEL;
|
|
33628
33875
|
}
|
|
33629
|
-
const
|
|
33630
|
-
if (
|
|
33876
|
+
const recentFlowEnabledCount = visibleWorkspaces.filter(isVideoGridRecentFlowEnabled).length;
|
|
33877
|
+
if (recentFlowEnabledCount === 0) {
|
|
33631
33878
|
return MAP_GRID_LEGEND_LABEL;
|
|
33632
33879
|
}
|
|
33633
|
-
if (
|
|
33880
|
+
if (recentFlowEnabledCount === visibleWorkspaces.length) {
|
|
33634
33881
|
return VIDEO_GRID_LEGEND_LABEL;
|
|
33635
33882
|
}
|
|
33636
33883
|
return MIXED_VIDEO_GRID_LEGEND_LABEL;
|
|
@@ -33680,7 +33927,11 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33680
33927
|
const videoGridMetricValue = getVideoGridMetricValue(workspace);
|
|
33681
33928
|
const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
|
|
33682
33929
|
const videoGridColorState = getVideoGridColorState(workspace, effectiveLegend);
|
|
33683
|
-
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";
|
|
33684
33935
|
const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
|
|
33685
33936
|
const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
|
|
33686
33937
|
const efficiencyStatus = videoGridColorState === "green" ? "High" : videoGridColorState === "yellow" ? "Medium" : videoGridColorState === "red" ? "Low" : "Neutral";
|
|
@@ -33762,10 +34013,7 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33762
34013
|
"data-testid": "video-card-metric-badge",
|
|
33763
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`,
|
|
33764
34015
|
title: badgeTitle,
|
|
33765
|
-
children: /* @__PURE__ */ jsxRuntime.
|
|
33766
|
-
Math.round(videoGridDisplayValue),
|
|
33767
|
-
"%"
|
|
33768
|
-
] })
|
|
34016
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${compact ? "text-[10px]" : "text-xs"} font-semibold`, children: badgeLabel })
|
|
33769
34017
|
}
|
|
33770
34018
|
) }),
|
|
33771
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(
|
|
@@ -33773,7 +34021,7 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33773
34021
|
{
|
|
33774
34022
|
"data-testid": "video-card-metric-bar",
|
|
33775
34023
|
className: `h-full ${efficiencyBarClass} transition-all duration-500`,
|
|
33776
|
-
style: { width: `${Math.min(100, videoGridMetricValue)}%` }
|
|
34024
|
+
style: { width: `${hasBarMetric ? Math.min(100, Math.max(0, videoGridMetricValue)) : videoGridColorState === "neutral" ? 100 : 0}%` }
|
|
33777
34025
|
}
|
|
33778
34026
|
) })
|
|
33779
34027
|
] }),
|
|
@@ -33804,7 +34052,7 @@ var VideoCard = React141__namespace.default.memo(({
|
|
|
33804
34052
|
}
|
|
33805
34053
|
);
|
|
33806
34054
|
}, (prevProps, nextProps) => {
|
|
33807
|
-
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) {
|
|
33808
34056
|
return false;
|
|
33809
34057
|
}
|
|
33810
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) {
|
|
@@ -39328,45 +39576,56 @@ var FileManagerFilters = ({
|
|
|
39328
39576
|
});
|
|
39329
39577
|
const [loadingPercentile, setLoadingPercentile] = React141.useState(false);
|
|
39330
39578
|
const resolvedTargetCycleTime = targetCycleTime && targetCycleTime > 0 ? targetCycleTime : null;
|
|
39331
|
-
const
|
|
39332
|
-
const
|
|
39333
|
-
|
|
39334
|
-
|
|
39335
|
-
|
|
39336
|
-
|
|
39337
|
-
|
|
39338
|
-
|
|
39339
|
-
|
|
39340
|
-
|
|
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
|
+
});
|
|
39341
39594
|
return {
|
|
39342
|
-
color:
|
|
39343
|
-
bgColor:
|
|
39344
|
-
borderColor:
|
|
39345
|
-
Icon:
|
|
39346
|
-
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
|
|
39347
39601
|
};
|
|
39348
|
-
};
|
|
39349
|
-
const normalizeIdleReasonLabel = React141.useCallback((label) => {
|
|
39350
|
-
return label.replace(/_/g, " ").trim();
|
|
39351
39602
|
}, []);
|
|
39352
|
-
const getIdleTimeRootCause = React141.useCallback((clipId) => {
|
|
39353
|
-
const classification = mergedClipClassifications[clipId];
|
|
39354
|
-
if (!classification) return "processing";
|
|
39355
|
-
if (classification.status === "processing") return "processing";
|
|
39356
|
-
return classification.label || "processing";
|
|
39357
|
-
}, [mergedClipClassifications]);
|
|
39358
39603
|
const idleReasonOptions = React141.useMemo(() => {
|
|
39359
39604
|
const idleClips = clipMetadata["idle_time"] || [];
|
|
39360
|
-
const uniqueReasons = /* @__PURE__ */ new
|
|
39605
|
+
const uniqueReasons = /* @__PURE__ */ new Map();
|
|
39361
39606
|
idleClips.forEach((clip) => {
|
|
39362
39607
|
const clipId = clip.clipId || clip.id;
|
|
39363
39608
|
if (!clipId) return;
|
|
39364
|
-
const
|
|
39365
|
-
if (!
|
|
39366
|
-
|
|
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
|
+
}
|
|
39367
39622
|
});
|
|
39368
|
-
return Array.from(uniqueReasons).sort((a, b) => a.localeCompare(b));
|
|
39369
|
-
}, [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
|
+
);
|
|
39370
39629
|
const getClipBadge = React141.useCallback((node) => {
|
|
39371
39630
|
if (node.categoryId === "idle_time" || node.categoryId === "low_value") {
|
|
39372
39631
|
return { text: "Idle", className: "bg-red-100 text-red-700" };
|
|
@@ -39438,6 +39697,10 @@ var FileManagerFilters = ({
|
|
|
39438
39697
|
seededClassifications[clip.clipId] = {
|
|
39439
39698
|
status: clip.classification_status,
|
|
39440
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,
|
|
39441
39704
|
confidence: clip.classification_confidence ?? void 0
|
|
39442
39705
|
};
|
|
39443
39706
|
}
|
|
@@ -39821,7 +40084,7 @@ var FileManagerFilters = ({
|
|
|
39821
40084
|
return slot ? slot.label : value;
|
|
39822
40085
|
}, [timeSlots]);
|
|
39823
40086
|
const isClipInTimeRange = React141.useCallback((clipTimestamp) => {
|
|
39824
|
-
if (!
|
|
40087
|
+
if (!startTime || !endTime) {
|
|
39825
40088
|
return true;
|
|
39826
40089
|
}
|
|
39827
40090
|
try {
|
|
@@ -39847,9 +40110,8 @@ var FileManagerFilters = ({
|
|
|
39847
40110
|
let filteredClips = categoryClips.filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
39848
40111
|
if (category.id === "idle_time" && idleLabelFilter) {
|
|
39849
40112
|
filteredClips = filteredClips.filter((clip) => {
|
|
39850
|
-
const
|
|
39851
|
-
|
|
39852
|
-
return normalizedRootCause === idleLabelFilter;
|
|
40113
|
+
const classification = getIdleTimeClassification(clip.clipId || clip.id);
|
|
40114
|
+
return classification?.label === idleLabelFilter;
|
|
39853
40115
|
});
|
|
39854
40116
|
}
|
|
39855
40117
|
const displayCount = isTimeFilterActive || category.id === "idle_time" && idleLabelFilter ? filteredClips.length : categoryCount;
|
|
@@ -39879,8 +40141,9 @@ var FileManagerFilters = ({
|
|
|
39879
40141
|
clipPosition: index + 1,
|
|
39880
40142
|
// Store 1-based position
|
|
39881
40143
|
cycleTimeSeconds: cycleTime,
|
|
39882
|
-
duration: clip.duration
|
|
40144
|
+
duration: clip.duration,
|
|
39883
40145
|
// Store duration for custom badge rendering
|
|
40146
|
+
cycleItemCount: clip.cycle_item_count ?? null
|
|
39884
40147
|
};
|
|
39885
40148
|
});
|
|
39886
40149
|
regularCategoryNodes.push({
|
|
@@ -40136,14 +40399,14 @@ var FileManagerFilters = ({
|
|
|
40136
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") ? (
|
|
40137
40400
|
// Show root cause icon for idle time clips
|
|
40138
40401
|
(() => {
|
|
40139
|
-
const
|
|
40140
|
-
if (
|
|
40402
|
+
const classification = getIdleTimeClassification(node.clipId || node.id);
|
|
40403
|
+
if (!classification || classification.status === "processing") {
|
|
40141
40404
|
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-3.5 w-3.5 text-purple-500", strokeWidth: 2.5 });
|
|
40142
40405
|
}
|
|
40143
40406
|
if (!idleTimeVlmEnabled && node.categoryId === "idle_time") {
|
|
40144
40407
|
return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-3.5 w-3.5 text-purple-500", strokeWidth: 2.5 });
|
|
40145
40408
|
}
|
|
40146
|
-
const config = getRootCauseConfig(
|
|
40409
|
+
const config = getRootCauseConfig(classification);
|
|
40147
40410
|
if (config) {
|
|
40148
40411
|
const IconComponent = config.Icon;
|
|
40149
40412
|
return /* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 ${config.iconColor}`, strokeWidth: 2.5 });
|
|
@@ -40165,10 +40428,10 @@ var FileManagerFilters = ({
|
|
|
40165
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" });
|
|
40166
40429
|
}
|
|
40167
40430
|
const clipId = node.clipId || node.id;
|
|
40168
|
-
const
|
|
40169
|
-
const isProcessing =
|
|
40170
|
-
const
|
|
40171
|
-
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...";
|
|
40172
40435
|
const bgClass = config ? config.bgColor : "bg-slate-50";
|
|
40173
40436
|
const textClass = config ? config.color : "text-slate-700";
|
|
40174
40437
|
const borderClass = config ? config.borderColor : "border-slate-200";
|
|
@@ -40178,7 +40441,13 @@ var FileManagerFilters = ({
|
|
|
40178
40441
|
// Show badge for other clips
|
|
40179
40442
|
(() => {
|
|
40180
40443
|
const badge = getClipBadge(node);
|
|
40181
|
-
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
|
+
] });
|
|
40182
40451
|
})()
|
|
40183
40452
|
) })
|
|
40184
40453
|
] }),
|
|
@@ -40266,7 +40535,7 @@ var FileManagerFilters = ({
|
|
|
40266
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: [
|
|
40267
40536
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium", children: [
|
|
40268
40537
|
"Reason: ",
|
|
40269
|
-
idleLabelFilter.replace(/_/g, " ")
|
|
40538
|
+
selectedIdleReasonOption?.displayName || idleLabelFilter.replace(/_/g, " ")
|
|
40270
40539
|
] }),
|
|
40271
40540
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
40272
40541
|
"button",
|
|
@@ -40315,21 +40584,31 @@ var FileManagerFilters = ({
|
|
|
40315
40584
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
40316
40585
|
"Loading idle reasons..."
|
|
40317
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) => {
|
|
40318
|
-
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
|
+
}
|
|
40319
40598
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
40320
40599
|
"button",
|
|
40321
40600
|
{
|
|
40322
40601
|
onClick: () => {
|
|
40323
|
-
setIdleLabelFilter(reason);
|
|
40602
|
+
setIdleLabelFilter(reason.label);
|
|
40324
40603
|
setShowIdleLabelFilterModal(false);
|
|
40325
40604
|
},
|
|
40326
|
-
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"}`,
|
|
40327
40606
|
children: [
|
|
40328
40607
|
/* @__PURE__ */ jsxRuntime.jsx(config.Icon, { className: `h-3.5 w-3.5 ${config.iconColor}` }),
|
|
40329
|
-
reason
|
|
40608
|
+
reason.displayName
|
|
40330
40609
|
]
|
|
40331
40610
|
},
|
|
40332
|
-
reason
|
|
40611
|
+
reason.label
|
|
40333
40612
|
);
|
|
40334
40613
|
}) })
|
|
40335
40614
|
]
|
|
@@ -40444,33 +40723,14 @@ var FileManagerFilters = ({
|
|
|
40444
40723
|
slot.value
|
|
40445
40724
|
)) })
|
|
40446
40725
|
] })
|
|
40447
|
-
] }) })
|
|
40448
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-t border-slate-200 bg-white rounded-b-xl", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
40449
|
-
"button",
|
|
40450
|
-
{
|
|
40451
|
-
onClick: () => {
|
|
40452
|
-
if (startTime && endTime) {
|
|
40453
|
-
setIsTimeFilterActive(true);
|
|
40454
|
-
}
|
|
40455
|
-
setShowTimeFilterModal(false);
|
|
40456
|
-
setStartSearchTerm("");
|
|
40457
|
-
setEndSearchTerm("");
|
|
40458
|
-
},
|
|
40459
|
-
disabled: !startTime || !endTime,
|
|
40460
|
-
className: `
|
|
40461
|
-
w-full px-4 py-2 text-sm font-semibold rounded-lg transition-all
|
|
40462
|
-
${startTime && endTime ? "bg-blue-600 text-white hover:bg-blue-700 active:scale-[0.98]" : "bg-slate-200 text-slate-400 cursor-not-allowed"}
|
|
40463
|
-
`,
|
|
40464
|
-
children: "Apply"
|
|
40465
|
-
}
|
|
40466
|
-
) })
|
|
40726
|
+
] }) })
|
|
40467
40727
|
]
|
|
40468
40728
|
}
|
|
40469
40729
|
)
|
|
40470
40730
|
] }),
|
|
40471
40731
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-4 py-3 flex-1 min-h-0 overflow-y-auto scrollbar-thin", children: [
|
|
40472
40732
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: filterTree.map((node) => renderNode(node)) }),
|
|
40473
|
-
filterTree.length === 0 &&
|
|
40733
|
+
filterTree.length === 0 && (startTime || endTime) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
40474
40734
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "h-12 w-12 mx-auto" }) }),
|
|
40475
40735
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips found" }),
|
|
40476
40736
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500 mb-4", children: "No clips match the selected time range" }),
|
|
@@ -40480,18 +40740,19 @@ var FileManagerFilters = ({
|
|
|
40480
40740
|
onClick: () => {
|
|
40481
40741
|
setStartTime("");
|
|
40482
40742
|
setEndTime("");
|
|
40743
|
+
setIsTimeFilterActive(false);
|
|
40483
40744
|
},
|
|
40484
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",
|
|
40485
40746
|
children: "Clear time filter"
|
|
40486
40747
|
}
|
|
40487
40748
|
)
|
|
40488
40749
|
] }),
|
|
40489
|
-
filterTree.length === 0 && !
|
|
40750
|
+
filterTree.length === 0 && !startTime && !endTime && categories.length === 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
40490
40751
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HelpCircle, { className: "h-12 w-12 mx-auto" }) }),
|
|
40491
40752
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clip types available" }),
|
|
40492
40753
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500", children: "Loading clip categories..." })
|
|
40493
40754
|
] }),
|
|
40494
|
-
filterTree.length === 0 && !
|
|
40755
|
+
filterTree.length === 0 && !startTime && !endTime && categories.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-12", children: [
|
|
40495
40756
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-slate-300 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { className: "h-12 w-12 mx-auto" }) }),
|
|
40496
40757
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-slate-700 mb-2", children: "No clips available" }),
|
|
40497
40758
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-500", children: "No clips found for the selected time period" })
|
|
@@ -40895,6 +41156,34 @@ function useClipsRealtimeUpdates({
|
|
|
40895
41156
|
hasNewClips: newClipsNotification !== null && newClipsNotification.count > 0
|
|
40896
41157
|
};
|
|
40897
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
|
+
};
|
|
40898
41187
|
var BottlenecksContent = ({
|
|
40899
41188
|
workspaceId,
|
|
40900
41189
|
workspaceName,
|
|
@@ -41635,6 +41924,10 @@ var BottlenecksContent = ({
|
|
|
41635
41924
|
classificationUpdates[clipId] = {
|
|
41636
41925
|
status,
|
|
41637
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,
|
|
41638
41931
|
confidence: clip.classification_confidence ?? void 0
|
|
41639
41932
|
};
|
|
41640
41933
|
});
|
|
@@ -42419,79 +42712,13 @@ var BottlenecksContent = ({
|
|
|
42419
42712
|
return () => window.removeEventListener("keydown", handleEscape);
|
|
42420
42713
|
}
|
|
42421
42714
|
}, [isFullscreen, exitFullscreen]);
|
|
42422
|
-
const
|
|
42423
|
-
"Machine Breakdown": {
|
|
42424
|
-
color: "text-white",
|
|
42425
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42426
|
-
borderColor: "border-transparent",
|
|
42427
|
-
Icon: lucideReact.AlertTriangle,
|
|
42428
|
-
iconColor: "text-red-500",
|
|
42429
|
-
// Standard red for high visibility on dark
|
|
42430
|
-
dotColor: "bg-red-600"
|
|
42431
|
-
},
|
|
42432
|
-
"Other": {
|
|
42433
|
-
color: "text-white",
|
|
42434
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42435
|
-
borderColor: "border-transparent",
|
|
42436
|
-
Icon: lucideReact.HelpCircle,
|
|
42437
|
-
iconColor: "text-gray-400",
|
|
42438
|
-
dotColor: "bg-gray-500"
|
|
42439
|
-
},
|
|
42440
|
-
"Power Outage": {
|
|
42441
|
-
color: "text-white",
|
|
42442
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42443
|
-
borderColor: "border-transparent",
|
|
42444
|
-
Icon: lucideReact.Zap,
|
|
42445
|
-
iconColor: "text-red-400",
|
|
42446
|
-
// Lighter red
|
|
42447
|
-
dotColor: "bg-red-500"
|
|
42448
|
-
},
|
|
42449
|
-
"Worker Absent": {
|
|
42450
|
-
color: "text-white",
|
|
42451
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42452
|
-
borderColor: "border-transparent",
|
|
42453
|
-
Icon: lucideReact.UserX,
|
|
42454
|
-
iconColor: "text-red-400",
|
|
42455
|
-
// Lighter red
|
|
42456
|
-
dotColor: "bg-red-500"
|
|
42457
|
-
},
|
|
42458
|
-
"Material Shortage": {
|
|
42459
|
-
color: "text-white",
|
|
42460
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42461
|
-
borderColor: "border-transparent",
|
|
42462
|
-
Icon: lucideReact.Package,
|
|
42463
|
-
iconColor: "text-red-300",
|
|
42464
|
-
// Even lighter red
|
|
42465
|
-
dotColor: "bg-red-400"
|
|
42466
|
-
},
|
|
42467
|
-
"Quality Issue": {
|
|
42468
|
-
color: "text-white",
|
|
42469
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42470
|
-
borderColor: "border-transparent",
|
|
42471
|
-
Icon: lucideReact.XCircle,
|
|
42472
|
-
iconColor: "text-red-300",
|
|
42473
|
-
// Even lighter red
|
|
42474
|
-
dotColor: "bg-red-400"
|
|
42475
|
-
},
|
|
42476
|
-
"Scheduled Maintenance": {
|
|
42477
|
-
color: "text-white",
|
|
42478
|
-
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42479
|
-
borderColor: "border-transparent",
|
|
42480
|
-
Icon: lucideReact.Wrench,
|
|
42481
|
-
iconColor: "text-red-200",
|
|
42482
|
-
// Very light red
|
|
42483
|
-
dotColor: "bg-red-300"
|
|
42484
|
-
}
|
|
42485
|
-
};
|
|
42486
|
-
const getIdleTimeRootCause = React141.useCallback((video) => {
|
|
42715
|
+
const getIdleTimeClassification = React141.useCallback((video) => {
|
|
42487
42716
|
if (video.type !== "idle_time") return null;
|
|
42488
42717
|
const videoId = video.id || video.clipId;
|
|
42489
|
-
if (!videoId) return
|
|
42718
|
+
if (!videoId) return null;
|
|
42490
42719
|
const classification = clipClassifications[videoId];
|
|
42491
|
-
console.log(`[
|
|
42492
|
-
|
|
42493
|
-
if (classification.status === "processing") return "processing";
|
|
42494
|
-
return classification.label || "processing";
|
|
42720
|
+
console.log(`[getIdleTimeClassification] Looking up ${videoId}: `, classification);
|
|
42721
|
+
return classification || null;
|
|
42495
42722
|
}, [clipClassifications]);
|
|
42496
42723
|
const getIdleTimeConfidence = React141.useCallback((video) => {
|
|
42497
42724
|
if (video.type !== "idle_time") return null;
|
|
@@ -42502,36 +42729,35 @@ var BottlenecksContent = ({
|
|
|
42502
42729
|
if (classification.status === "processing") return null;
|
|
42503
42730
|
return classification.confidence ?? null;
|
|
42504
42731
|
}, [clipClassifications]);
|
|
42505
|
-
const
|
|
42506
|
-
|
|
42507
|
-
}, []);
|
|
42508
|
-
const getRootCauseConfig = React141.useCallback((rootCause) => {
|
|
42509
|
-
if (!rootCause) return null;
|
|
42510
|
-
if (rootCause === "processing") {
|
|
42732
|
+
const getRootCauseConfig = React141.useCallback((classification) => {
|
|
42733
|
+
if (!classification || classification.status === "processing") {
|
|
42511
42734
|
return {
|
|
42512
42735
|
color: "text-white",
|
|
42513
42736
|
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42514
|
-
borderColor: "border-
|
|
42737
|
+
borderColor: "border-white/10",
|
|
42515
42738
|
Icon: lucideReact.Clock,
|
|
42516
|
-
iconColor: "text-purple-
|
|
42517
|
-
dotColor: "bg-
|
|
42739
|
+
iconColor: "text-purple-300",
|
|
42740
|
+
dotColor: "bg-purple-400",
|
|
42518
42741
|
displayName: "Analyzing..."
|
|
42519
42742
|
};
|
|
42520
42743
|
}
|
|
42521
|
-
const
|
|
42522
|
-
|
|
42523
|
-
|
|
42524
|
-
|
|
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
|
+
});
|
|
42525
42751
|
return {
|
|
42526
42752
|
color: "text-white",
|
|
42527
42753
|
bgColor: "bg-black/60 backdrop-blur-sm",
|
|
42528
|
-
borderColor: "border-
|
|
42529
|
-
Icon:
|
|
42530
|
-
iconColor:
|
|
42531
|
-
dotColor:
|
|
42532
|
-
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
|
|
42533
42759
|
};
|
|
42534
|
-
}, [
|
|
42760
|
+
}, []);
|
|
42535
42761
|
const getClipTypeLabel = React141.useCallback((video) => {
|
|
42536
42762
|
if (!video) return "";
|
|
42537
42763
|
const currentFilter = activeFilterRef.current;
|
|
@@ -42696,15 +42922,15 @@ var BottlenecksContent = ({
|
|
|
42696
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" ? (
|
|
42697
42923
|
// Show full colored badge for idle time
|
|
42698
42924
|
(() => {
|
|
42699
|
-
const
|
|
42925
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42700
42926
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42701
|
-
const config = getRootCauseConfig(
|
|
42927
|
+
const config = getRootCauseConfig(classification);
|
|
42702
42928
|
if (!config) return null;
|
|
42703
42929
|
const IconComponent = config.Icon;
|
|
42704
42930
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
42705
|
-
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
|
|
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: 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..." })
|
|
42708
42934
|
] }) }),
|
|
42709
42935
|
idleTimeVlmEnabled && confidence !== null && (() => {
|
|
42710
42936
|
const confidencePercent = confidence * 100;
|
|
@@ -42739,9 +42965,9 @@ var BottlenecksContent = ({
|
|
|
42739
42965
|
currentVideo.type === "idle_time" ? (
|
|
42740
42966
|
// Show full colored badge for idle time
|
|
42741
42967
|
(() => {
|
|
42742
|
-
const
|
|
42968
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42743
42969
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42744
|
-
const config = getRootCauseConfig(
|
|
42970
|
+
const config = getRootCauseConfig(classification);
|
|
42745
42971
|
if (!config) return null;
|
|
42746
42972
|
const IconComponent = config.Icon;
|
|
42747
42973
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -42750,9 +42976,9 @@ var BottlenecksContent = ({
|
|
|
42750
42976
|
(confidence * 100).toFixed(0),
|
|
42751
42977
|
"%"
|
|
42752
42978
|
] }) }) }),
|
|
42753
|
-
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
|
|
42754
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-3.5 w-3.5 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42755
|
-
/* @__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..." })
|
|
42756
42982
|
] }) })
|
|
42757
42983
|
] });
|
|
42758
42984
|
})()
|
|
@@ -42792,6 +43018,7 @@ var BottlenecksContent = ({
|
|
|
42792
43018
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "No clips found" })
|
|
42793
43019
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: triageClips.map((clip, index) => {
|
|
42794
43020
|
const isIdleTime = clip.categoryId === "idle_time";
|
|
43021
|
+
const cycleItemCount = getMultiCycleItemCount(clip);
|
|
42795
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", {
|
|
42796
43023
|
hour12: true,
|
|
42797
43024
|
hour: "numeric",
|
|
@@ -42844,15 +43071,15 @@ var BottlenecksContent = ({
|
|
|
42844
43071
|
// Idle time clips - show root cause label below time
|
|
42845
43072
|
(() => {
|
|
42846
43073
|
const clipId = clip.id || clip.clipId;
|
|
42847
|
-
const
|
|
43074
|
+
const classification = getIdleTimeClassification({
|
|
42848
43075
|
id: clipId,
|
|
42849
43076
|
type: "idle_time",
|
|
42850
43077
|
creation_timestamp: clip.clip_timestamp
|
|
42851
43078
|
});
|
|
42852
|
-
console.log(`[BottlenecksContent] Sidebar clip ${clipId}:
|
|
42853
|
-
const config = getRootCauseConfig(
|
|
43079
|
+
console.log(`[BottlenecksContent] Sidebar clip ${clipId}: classification=`, clipClassifications[clipId]);
|
|
43080
|
+
const config = getRootCauseConfig(classification);
|
|
42854
43081
|
if (!config) {
|
|
42855
|
-
console.log(`[BottlenecksContent] No config found for
|
|
43082
|
+
console.log(`[BottlenecksContent] No config found for classification on clip: ${clipId}`);
|
|
42856
43083
|
return null;
|
|
42857
43084
|
}
|
|
42858
43085
|
const IconComponent = config.Icon;
|
|
@@ -42867,7 +43094,7 @@ var BottlenecksContent = ({
|
|
|
42867
43094
|
] }) })
|
|
42868
43095
|
] }),
|
|
42869
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: (() => {
|
|
42870
|
-
const displayText = config.displayName ||
|
|
43097
|
+
const displayText = config.displayName || "Analyzing...";
|
|
42871
43098
|
console.log(`[BottlenecksContent] Displaying label: "${displayText}" for clip ${clipId}`);
|
|
42872
43099
|
return displayText;
|
|
42873
43100
|
})() }) : (() => {
|
|
@@ -42887,7 +43114,13 @@ var BottlenecksContent = ({
|
|
|
42887
43114
|
clip.duration ? `${clip.duration.toFixed(1)}s` : "N/A",
|
|
42888
43115
|
")"
|
|
42889
43116
|
] }) }),
|
|
42890
|
-
/* @__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
|
+
] })
|
|
42891
43124
|
] })
|
|
42892
43125
|
)
|
|
42893
43126
|
},
|
|
@@ -42980,15 +43213,15 @@ var BottlenecksContent = ({
|
|
|
42980
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" ? (
|
|
42981
43214
|
// Show full colored badge for idle time
|
|
42982
43215
|
(() => {
|
|
42983
|
-
const
|
|
43216
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
42984
43217
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
42985
|
-
const config = getRootCauseConfig(
|
|
43218
|
+
const config = getRootCauseConfig(classification);
|
|
42986
43219
|
if (!config) return null;
|
|
42987
43220
|
const IconComponent = config.Icon;
|
|
42988
43221
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
42989
|
-
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
|
|
42990
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-4 w-4 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
42991
|
-
/* @__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..." })
|
|
42992
43225
|
] }) }),
|
|
42993
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: [
|
|
42994
43227
|
"AI Confidence: ",
|
|
@@ -43010,9 +43243,9 @@ var BottlenecksContent = ({
|
|
|
43010
43243
|
] }) }) : currentVideo.type === "idle_time" ? (
|
|
43011
43244
|
// Show full colored badge for idle time
|
|
43012
43245
|
(() => {
|
|
43013
|
-
const
|
|
43246
|
+
const classification = getIdleTimeClassification(currentVideo);
|
|
43014
43247
|
const confidence = getIdleTimeConfidence(currentVideo);
|
|
43015
|
-
const config = getRootCauseConfig(
|
|
43248
|
+
const config = getRootCauseConfig(classification);
|
|
43016
43249
|
if (!config) return null;
|
|
43017
43250
|
const IconComponent = config.Icon;
|
|
43018
43251
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -43021,9 +43254,9 @@ var BottlenecksContent = ({
|
|
|
43021
43254
|
(confidence * 100).toFixed(0),
|
|
43022
43255
|
"%"
|
|
43023
43256
|
] }) }) }),
|
|
43024
|
-
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
|
|
43025
|
-
/* @__PURE__ */ jsxRuntime.jsx(IconComponent, { className: `h-4 w-4 ${config.iconColor}`, strokeWidth: 2.5 }),
|
|
43026
|
-
/* @__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..." })
|
|
43027
43260
|
] }) })
|
|
43028
43261
|
] });
|
|
43029
43262
|
})()
|
|
@@ -44972,16 +45205,6 @@ var LineHistoryCalendar = ({
|
|
|
44972
45205
|
] });
|
|
44973
45206
|
};
|
|
44974
45207
|
var LineHistoryCalendar_default = LineHistoryCalendar;
|
|
44975
|
-
var STATIC_COLORS = {
|
|
44976
|
-
"Operator Absent": "#dc2626",
|
|
44977
|
-
// red-600 - Critical/Urgent
|
|
44978
|
-
"No Material": "#f59e0b",
|
|
44979
|
-
// amber-500 - Warning/Supply Chain
|
|
44980
|
-
"Machine Downtime": "#3b82f6",
|
|
44981
|
-
// blue-500 - Scheduled/Technical
|
|
44982
|
-
"Operator Idle": "#8b5cf6"
|
|
44983
|
-
// violet-500 - Low Priority/Behavioral
|
|
44984
|
-
};
|
|
44985
45208
|
var PRODUCTIVE_COLOR = "#00AB45";
|
|
44986
45209
|
var IDLE_COLOR = "#e5e7eb";
|
|
44987
45210
|
var formatDuration = (seconds) => {
|
|
@@ -45004,19 +45227,21 @@ var formatDuration = (seconds) => {
|
|
|
45004
45227
|
}
|
|
45005
45228
|
return parts.join(" ");
|
|
45006
45229
|
};
|
|
45007
|
-
var getColorForEntry = (
|
|
45008
|
-
const normalized = name.trim().toLowerCase();
|
|
45230
|
+
var getColorForEntry = (entry) => {
|
|
45231
|
+
const normalized = entry.name.trim().toLowerCase();
|
|
45009
45232
|
if (normalized === "productive" || normalized === "productive time") {
|
|
45010
45233
|
return PRODUCTIVE_COLOR;
|
|
45011
45234
|
}
|
|
45012
45235
|
if (normalized === "idle" || normalized === "idle time") {
|
|
45013
45236
|
return IDLE_COLOR;
|
|
45014
45237
|
}
|
|
45015
|
-
|
|
45016
|
-
|
|
45017
|
-
|
|
45018
|
-
|
|
45019
|
-
|
|
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
|
+
});
|
|
45020
45245
|
};
|
|
45021
45246
|
var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
|
|
45022
45247
|
if (active && payload && payload.length) {
|
|
@@ -45030,8 +45255,8 @@ var CustomTooltip = ({ active, payload, hideTotalDuration }) => {
|
|
|
45030
45255
|
const hasContributors = contributors.length > 0;
|
|
45031
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: [
|
|
45032
45257
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 pb-2 mb-2 border-b border-slate-100", children: [
|
|
45033
|
-
/* @__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].
|
|
45034
|
-
/* @__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, " ") })
|
|
45035
45260
|
] }),
|
|
45036
45261
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1.5 pb-1", children: [
|
|
45037
45262
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center gap-4", children: [
|
|
@@ -45092,7 +45317,8 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45092
45317
|
isLoading = false,
|
|
45093
45318
|
error = null,
|
|
45094
45319
|
hideTotalDuration = false,
|
|
45095
|
-
updateAnimation = "replay"
|
|
45320
|
+
updateAnimation = "replay",
|
|
45321
|
+
variant = "pie"
|
|
45096
45322
|
}) => {
|
|
45097
45323
|
const [activeData, setActiveData] = React141__namespace.default.useState([]);
|
|
45098
45324
|
React141__namespace.default.useEffect(() => {
|
|
@@ -45137,6 +45363,73 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45137
45363
|
if (!data || data.length === 0) {
|
|
45138
45364
|
return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { message: "No Idle Time reasons available" });
|
|
45139
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
|
+
}
|
|
45140
45433
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
45141
45434
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `
|
|
45142
45435
|
.recharts-wrapper:focus,
|
|
@@ -45198,7 +45491,7 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45198
45491
|
children: activeData.map((entry, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
45199
45492
|
recharts.Cell,
|
|
45200
45493
|
{
|
|
45201
|
-
fill: getColorForEntry(entry
|
|
45494
|
+
fill: getColorForEntry(entry),
|
|
45202
45495
|
strokeWidth: 0
|
|
45203
45496
|
},
|
|
45204
45497
|
`cell-${index}`
|
|
@@ -45215,10 +45508,10 @@ var IdleTimeReasonChartComponent = ({
|
|
|
45215
45508
|
"span",
|
|
45216
45509
|
{
|
|
45217
45510
|
className: "inline-block w-2.5 h-2.5 rounded-full mr-1.5 mt-0.5 flex-shrink-0",
|
|
45218
|
-
style: { backgroundColor: getColorForEntry(entry
|
|
45511
|
+
style: { backgroundColor: getColorForEntry(entry) }
|
|
45219
45512
|
}
|
|
45220
45513
|
),
|
|
45221
|
-
/* @__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, " ") })
|
|
45222
45515
|
] }, `item-${index}`)) }) })
|
|
45223
45516
|
]
|
|
45224
45517
|
}
|
|
@@ -45343,7 +45636,6 @@ var LineMonthlyHistory = ({
|
|
|
45343
45636
|
const { isIdleTimeVlmEnabled } = useIdleTimeVlmConfig();
|
|
45344
45637
|
const idleTimeVlmEnabled = isIdleTimeVlmEnabled(lineId);
|
|
45345
45638
|
const isUptimeMode = monitoringMode === "uptime";
|
|
45346
|
-
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
45347
45639
|
const chartKey = React141.useMemo(() => `${lineId}-${month}-${year}-${selectedShiftId}-${rangeStart}-${rangeEnd}`, [lineId, month, year, selectedShiftId, rangeStart, rangeEnd]);
|
|
45348
45640
|
const monthBounds = React141.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
45349
45641
|
const normalizedRange = React141.useMemo(() => {
|
|
@@ -45391,20 +45683,20 @@ var LineMonthlyHistory = ({
|
|
|
45391
45683
|
{ efficiency: 0, underperforming: 0, totalWorkspaces: 0, count: 0 }
|
|
45392
45684
|
);
|
|
45393
45685
|
const avgEfficiency = averages.count > 0 ? averages.efficiency / averages.count : 0;
|
|
45394
|
-
const
|
|
45686
|
+
const outputAverages = (analysisMonthlyData || []).reduce(
|
|
45395
45687
|
(acc, day) => {
|
|
45396
45688
|
const shiftData = getShiftData2(day, selectedShiftId);
|
|
45397
45689
|
if (!shiftData || !hasRealData(shiftData)) {
|
|
45398
45690
|
return acc;
|
|
45399
45691
|
}
|
|
45400
|
-
const status = getEfficiencyColor(shiftData.avg_efficiency || 0, effectiveLegend);
|
|
45401
45692
|
return {
|
|
45402
|
-
|
|
45403
|
-
|
|
45693
|
+
output: acc.output + (shiftData.output || 0),
|
|
45694
|
+
count: acc.count + 1
|
|
45404
45695
|
};
|
|
45405
45696
|
},
|
|
45406
|
-
{
|
|
45697
|
+
{ output: 0, count: 0 }
|
|
45407
45698
|
);
|
|
45699
|
+
const avgOutput = outputAverages.count > 0 ? outputAverages.output / outputAverages.count : 0;
|
|
45408
45700
|
const uptimeSummary = React141.useMemo(() => {
|
|
45409
45701
|
if (!isUptimeMode) return null;
|
|
45410
45702
|
const validDays = (analysisMonthlyData || []).map((day) => getShiftData2(day, selectedShiftId)).filter((shiftData) => shiftData && hasRealData(shiftData)).map((shiftData) => ({ shiftData, totals: getUptimeTotals(shiftData) }));
|
|
@@ -45437,6 +45729,10 @@ var LineMonthlyHistory = ({
|
|
|
45437
45729
|
const efficiencyImproved = efficiencyDelta >= 0;
|
|
45438
45730
|
const EfficiencyTrendIcon = efficiencyImproved ? lucideReact.ArrowUp : lucideReact.ArrowDown;
|
|
45439
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)}%`;
|
|
45440
45736
|
const utilizationDelta = efficiencyDelta;
|
|
45441
45737
|
const utilizationImproved = utilizationDelta >= 0;
|
|
45442
45738
|
const UtilizationTrendIcon = utilizationImproved ? lucideReact.ArrowUp : lucideReact.ArrowDown;
|
|
@@ -45721,12 +46017,17 @@ var LineMonthlyHistory = ({
|
|
|
45721
46017
|
] })
|
|
45722
46018
|
] }),
|
|
45723
46019
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
45724
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-bold text-gray-700 mb-2", children: "
|
|
45725
|
-
/* @__PURE__ */ jsxRuntime.
|
|
45726
|
-
|
|
45727
|
-
"
|
|
45728
|
-
|
|
45729
|
-
|
|
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
|
+
] })
|
|
45730
46031
|
] })
|
|
45731
46032
|
] }),
|
|
45732
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: [
|
|
@@ -46245,11 +46546,6 @@ var LineMonthlyPdfGenerator = ({
|
|
|
46245
46546
|
doc.text("Working Days:", 25, kpiStartY + kpiSpacing * 2);
|
|
46246
46547
|
doc.setFont("helvetica", "bold");
|
|
46247
46548
|
doc.text(`${outputMetrics.totalDays} days`, 120, kpiStartY + kpiSpacing * 2);
|
|
46248
|
-
createKPIBox(kpiStartY + kpiSpacing * 3);
|
|
46249
|
-
doc.setFont("helvetica", "normal");
|
|
46250
|
-
doc.text("Underperforming Days:", 25, kpiStartY + kpiSpacing * 3);
|
|
46251
|
-
doc.setFont("helvetica", "bold");
|
|
46252
|
-
doc.text(`${outputMetrics.underperformingDays} of ${outputMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 3);
|
|
46253
46549
|
}
|
|
46254
46550
|
} else {
|
|
46255
46551
|
doc.setFontSize(12);
|
|
@@ -47827,7 +48123,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
47827
48123
|
availableShifts,
|
|
47828
48124
|
monthlyDataLoading = false,
|
|
47829
48125
|
className = "",
|
|
47830
|
-
trendSummary
|
|
48126
|
+
trendSummary,
|
|
48127
|
+
isAssemblyWorkspace = false
|
|
47831
48128
|
}) => {
|
|
47832
48129
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
47833
48130
|
const isUptimeMode = monitoringMode === "uptime";
|
|
@@ -48066,12 +48363,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48066
48363
|
}, [analysisMonthlyData, selectedShiftId, isUptimeMode, shiftWorkSeconds]);
|
|
48067
48364
|
const efficiencyDelta = trendSummary?.avg_efficiency?.delta_pp ?? 0;
|
|
48068
48365
|
const efficiencyImproved = efficiencyDelta >= 0;
|
|
48069
|
-
const outputDeltaRaw = trendSummary?.avg_daily_output?.delta_pp ?? 0;
|
|
48070
48366
|
const cycleDeltaRaw = trendSummary?.avg_cycle_time?.delta_seconds ?? 0;
|
|
48071
|
-
const outputPrev = trendSummary?.avg_daily_output?.previous ?? 0;
|
|
48072
48367
|
const cyclePrev = trendSummary?.avg_cycle_time?.previous ?? 0;
|
|
48073
|
-
const outputDelta = outputPrev ? outputDeltaRaw / outputPrev * 100 : 0;
|
|
48074
|
-
const outputImproved = outputDelta >= 0;
|
|
48075
48368
|
const cycleDelta = cyclePrev ? cycleDeltaRaw / cyclePrev * 100 : 0;
|
|
48076
48369
|
const cycleWorsened = cycleDelta > 0;
|
|
48077
48370
|
const utilizationDelta = efficiencyDelta;
|
|
@@ -48151,7 +48444,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48151
48444
|
shift.id
|
|
48152
48445
|
)) }) }),
|
|
48153
48446
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6", children: [
|
|
48154
|
-
/* @__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: [
|
|
48155
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)) }),
|
|
48156
48449
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-7 gap-2 mt-6", children: calendarData.calendar.map((day, index) => {
|
|
48157
48450
|
const dayNumber = index >= calendarData.startOffset ? index - calendarData.startOffset + 1 : null;
|
|
@@ -48239,8 +48532,32 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48239
48532
|
) }, index);
|
|
48240
48533
|
}) })
|
|
48241
48534
|
] }),
|
|
48242
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
48243
|
-
/* @__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: [
|
|
48244
48561
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48245
48562
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-600 mb-1", children: isUptimeMode ? "Avg Utilization" : "Avg Efficiency" }),
|
|
48246
48563
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
@@ -48254,16 +48571,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48254
48571
|
] })
|
|
48255
48572
|
] })
|
|
48256
48573
|
] }),
|
|
48257
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-lg shadow-sm border border-gray-100 p-4 flex flex-col justify-between", children: [
|
|
48258
|
-
/* @__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" }),
|
|
48259
48576
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-nowrap", children: [
|
|
48260
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-2xl font-bold text-gray-900", children:
|
|
48261
|
-
|
|
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: [
|
|
48262
48579
|
idleImproved ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "w-3 h-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-3 h-3" }),
|
|
48263
48580
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: idleTrendText })
|
|
48264
|
-
] }) : /* @__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: [
|
|
48265
|
-
outputImproved ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "w-3 h-3" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDown, { className: "w-3 h-3" }),
|
|
48266
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: `${Math.abs(outputDelta).toFixed(1)}% vs last month` })
|
|
48267
48581
|
] })
|
|
48268
48582
|
] })
|
|
48269
48583
|
] }),
|
|
@@ -48285,9 +48599,9 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48285
48599
|
] })
|
|
48286
48600
|
] }),
|
|
48287
48601
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `grid grid-cols-1 ${idleTimeVlmEnabled ? "sm:grid-cols-2" : "sm:grid-cols-1"} gap-4`, children: [
|
|
48288
|
-
/* @__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: [
|
|
48289
48603
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: isUptimeMode ? "Utilization" : "Time Utilization" }),
|
|
48290
|
-
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: [
|
|
48291
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: [
|
|
48292
48606
|
/* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsx(recharts.PieChart, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
48293
48607
|
recharts.Pie,
|
|
@@ -48360,7 +48674,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48360
48674
|
] }) })
|
|
48361
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" }) })
|
|
48362
48676
|
] }),
|
|
48363
|
-
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: [
|
|
48364
48678
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: "Idle Time Breakdown" }),
|
|
48365
48679
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[160px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
48366
48680
|
IdleTimeReasonChart,
|
|
@@ -48372,7 +48686,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
48372
48686
|
) })
|
|
48373
48687
|
] })
|
|
48374
48688
|
] }),
|
|
48375
|
-
/* @__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: [
|
|
48376
48690
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700 mb-3 text-left", children: isUptimeMode ? "Daily Utilization" : "Daily Output" }),
|
|
48377
48691
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height: "220px" }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
48378
48692
|
recharts.BarChart,
|
|
@@ -48570,7 +48884,7 @@ var WorkspaceWhatsAppShareButton = ({
|
|
|
48570
48884
|
}
|
|
48571
48885
|
);
|
|
48572
48886
|
};
|
|
48573
|
-
var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiencyLegend }) => {
|
|
48887
|
+
var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiencyLegend, hourlyCycleTimes }) => {
|
|
48574
48888
|
const [isGenerating, setIsGenerating] = React141.useState(false);
|
|
48575
48889
|
const entityConfig = useEntityConfig();
|
|
48576
48890
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
@@ -48578,6 +48892,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48578
48892
|
setIsGenerating(true);
|
|
48579
48893
|
try {
|
|
48580
48894
|
const isUptimeMode = workspace.monitoring_mode === "uptime";
|
|
48895
|
+
const isAssemblyCycleMode = !isUptimeMode && workspace.line_assembly_enabled === true && workspace.action_type === "assembly";
|
|
48581
48896
|
const shiftMinutes = getShiftDurationMinutes(workspace.shift_start, workspace.shift_end);
|
|
48582
48897
|
const shiftSeconds = shiftMinutes ? shiftMinutes * 60 : 0;
|
|
48583
48898
|
const idleSeconds = Math.max(workspace.idle_time || 0, 0);
|
|
@@ -48638,9 +48953,38 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48638
48953
|
minute: "2-digit",
|
|
48639
48954
|
hour12: true
|
|
48640
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;
|
|
48641
48985
|
doc.setFontSize(12);
|
|
48642
48986
|
doc.setTextColor(80, 80, 80);
|
|
48643
|
-
doc.text(`Report Period: ${shiftStartTime} - ${
|
|
48987
|
+
doc.text(`Report Period: ${shiftStartTime} - ${reportPeriodEndTime}`, 20, 79);
|
|
48644
48988
|
doc.setTextColor(0, 0, 0);
|
|
48645
48989
|
doc.setDrawColor(180, 180, 180);
|
|
48646
48990
|
doc.setLineWidth(0.8);
|
|
@@ -48654,10 +48998,8 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48654
48998
|
};
|
|
48655
48999
|
const perfOverviewStartY = 93;
|
|
48656
49000
|
const hasIdleTimeReason = idleTimeReasons && idleTimeReasons.length > 0;
|
|
48657
|
-
|
|
48658
|
-
|
|
48659
|
-
perfOverviewHeight = hasIdleTimeReason ? 70 : 60;
|
|
48660
|
-
}
|
|
49001
|
+
const perfOverviewRows = isUptimeMode ? 3 : isAssemblyCycleMode ? 2 : 4;
|
|
49002
|
+
const perfOverviewHeight = 30 + perfOverviewRows * 10 + (hasIdleTimeReason ? 10 : 0);
|
|
48661
49003
|
doc.setFillColor(245, 245, 245);
|
|
48662
49004
|
doc.roundedRect(15, perfOverviewStartY, 180, perfOverviewHeight, 3, 3, "F");
|
|
48663
49005
|
doc.setFontSize(18);
|
|
@@ -48685,6 +49027,19 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48685
49027
|
doc.text("Stoppages:", 25, kpiStartY + kpiSpacing * 2);
|
|
48686
49028
|
doc.setFont("helvetica", "bold");
|
|
48687
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);
|
|
48688
49043
|
} else {
|
|
48689
49044
|
createKPIBox(kpiStartY);
|
|
48690
49045
|
doc.setFontSize(11);
|
|
@@ -48721,17 +49076,11 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48721
49076
|
const reasonText = `${reasonName} (${topReason.value.toFixed(1)}%)`;
|
|
48722
49077
|
doc.text(reasonText, 120, reasonY);
|
|
48723
49078
|
}
|
|
48724
|
-
|
|
48725
|
-
if (isUptimeMode) {
|
|
48726
|
-
separatorBeforeHourlyY -= 10;
|
|
48727
|
-
}
|
|
49079
|
+
const separatorBeforeHourlyY = perfOverviewStartY + perfOverviewHeight + 10;
|
|
48728
49080
|
doc.setDrawColor(180, 180, 180);
|
|
48729
49081
|
doc.setLineWidth(0.8);
|
|
48730
49082
|
doc.line(20, separatorBeforeHourlyY, 190, separatorBeforeHourlyY);
|
|
48731
|
-
|
|
48732
|
-
if (isUptimeMode) {
|
|
48733
|
-
hourlyPerfStartY -= 10;
|
|
48734
|
-
}
|
|
49083
|
+
const hourlyPerfStartY = separatorBeforeHourlyY + 5;
|
|
48735
49084
|
const uptimeSeries = isUptimeMode ? buildUptimeSeries({
|
|
48736
49085
|
idleTimeHourly: workspace.idle_time_hourly,
|
|
48737
49086
|
shiftStart: workspace.shift_start,
|
|
@@ -48749,8 +49098,9 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48749
49098
|
const uptimePercent = total > 0 ? Math.round(activeMinutes / total * 100) : 0;
|
|
48750
49099
|
return { activeMinutes, idleMinutes, uptimePercent };
|
|
48751
49100
|
}) : [];
|
|
48752
|
-
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 || [];
|
|
48753
49102
|
const hourlyTarget = workspace.pph_threshold;
|
|
49103
|
+
const cycleTarget = workspace.ideal_cycle_time || 0;
|
|
48754
49104
|
const pageHeight = doc.internal.pageSize.height;
|
|
48755
49105
|
const maxContentY = pageHeight - 15;
|
|
48756
49106
|
const baseTableStartY = hourlyPerfStartY + 31;
|
|
@@ -48775,12 +49125,16 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48775
49125
|
doc.setFont("helvetica", "bold");
|
|
48776
49126
|
doc.setTextColor(40, 40, 40);
|
|
48777
49127
|
const hourlyTitleY = hourlyPerfStartY + 10;
|
|
48778
|
-
doc.text(
|
|
49128
|
+
doc.text(
|
|
49129
|
+
isUptimeMode ? "Hourly Utilization" : isAssemblyCycleMode ? "Hourly Cycle Time" : "Hourly Performance",
|
|
49130
|
+
20,
|
|
49131
|
+
hourlyTitleY
|
|
49132
|
+
);
|
|
48779
49133
|
doc.setTextColor(0, 0, 0);
|
|
48780
49134
|
const headerY = titleFontSize === 16 ? hourlyPerfStartY + 18 : hourlyPerfStartY + 20;
|
|
48781
49135
|
const gridTopY = headerY - 5;
|
|
48782
49136
|
const headerBottomY = gridTopY + 8;
|
|
48783
|
-
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];
|
|
48784
49138
|
const totalRows = hourlyData.length;
|
|
48785
49139
|
const gridBottomY = headerBottomY + totalRows * rowHeight;
|
|
48786
49140
|
const tableHeight = gridBottomY - gridTopY;
|
|
@@ -48801,6 +49155,10 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48801
49155
|
doc.text("Time Range", 25, headerTextY);
|
|
48802
49156
|
if (isUptimeMode) {
|
|
48803
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);
|
|
48804
49162
|
} else {
|
|
48805
49163
|
doc.text("Output", 75, headerTextY);
|
|
48806
49164
|
doc.text("Target", 105, headerTextY);
|
|
@@ -48849,6 +49207,25 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48849
49207
|
if (isUptimeMode) {
|
|
48850
49208
|
const utilizationStr = dataCollected ? `${uptimePercent}%` : "TBD";
|
|
48851
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);
|
|
48852
49229
|
} else {
|
|
48853
49230
|
doc.text(outputStr, 75, yPos);
|
|
48854
49231
|
doc.text(targetStr, 105, yPos);
|
|
@@ -48920,7 +49297,8 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
48920
49297
|
shiftConfig,
|
|
48921
49298
|
efficiencyLegend,
|
|
48922
49299
|
className,
|
|
48923
|
-
compact = false
|
|
49300
|
+
compact = false,
|
|
49301
|
+
isAssemblyWorkspace = false
|
|
48924
49302
|
}) => {
|
|
48925
49303
|
const [isGenerating, setIsGenerating] = React141.useState(false);
|
|
48926
49304
|
const effectiveLegend = efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
@@ -49043,6 +49421,7 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49043
49421
|
avgOutput: filteredShifts.reduce((sum, shift) => sum + shift.output, 0) / filteredShifts.length,
|
|
49044
49422
|
avgCycleTime: filteredShifts.reduce((sum, shift) => sum + shift.cycleTime, 0) / filteredShifts.length,
|
|
49045
49423
|
avgPph: filteredShifts.reduce((sum, shift) => sum + shift.pph, 0) / filteredShifts.length,
|
|
49424
|
+
avgIdleTime: filteredShifts.reduce((sum, shift) => sum + shift.idleTime, 0) / filteredShifts.length,
|
|
49046
49425
|
totalDays: filteredShifts.length,
|
|
49047
49426
|
underperformingDays: filteredShifts.filter((shift) => shift.efficiency < effectiveLegend.green_min).length
|
|
49048
49427
|
} : null;
|
|
@@ -49054,7 +49433,8 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49054
49433
|
doc.roundedRect(22, y - 7, 165, 12, 2, 2, "S");
|
|
49055
49434
|
};
|
|
49056
49435
|
doc.setFillColor(245, 245, 245);
|
|
49057
|
-
|
|
49436
|
+
const isAssemblyWorkspaceAndNotUptime = !isUptimeMode && isAssemblyWorkspace;
|
|
49437
|
+
doc.roundedRect(15, 95, 180, isAssemblyWorkspaceAndNotUptime ? 40 : 70, 3, 3, "F");
|
|
49058
49438
|
doc.setFontSize(18);
|
|
49059
49439
|
doc.setFont("helvetica", "bold");
|
|
49060
49440
|
doc.setTextColor(40, 40, 40);
|
|
@@ -49093,32 +49473,41 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49093
49473
|
doc.text(`${uptimeMetrics.underperformingDays} of ${uptimeMetrics.totalDays}`, 120, kpiStartY + kpiSpacing * 4);
|
|
49094
49474
|
} else {
|
|
49095
49475
|
const outputMetrics = monthlyMetrics;
|
|
49096
|
-
|
|
49097
|
-
|
|
49098
|
-
|
|
49099
|
-
|
|
49100
|
-
|
|
49101
|
-
|
|
49102
|
-
|
|
49103
|
-
|
|
49104
|
-
|
|
49105
|
-
|
|
49106
|
-
|
|
49107
|
-
|
|
49108
|
-
|
|
49109
|
-
|
|
49110
|
-
|
|
49111
|
-
|
|
49112
|
-
|
|
49113
|
-
|
|
49114
|
-
|
|
49115
|
-
|
|
49116
|
-
|
|
49117
|
-
|
|
49118
|
-
|
|
49119
|
-
|
|
49120
|
-
|
|
49121
|
-
|
|
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
|
+
}
|
|
49122
49511
|
}
|
|
49123
49512
|
} else {
|
|
49124
49513
|
doc.setFontSize(12);
|
|
@@ -49129,29 +49518,33 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49129
49518
|
}
|
|
49130
49519
|
doc.setDrawColor(180, 180, 180);
|
|
49131
49520
|
doc.setLineWidth(0.8);
|
|
49132
|
-
|
|
49521
|
+
const separatorY = isAssemblyWorkspaceAndNotUptime ? 150 : 180;
|
|
49522
|
+
doc.line(20, separatorY, 190, separatorY);
|
|
49133
49523
|
doc.setFillColor(245, 245, 245);
|
|
49134
|
-
|
|
49524
|
+
const dailySectionY = isAssemblyWorkspaceAndNotUptime ? 155 : 185;
|
|
49525
|
+
doc.roundedRect(15, dailySectionY, 180, 85, 3, 3, "F");
|
|
49135
49526
|
doc.setFontSize(18);
|
|
49136
49527
|
doc.setFont("helvetica", "bold");
|
|
49137
49528
|
doc.setTextColor(40, 40, 40);
|
|
49138
|
-
doc.text(isUptimeMode ? "Daily Utilization Summary" : "Daily Performance Summary", 20,
|
|
49529
|
+
doc.text(isUptimeMode ? "Daily Utilization Summary" : "Daily Performance Summary", 20, dailySectionY + 10);
|
|
49139
49530
|
doc.setTextColor(0, 0, 0);
|
|
49140
49531
|
if (validDays.length > 0) {
|
|
49141
49532
|
doc.setFontSize(10);
|
|
49142
49533
|
doc.setFont("helvetica", "bold");
|
|
49143
49534
|
doc.setFillColor(240, 240, 240);
|
|
49144
|
-
|
|
49145
|
-
doc.
|
|
49146
|
-
|
|
49147
|
-
doc.text(
|
|
49148
|
-
doc.text(isUptimeMode ? "
|
|
49149
|
-
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);
|
|
49150
49543
|
doc.setLineWidth(0.2);
|
|
49151
49544
|
doc.setDrawColor(220, 220, 220);
|
|
49152
|
-
doc.line(20,
|
|
49545
|
+
doc.line(20, textY + 3, 190, textY + 3);
|
|
49153
49546
|
doc.setFont("helvetica", "normal");
|
|
49154
|
-
let yPos =
|
|
49547
|
+
let yPos = textY + 10;
|
|
49155
49548
|
const recentDays = validDays.slice(-10).reverse();
|
|
49156
49549
|
recentDays.forEach((dayData, index) => {
|
|
49157
49550
|
if (yPos > 260) return;
|
|
@@ -49185,8 +49578,13 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49185
49578
|
}
|
|
49186
49579
|
doc.setTextColor(0, 0, 0);
|
|
49187
49580
|
} else {
|
|
49188
|
-
|
|
49189
|
-
|
|
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
|
+
}
|
|
49190
49588
|
doc.text(`${shift.efficiency.toFixed(1)}%`, 135, yPos);
|
|
49191
49589
|
if (shift.efficiency >= effectiveLegend.green_min) {
|
|
49192
49590
|
doc.setTextColor(0, 171, 69);
|
|
@@ -49201,12 +49599,12 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
49201
49599
|
});
|
|
49202
49600
|
doc.setLineWidth(0.2);
|
|
49203
49601
|
doc.setDrawColor(220, 220, 220);
|
|
49204
|
-
doc.roundedRect(20,
|
|
49602
|
+
doc.roundedRect(20, tableHeaderY, 170, yPos - tableHeaderY - 3, 1, 1, "S");
|
|
49205
49603
|
} else {
|
|
49206
49604
|
doc.setFontSize(12);
|
|
49207
49605
|
doc.setFont("helvetica", "normal");
|
|
49208
49606
|
doc.setTextColor(100, 100, 100);
|
|
49209
|
-
doc.text("No daily data available for this month", 25,
|
|
49607
|
+
doc.text("No daily data available for this month", 25, dailySectionY + 30);
|
|
49210
49608
|
doc.setTextColor(0, 0, 0);
|
|
49211
49609
|
}
|
|
49212
49610
|
doc.setFontSize(9);
|
|
@@ -49239,46 +49637,64 @@ var WorkspaceCycleTimeMetricCards = ({
|
|
|
49239
49637
|
workspace,
|
|
49240
49638
|
className,
|
|
49241
49639
|
legend,
|
|
49242
|
-
layout: layout2 = "grid"
|
|
49640
|
+
layout: layout2 = "grid",
|
|
49641
|
+
isAssemblyWorkspace = false,
|
|
49642
|
+
idleTimeData
|
|
49243
49643
|
}) => {
|
|
49244
49644
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
49245
49645
|
const efficiencyValue = workspace.avg_efficiency || 0;
|
|
49246
49646
|
const efficiencyTarget = effectiveLegend.green_min;
|
|
49247
49647
|
const efficiencyColor = getEfficiencyHexColor(efficiencyValue, effectiveLegend);
|
|
49248
|
-
const hideEfficiencyCard = shouldHideWorkspaceEfficiencyCard(workspace);
|
|
49249
|
-
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 || ""}`;
|
|
49250
49654
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: containerClassName, children: [
|
|
49251
|
-
!hideEfficiencyCard && /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
49252
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-
|
|
49253
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49254
|
-
/* @__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: [
|
|
49255
49659
|
efficiencyValue.toFixed(1),
|
|
49256
49660
|
"%"
|
|
49257
49661
|
] }),
|
|
49258
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-
|
|
49662
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-500 mt-1 font-medium tracking-wide", children: [
|
|
49259
49663
|
"Target: ",
|
|
49260
49664
|
Math.round(efficiencyTarget),
|
|
49261
49665
|
"%"
|
|
49262
49666
|
] })
|
|
49263
|
-
] })
|
|
49667
|
+
] })
|
|
49264
49668
|
] }),
|
|
49265
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
49266
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-
|
|
49267
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49268
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-
|
|
49269
|
-
/* @__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: [
|
|
49270
49674
|
"Standard: ",
|
|
49271
49675
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
49272
49676
|
"s"
|
|
49273
49677
|
] })
|
|
49274
|
-
] })
|
|
49678
|
+
] })
|
|
49275
49679
|
] }),
|
|
49276
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
49277
|
-
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-
|
|
49278
|
-
/* @__PURE__ */ jsxRuntime.
|
|
49279
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-
|
|
49280
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-
|
|
49281
|
-
] })
|
|
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
|
+
) })
|
|
49282
49698
|
] })
|
|
49283
49699
|
] });
|
|
49284
49700
|
};
|
|
@@ -49416,13 +49832,13 @@ var getWorkspaceStyles = (position, isPlaceholder = false) => {
|
|
|
49416
49832
|
${isPlaceholder ? "cursor-default" : ""}`;
|
|
49417
49833
|
};
|
|
49418
49834
|
var formatPercentRange = (min, max) => {
|
|
49419
|
-
const
|
|
49835
|
+
const format9 = (value) => Number.isInteger(value) ? `${value}` : value.toFixed(1);
|
|
49420
49836
|
if (min >= 100 || max >= 100) {
|
|
49421
|
-
return `${
|
|
49837
|
+
return `${format9(min)}+%`;
|
|
49422
49838
|
}
|
|
49423
|
-
return `${
|
|
49839
|
+
return `${format9(min)}-${format9(max)}%`;
|
|
49424
49840
|
};
|
|
49425
|
-
var
|
|
49841
|
+
var Legend5 = ({
|
|
49426
49842
|
useBottleneckLabel = false,
|
|
49427
49843
|
legend,
|
|
49428
49844
|
metricLabel = "Efficiency"
|
|
@@ -49608,7 +50024,7 @@ var WorkspaceGrid = React141__namespace.default.memo(({
|
|
|
49608
50024
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative w-full h-full overflow-hidden ${className}`, children: [
|
|
49609
50025
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-0 left-2 sm:left-4 right-2 sm:right-8 z-20", children: [
|
|
49610
50026
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-row items-center justify-between py-1 sm:py-1.5 gap-2", children: [
|
|
49611
|
-
/* @__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 }) }),
|
|
49612
50028
|
mapViewEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
49613
50029
|
"button",
|
|
49614
50030
|
{
|
|
@@ -49625,7 +50041,7 @@ var WorkspaceGrid = React141__namespace.default.memo(({
|
|
|
49625
50041
|
}
|
|
49626
50042
|
)
|
|
49627
50043
|
] }),
|
|
49628
|
-
/* @__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 }) })
|
|
49629
50045
|
] }),
|
|
49630
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(
|
|
49631
50047
|
motion.div,
|
|
@@ -50136,7 +50552,7 @@ var KPISection = React141.memo(({
|
|
|
50136
50552
|
value: showSkeleton ? "" : kpis.efficiency.value,
|
|
50137
50553
|
change: effChange,
|
|
50138
50554
|
trend: effTrend,
|
|
50139
|
-
trendLabel: "
|
|
50555
|
+
trendLabel: "vs yesterday",
|
|
50140
50556
|
trendMode: "pill",
|
|
50141
50557
|
suffix: "%",
|
|
50142
50558
|
showZeroChange: true,
|
|
@@ -52372,7 +52788,7 @@ var SideNavBar = React141.memo(({
|
|
|
52372
52788
|
setIsAlertsOpen(willOpen);
|
|
52373
52789
|
setIsSettingsOpen(false);
|
|
52374
52790
|
if (willOpen) {
|
|
52375
|
-
trackCoreEvent("Alerts
|
|
52791
|
+
trackCoreEvent("Alerts page clicked", { source: "side_nav" });
|
|
52376
52792
|
void refreshAlertsSummary();
|
|
52377
52793
|
}
|
|
52378
52794
|
},
|
|
@@ -52527,7 +52943,7 @@ var SideNavBar = React141.memo(({
|
|
|
52527
52943
|
{
|
|
52528
52944
|
onClick: () => {
|
|
52529
52945
|
setIsAlertsOpen(true);
|
|
52530
|
-
trackCoreEvent("Alerts
|
|
52946
|
+
trackCoreEvent("Alerts page clicked", { source: "side_nav_mobile" });
|
|
52531
52947
|
void refreshAlertsSummary();
|
|
52532
52948
|
onMobileMenuClose?.();
|
|
52533
52949
|
},
|
|
@@ -59737,7 +60153,8 @@ var MonthlyRangeFilter = ({
|
|
|
59737
60153
|
onMonthNavigate,
|
|
59738
60154
|
className,
|
|
59739
60155
|
variant = "default",
|
|
59740
|
-
showLabel = true
|
|
60156
|
+
showLabel = true,
|
|
60157
|
+
singleDateOnly = false
|
|
59741
60158
|
}) => {
|
|
59742
60159
|
const todayKey = React141.useMemo(
|
|
59743
60160
|
() => dateFnsTz.formatInTimeZone(/* @__PURE__ */ new Date(), timezone || "UTC", "yyyy-MM-dd"),
|
|
@@ -59825,6 +60242,12 @@ var MonthlyRangeFilter = ({
|
|
|
59825
60242
|
}
|
|
59826
60243
|
setActivePreset("Custom");
|
|
59827
60244
|
setPendingChangeMeta({ source: "custom" });
|
|
60245
|
+
if (singleDateOnly) {
|
|
60246
|
+
setRangeStart(day);
|
|
60247
|
+
setRangeEnd(day);
|
|
60248
|
+
setSelecting(false);
|
|
60249
|
+
return;
|
|
60250
|
+
}
|
|
59828
60251
|
if (!selecting || !rangeStart) {
|
|
59829
60252
|
setRangeStart(day);
|
|
59830
60253
|
setRangeEnd(null);
|
|
@@ -59859,6 +60282,13 @@ var MonthlyRangeFilter = ({
|
|
|
59859
60282
|
};
|
|
59860
60283
|
const handleApply = () => {
|
|
59861
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
|
+
}
|
|
59862
60292
|
const boundedStart = dateFns.startOfDay(rangeStart) > dateFns.startOfDay(today) ? dateFns.startOfDay(today) : dateFns.startOfDay(rangeStart);
|
|
59863
60293
|
const candidateEnd = rangeEnd || rangeStart;
|
|
59864
60294
|
const boundedEnd = dateFns.startOfDay(candidateEnd) > dateFns.startOfDay(today) ? dateFns.startOfDay(today) : dateFns.startOfDay(candidateEnd);
|
|
@@ -59953,7 +60383,7 @@ var MonthlyRangeFilter = ({
|
|
|
59953
60383
|
"overflow-hidden bg-white animate-in fade-in zoom-in-95 duration-200 flex",
|
|
59954
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"
|
|
59955
60385
|
), children: [
|
|
59956
|
-
/* @__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: [
|
|
59957
60387
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
59958
60388
|
presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
59959
60389
|
"button",
|
|
@@ -59962,7 +60392,7 @@ var MonthlyRangeFilter = ({
|
|
|
59962
60392
|
onClick: () => handlePresetClick(preset),
|
|
59963
60393
|
className: clsx(
|
|
59964
60394
|
"w-full text-left px-3 py-2 text-sm rounded-lg transition-all duration-200",
|
|
59965
|
-
activePreset === preset.label ? "bg-
|
|
60395
|
+
activePreset === preset.label ? "bg-blue-50 text-blue-600 font-semibold" : "text-gray-600 hover:bg-gray-100/80"
|
|
59966
60396
|
),
|
|
59967
60397
|
children: preset.label
|
|
59968
60398
|
},
|
|
@@ -59975,7 +60405,7 @@ var MonthlyRangeFilter = ({
|
|
|
59975
60405
|
onClick: () => setActivePreset("Custom"),
|
|
59976
60406
|
className: clsx(
|
|
59977
60407
|
"w-full text-left px-3 py-2 text-sm rounded-lg transition-all duration-200",
|
|
59978
|
-
activePreset === "Custom" ? "bg-
|
|
60408
|
+
activePreset === "Custom" ? "bg-blue-50 text-blue-600 font-semibold" : "text-gray-600 hover:bg-gray-100/80"
|
|
59979
60409
|
),
|
|
59980
60410
|
children: "Custom"
|
|
59981
60411
|
}
|
|
@@ -59997,7 +60427,7 @@ var MonthlyRangeFilter = ({
|
|
|
59997
60427
|
type: "button",
|
|
59998
60428
|
onClick: handleApply,
|
|
59999
60429
|
disabled: !rangeStart,
|
|
60000
|
-
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",
|
|
60001
60431
|
children: "Apply"
|
|
60002
60432
|
}
|
|
60003
60433
|
)
|
|
@@ -60047,9 +60477,9 @@ var MonthlyRangeFilter = ({
|
|
|
60047
60477
|
const dayNum = day.getDate();
|
|
60048
60478
|
const isFutureDay = dateFns.startOfDay(day) > dateFns.startOfDay(today);
|
|
60049
60479
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
60050
|
-
inRange && !isStart && !isEnd && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 -inset-x-0.5 bg-
|
|
60051
|
-
inRange && isStart && !isSingleDaySelection && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-y-0 right-0 left-1/2 bg-
|
|
60052
|
-
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" }),
|
|
60053
60483
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60054
60484
|
"button",
|
|
60055
60485
|
{
|
|
@@ -60058,19 +60488,47 @@ var MonthlyRangeFilter = ({
|
|
|
60058
60488
|
disabled: isFutureDay,
|
|
60059
60489
|
className: clsx(
|
|
60060
60490
|
"h-10 w-full flex items-center justify-center text-sm font-semibold transition-all duration-150 relative z-10",
|
|
60061
|
-
|
|
60491
|
+
// Future day NOT in range
|
|
60492
|
+
isFutureDay && !inRange && "text-gray-300 cursor-not-allowed",
|
|
60062
60493
|
// Not in range
|
|
60063
|
-
!isFutureDay && !inRange && "text-gray-700 hover:bg-gray-
|
|
60494
|
+
!isFutureDay && !inRange && "text-gray-700 hover:bg-gray-100 rounded-lg",
|
|
60064
60495
|
// Middle of range
|
|
60065
|
-
inRange && !isStart && !isEnd &&
|
|
60496
|
+
inRange && !isStart && !isEnd && clsx(
|
|
60497
|
+
"text-blue-600",
|
|
60498
|
+
isFutureDay && "cursor-not-allowed opacity-60"
|
|
60499
|
+
),
|
|
60066
60500
|
// Start/End of range or Single selection
|
|
60067
|
-
(isStart || isEnd) &&
|
|
60501
|
+
(isStart || isEnd) && clsx(
|
|
60502
|
+
"bg-blue-600 text-white rounded-lg shadow-sm",
|
|
60503
|
+
isFutureDay && "cursor-not-allowed opacity-80"
|
|
60504
|
+
)
|
|
60068
60505
|
),
|
|
60069
60506
|
children: dayNum
|
|
60070
60507
|
}
|
|
60071
60508
|
)
|
|
60072
60509
|
] }, day.toISOString());
|
|
60073
|
-
}) })
|
|
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
|
+
] })
|
|
60074
60532
|
] })
|
|
60075
60533
|
] })
|
|
60076
60534
|
] });
|
|
@@ -61847,7 +62305,36 @@ var getMonthDateInfo = (timezone) => {
|
|
|
61847
62305
|
const monthEndDate = dateFnsTz.fromZonedTime(`${monthEndKey}T23:59:59`, timezone);
|
|
61848
62306
|
return { startDate, endDate, monthEndDate };
|
|
61849
62307
|
};
|
|
61850
|
-
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 }) => {
|
|
61851
62338
|
const [time2, setTime] = React141.useState("");
|
|
61852
62339
|
const hasFinishedRef = React141.useRef(false);
|
|
61853
62340
|
React141.useEffect(() => {
|
|
@@ -61869,7 +62356,7 @@ var LeaderboardCountdown = ({ targetDate, format: format8, finishedLabel = "Fini
|
|
|
61869
62356
|
}
|
|
61870
62357
|
return;
|
|
61871
62358
|
}
|
|
61872
|
-
if (
|
|
62359
|
+
if (format9 === "days") {
|
|
61873
62360
|
const days = Math.floor(diff / (1e3 * 60 * 60 * 24));
|
|
61874
62361
|
const hours = Math.floor(diff % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60));
|
|
61875
62362
|
setTime(`${days} days ${hours} hours`);
|
|
@@ -61884,7 +62371,7 @@ var LeaderboardCountdown = ({ targetDate, format: format8, finishedLabel = "Fini
|
|
|
61884
62371
|
tick();
|
|
61885
62372
|
const interval = setInterval(tick, 1e3);
|
|
61886
62373
|
return () => clearInterval(interval);
|
|
61887
|
-
}, [targetDate,
|
|
62374
|
+
}, [targetDate, format9, finishedLabel, placeholder, onFinished]);
|
|
61888
62375
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: time2 });
|
|
61889
62376
|
};
|
|
61890
62377
|
var LinesLeaderboard = ({
|
|
@@ -61902,7 +62389,9 @@ var LinesLeaderboard = ({
|
|
|
61902
62389
|
shiftEndDate,
|
|
61903
62390
|
monthEndDate,
|
|
61904
62391
|
viewType,
|
|
61905
|
-
setViewType
|
|
62392
|
+
setViewType,
|
|
62393
|
+
timezone: _timezone,
|
|
62394
|
+
isHistoricalDaily
|
|
61906
62395
|
}) => {
|
|
61907
62396
|
const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
|
|
61908
62397
|
const assignedLineIdSet = React141__namespace.default.useMemo(
|
|
@@ -61995,10 +62484,10 @@ var LinesLeaderboard = ({
|
|
|
61995
62484
|
}
|
|
61996
62485
|
}, [timeRange, leaderboardData, isLoadingToday, isLoadingMonthly]);
|
|
61997
62486
|
const topThree = leaderboardData.slice(0, 3);
|
|
61998
|
-
leaderboardData.slice(3);
|
|
61999
62487
|
const countdownTarget = timeRange === "monthly" ? monthEndDate : shiftEndDate;
|
|
62000
62488
|
const countdownFormat = timeRange === "monthly" ? "days" : "clock";
|
|
62001
62489
|
const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift Ended";
|
|
62490
|
+
const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
|
|
62002
62491
|
const handleCountdownFinished = React141__namespace.default.useCallback(() => {
|
|
62003
62492
|
trackCoreEvent("Leaderboard Countdown Finished", {
|
|
62004
62493
|
countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
|
|
@@ -62072,7 +62561,7 @@ var LinesLeaderboard = ({
|
|
|
62072
62561
|
}
|
|
62073
62562
|
)
|
|
62074
62563
|
] }),
|
|
62075
|
-
/* @__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: [
|
|
62076
62565
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Clock, { className: "w-4 h-4 text-orange-500" }),
|
|
62077
62566
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline gap-2", children: [
|
|
62078
62567
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider", children: "Ends in" }),
|
|
@@ -62193,7 +62682,7 @@ var LinesLeaderboard = ({
|
|
|
62193
62682
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-900", children: item.supervisorName })
|
|
62194
62683
|
] }) }),
|
|
62195
62684
|
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 whitespace-nowrap text-sm text-gray-500", children: item.line.line_name }),
|
|
62196
|
-
/* @__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) }) }) })
|
|
62197
62686
|
]
|
|
62198
62687
|
},
|
|
62199
62688
|
item.id
|
|
@@ -62367,6 +62856,9 @@ var KPIsOverviewView = ({
|
|
|
62367
62856
|
const [activeTab, setActiveTab] = React141.useState("today");
|
|
62368
62857
|
const [timeRange, setTimeRange] = React141.useState("today");
|
|
62369
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);
|
|
62370
62862
|
const [loading, setLoading] = React141.useState(true);
|
|
62371
62863
|
const [error, setError] = React141.useState(null);
|
|
62372
62864
|
const [topPerformer, setTopPerformer] = React141.useState({
|
|
@@ -62388,13 +62880,6 @@ var KPIsOverviewView = ({
|
|
|
62388
62880
|
const [monthlyError, setMonthlyError] = React141.useState(null);
|
|
62389
62881
|
const dailyRequestKeyRef = React141.useRef(null);
|
|
62390
62882
|
const monthlyRequestKeyRef = React141.useRef(null);
|
|
62391
|
-
React141.useEffect(() => {
|
|
62392
|
-
if (!router$1.isReady) return;
|
|
62393
|
-
const tab = router$1.query.tab;
|
|
62394
|
-
if (tab === "leaderboard") {
|
|
62395
|
-
setActiveTab("leaderboard");
|
|
62396
|
-
}
|
|
62397
|
-
}, [router$1.isReady, router$1.query.tab]);
|
|
62398
62883
|
const supabase = useSupabase();
|
|
62399
62884
|
const { user } = useAuth();
|
|
62400
62885
|
const dashboardConfig = useDashboardConfig();
|
|
@@ -62480,7 +62965,77 @@ var KPIsOverviewView = ({
|
|
|
62480
62965
|
() => getShiftEndDate(currentShiftDetails, configuredTimezone),
|
|
62481
62966
|
[currentShiftDetails, configuredTimezone]
|
|
62482
62967
|
);
|
|
62483
|
-
|
|
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
|
+
]);
|
|
62484
63039
|
const factoryViewId = entityConfig.factoryViewId || "factory";
|
|
62485
63040
|
const {
|
|
62486
63041
|
lineMetrics,
|
|
@@ -62655,10 +63210,10 @@ var KPIsOverviewView = ({
|
|
|
62655
63210
|
}, [supabase, resolvedCompanyId, leaderboardLinesForView, monthStartDate, monthEndDateKey, viewType]);
|
|
62656
63211
|
const fetchDailyLeaderboard = React141.useCallback(async () => {
|
|
62657
63212
|
if (!supabase || !resolvedCompanyId || leaderboardLinesForView.length === 0) return;
|
|
62658
|
-
if (!
|
|
63213
|
+
if (!effectiveLeaderboardDate) return;
|
|
62659
63214
|
const targetLineIds = leaderboardLinesForView.map((line) => line.id);
|
|
62660
63215
|
const lineIdsKey = targetLineIds.slice().sort().join(",");
|
|
62661
|
-
const requestKey = `${resolvedCompanyId}|${
|
|
63216
|
+
const requestKey = `${resolvedCompanyId}|${effectiveLeaderboardDate}|${effectiveLeaderboardShiftId}|${lineIdsKey}`;
|
|
62662
63217
|
if (dailyRequestKeyRef.current === requestKey) return;
|
|
62663
63218
|
dailyRequestKeyRef.current = requestKey;
|
|
62664
63219
|
setDailyLoading(true);
|
|
@@ -62666,8 +63221,8 @@ var KPIsOverviewView = ({
|
|
|
62666
63221
|
try {
|
|
62667
63222
|
const entries = await lineLeaderboardService.getDailyLineLeaderboard(supabase, {
|
|
62668
63223
|
companyId: resolvedCompanyId,
|
|
62669
|
-
date:
|
|
62670
|
-
shiftId:
|
|
63224
|
+
date: effectiveLeaderboardDate,
|
|
63225
|
+
shiftId: effectiveLeaderboardShiftId,
|
|
62671
63226
|
lineIds: targetLineIds,
|
|
62672
63227
|
lineMode: viewType === "machine" ? "uptime" : "output"
|
|
62673
63228
|
});
|
|
@@ -62685,7 +63240,14 @@ var KPIsOverviewView = ({
|
|
|
62685
63240
|
} finally {
|
|
62686
63241
|
setDailyLoading(false);
|
|
62687
63242
|
}
|
|
62688
|
-
}, [
|
|
63243
|
+
}, [
|
|
63244
|
+
supabase,
|
|
63245
|
+
resolvedCompanyId,
|
|
63246
|
+
leaderboardLinesForView,
|
|
63247
|
+
effectiveLeaderboardDate,
|
|
63248
|
+
effectiveLeaderboardShiftId,
|
|
63249
|
+
viewType
|
|
63250
|
+
]);
|
|
62689
63251
|
React141.useEffect(() => {
|
|
62690
63252
|
if (activeTab !== "leaderboard") return;
|
|
62691
63253
|
fetchMonthlyLeaderboard();
|
|
@@ -62774,6 +63336,12 @@ var KPIsOverviewView = ({
|
|
|
62774
63336
|
trackProps.status = isEfficiencyOnTrack(kpis.efficiency?.value) ? "On Track" : "Behind";
|
|
62775
63337
|
}
|
|
62776
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
|
+
}
|
|
62777
63345
|
navigation.navigate(`/kpis/${line.id}`);
|
|
62778
63346
|
};
|
|
62779
63347
|
const handleBackClick = React141.useCallback(() => {
|
|
@@ -62799,21 +63367,24 @@ var KPIsOverviewView = ({
|
|
|
62799
63367
|
});
|
|
62800
63368
|
setActiveTab(newTab);
|
|
62801
63369
|
}, [activeTab, leaderboardLines.length, lines.length]);
|
|
62802
|
-
const formatLocalDate2 = (
|
|
62803
|
-
|
|
63370
|
+
const formatLocalDate2 = React141.useCallback((dateKey) => {
|
|
63371
|
+
return formatDateKey(dateKey, configuredTimezone, {
|
|
62804
63372
|
year: "numeric",
|
|
62805
63373
|
month: "long",
|
|
62806
63374
|
day: "numeric"
|
|
62807
|
-
};
|
|
62808
|
-
|
|
62809
|
-
};
|
|
63375
|
+
});
|
|
63376
|
+
}, [configuredTimezone]);
|
|
62810
63377
|
const getMonthRange = () => {
|
|
62811
|
-
const
|
|
62812
|
-
const
|
|
62813
|
-
const
|
|
62814
|
-
|
|
62815
|
-
|
|
62816
|
-
|
|
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()}`;
|
|
62817
63388
|
};
|
|
62818
63389
|
const isMonthlyMode = activeTab === "leaderboard" && timeRange === "monthly";
|
|
62819
63390
|
const isLeaderboardLoading = timeRange === "today" ? dailyLoading : monthlyLoading;
|
|
@@ -62822,8 +63393,13 @@ var KPIsOverviewView = ({
|
|
|
62822
63393
|
const showTopPerformerImage = Boolean(topPerformer.imageUrl) && !topPerformerImageError;
|
|
62823
63394
|
typeof topPerformer.efficiency === "number" && Number.isFinite(topPerformer.efficiency);
|
|
62824
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);
|
|
62825
63401
|
const getShiftIcon = (shiftId) => {
|
|
62826
|
-
const shiftNameLower =
|
|
63402
|
+
const shiftNameLower = getShiftNameById(shiftId, configuredTimezone, shiftConfig).toLowerCase();
|
|
62827
63403
|
if (shiftNameLower.includes("day") || shiftNameLower.includes("morning") || shiftId === 0) {
|
|
62828
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" }) });
|
|
62829
63405
|
}
|
|
@@ -62926,18 +63502,26 @@ var KPIsOverviewView = ({
|
|
|
62926
63502
|
),
|
|
62927
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: [
|
|
62928
63504
|
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold text-gray-900", children: activeTab === "leaderboard" ? "Leaderboard" : "Overview" }),
|
|
62929
|
-
/* @__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
|
+
)
|
|
62930
63511
|
] }) }),
|
|
62931
63512
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12" })
|
|
62932
63513
|
] }),
|
|
62933
63514
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 flex flex-wrap items-center justify-center gap-2", children: [
|
|
62934
|
-
/* @__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 }) }),
|
|
62935
63516
|
!isMonthlyMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
62936
63517
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-center gap-1 px-2.5 py-1 bg-gray-100 rounded-full", children: [
|
|
62937
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-gray-700 scale-90", children: getShiftIcon(
|
|
62938
|
-
/* @__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 })
|
|
62939
63520
|
] }),
|
|
62940
|
-
/* @__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, {}) }) })
|
|
62941
63525
|
] })
|
|
62942
63526
|
] }),
|
|
62943
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: [
|
|
@@ -63038,7 +63622,12 @@ var KPIsOverviewView = ({
|
|
|
63038
63622
|
) }),
|
|
63039
63623
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
63040
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" }),
|
|
63041
|
-
/* @__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
|
+
)
|
|
63042
63631
|
] }),
|
|
63043
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: [
|
|
63044
63633
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
@@ -63108,7 +63697,7 @@ var KPIsOverviewView = ({
|
|
|
63108
63697
|
] }) })
|
|
63109
63698
|
] }),
|
|
63110
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: [
|
|
63111
|
-
!isMonthlyMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63700
|
+
!isMonthlyMode && !showHistoricalLeaderboardHeader && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63112
63701
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-blue-700", children: [
|
|
63113
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" }) }),
|
|
63114
63703
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-semibold tabular-nums", children: /* @__PURE__ */ jsxRuntime.jsx(ISTTimer_default, {}) })
|
|
@@ -63117,16 +63706,23 @@ var KPIsOverviewView = ({
|
|
|
63117
63706
|
] }),
|
|
63118
63707
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-blue-600", children: [
|
|
63119
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" }) }),
|
|
63120
|
-
/* @__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 })
|
|
63121
63710
|
] }),
|
|
63122
63711
|
!isMonthlyMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
63123
63712
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-px h-4 bg-blue-200" }),
|
|
63124
63713
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-blue-600", children: [
|
|
63125
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-70", children: getShiftIcon(
|
|
63714
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "opacity-70", children: getShiftIcon(headerShiftId) }),
|
|
63126
63715
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold uppercase tracking-wider", children: [
|
|
63127
|
-
|
|
63716
|
+
headerShiftName,
|
|
63128
63717
|
" Shift"
|
|
63129
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
|
+
] })
|
|
63130
63726
|
] })
|
|
63131
63727
|
] })
|
|
63132
63728
|
] }) }),
|
|
@@ -63149,19 +63745,52 @@ var KPIsOverviewView = ({
|
|
|
63149
63745
|
}
|
|
63150
63746
|
)
|
|
63151
63747
|
] }),
|
|
63152
|
-
|
|
63153
|
-
"
|
|
63154
|
-
|
|
63155
|
-
|
|
63156
|
-
|
|
63157
|
-
|
|
63158
|
-
|
|
63159
|
-
|
|
63160
|
-
|
|
63161
|
-
|
|
63162
|
-
|
|
63163
|
-
|
|
63164
|
-
|
|
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
|
+
] })
|
|
63165
63794
|
] })
|
|
63166
63795
|
] })
|
|
63167
63796
|
] }) }),
|
|
@@ -63206,7 +63835,9 @@ var KPIsOverviewView = ({
|
|
|
63206
63835
|
shiftEndDate,
|
|
63207
63836
|
monthEndDate,
|
|
63208
63837
|
viewType,
|
|
63209
|
-
setViewType
|
|
63838
|
+
setViewType,
|
|
63839
|
+
timezone: configuredTimezone,
|
|
63840
|
+
isHistoricalDaily: isHistoricalLeaderboardDaily
|
|
63210
63841
|
}
|
|
63211
63842
|
) })
|
|
63212
63843
|
) })
|
|
@@ -64748,51 +65379,41 @@ var ClipsCostView = () => {
|
|
|
64748
65379
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-[120px]" })
|
|
64749
65380
|
] }) })
|
|
64750
65381
|
] }) }),
|
|
64751
|
-
/* @__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: [
|
|
64752
65383
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircle, { className: "h-5 w-5 flex-shrink-0 mt-0.5" }),
|
|
64753
65384
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
64754
65385
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-medium", children: "Error loading usage data" }),
|
|
64755
65386
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm mt-1 text-red-600", children: error })
|
|
64756
65387
|
] })
|
|
64757
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
64758
|
-
/* @__PURE__ */ jsxRuntime.jsx(Card2, { className: "overflow-hidden shadow-sm border-gray-200 bg-white", children: /* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "p-
|
|
64759
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-
|
|
64760
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-
|
|
64761
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-
|
|
64762
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-
|
|
64763
|
-
|
|
64764
|
-
|
|
64765
|
-
|
|
64766
|
-
|
|
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(
|
|
64767
65402
|
"div",
|
|
64768
65403
|
{
|
|
64769
|
-
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",
|
|
64770
65405
|
children: [
|
|
64771
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm text-gray-
|
|
64772
|
-
/* @__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) })
|
|
64773
65408
|
]
|
|
64774
65409
|
},
|
|
64775
65410
|
item.monthStart
|
|
64776
65411
|
)) })
|
|
64777
|
-
] }) })
|
|
65412
|
+
] }) }) })
|
|
64778
65413
|
] }) })
|
|
64779
65414
|
] });
|
|
64780
65415
|
};
|
|
64781
65416
|
var ClipsCostView_default = ClipsCostView;
|
|
64782
|
-
|
|
64783
|
-
// src/lib/constants/actions.ts
|
|
64784
|
-
var ACTION_NAMES = {
|
|
64785
|
-
/** Assembly operations */
|
|
64786
|
-
ASSEMBLY: "Assembly",
|
|
64787
|
-
/** Packaging operations */
|
|
64788
|
-
PACKAGING: "Packaging",
|
|
64789
|
-
/** Inspection operations */
|
|
64790
|
-
INSPECTION: "Inspection",
|
|
64791
|
-
/** Testing operations */
|
|
64792
|
-
TESTING: "Testing",
|
|
64793
|
-
/** Quality control operations */
|
|
64794
|
-
QUALITY_CONTROL: "Quality Control"
|
|
64795
|
-
};
|
|
64796
65417
|
var calculateShiftHours = (startTime, endTime, breaks = []) => {
|
|
64797
65418
|
if (!startTime || !endTime) return 8;
|
|
64798
65419
|
const [startHour, startMinute] = startTime.split(":").map(Number);
|
|
@@ -65374,9 +65995,9 @@ var ShiftsView = ({
|
|
|
65374
65995
|
const actionIds = Array.from(
|
|
65375
65996
|
new Set(currentThresholds.map((threshold) => threshold.action_id).filter(Boolean))
|
|
65376
65997
|
);
|
|
65377
|
-
const
|
|
65998
|
+
const actionMetadataById = /* @__PURE__ */ new Map();
|
|
65378
65999
|
if (actionIds.length > 0) {
|
|
65379
|
-
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);
|
|
65380
66001
|
if (actionsError) {
|
|
65381
66002
|
console.warn(
|
|
65382
66003
|
`[ShiftsView] Failed to resolve action names for line ${lineId}, shift ${shift.shiftId}: ${actionsError.message}`
|
|
@@ -65384,7 +66005,13 @@ var ShiftsView = ({
|
|
|
65384
66005
|
} else {
|
|
65385
66006
|
(actionRows || []).forEach((actionRow) => {
|
|
65386
66007
|
if (actionRow.id && actionRow.action_name) {
|
|
65387
|
-
|
|
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
|
+
});
|
|
65388
66015
|
}
|
|
65389
66016
|
});
|
|
65390
66017
|
}
|
|
@@ -65405,7 +66032,7 @@ var ShiftsView = ({
|
|
|
65405
66032
|
nextDayOutput = dayOutputToKeep;
|
|
65406
66033
|
nextPPH = newShiftHours > 0 ? Math.round(dayOutputToKeep / newShiftHours) : 0;
|
|
65407
66034
|
}
|
|
65408
|
-
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;
|
|
65409
66036
|
return {
|
|
65410
66037
|
line_id: threshold.line_id || lineId,
|
|
65411
66038
|
shift_id: shift.shiftId,
|
|
@@ -65426,18 +66053,20 @@ var ShiftsView = ({
|
|
|
65426
66053
|
`Failed to update action thresholds for line ${lineId}, shift ${shift.shiftId}: ${thresholdsUpsertError.message}`
|
|
65427
66054
|
);
|
|
65428
66055
|
}
|
|
65429
|
-
const
|
|
65430
|
-
Array.from(
|
|
66056
|
+
const outputActionIds = new Set(
|
|
66057
|
+
Array.from(actionMetadataById.entries()).filter(([, action]) => action.action_family === ACTION_FAMILIES.OUTPUT).map(([actionId]) => actionId)
|
|
65431
66058
|
);
|
|
65432
|
-
const
|
|
65433
|
-
if (
|
|
65434
|
-
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;
|
|
65435
66064
|
});
|
|
65436
|
-
const thresholdDayOutput =
|
|
66065
|
+
const thresholdDayOutput = outputThresholds.reduce(
|
|
65437
66066
|
(sum, threshold) => sum + (Number(threshold.total_day_output) || 0),
|
|
65438
66067
|
0
|
|
65439
66068
|
);
|
|
65440
|
-
const thresholdPPH =
|
|
66069
|
+
const thresholdPPH = outputThresholds.reduce(
|
|
65441
66070
|
(sum, threshold) => sum + (Number(threshold.pph_threshold) || 0),
|
|
65442
66071
|
0
|
|
65443
66072
|
);
|
|
@@ -66648,7 +67277,7 @@ var TargetsViewUI = ({
|
|
|
66648
67277
|
"aria-label": `Action type for ${formattedName}`,
|
|
66649
67278
|
children: [
|
|
66650
67279
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "assembly", className: "py-2", children: "Assembly" }),
|
|
66651
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
67280
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "output", className: "py-2", children: ACTION_NAMES.OUTPUT })
|
|
66652
67281
|
]
|
|
66653
67282
|
}
|
|
66654
67283
|
) }),
|
|
@@ -66719,7 +67348,7 @@ var TargetsViewUI = ({
|
|
|
66719
67348
|
"aria-label": `Action type for ${formattedName}`,
|
|
66720
67349
|
children: [
|
|
66721
67350
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "assembly", children: "Assembly" }),
|
|
66722
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "
|
|
67351
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "output", children: ACTION_NAMES.OUTPUT })
|
|
66723
67352
|
]
|
|
66724
67353
|
}
|
|
66725
67354
|
)
|
|
@@ -66924,14 +67553,20 @@ var TargetsView = ({
|
|
|
66924
67553
|
throw new Error("Failed to fetch bulk targets data");
|
|
66925
67554
|
}
|
|
66926
67555
|
const { data } = bulkResponse;
|
|
66927
|
-
const assemblyAction = Object.values(data.actions).find((a) =>
|
|
66928
|
-
|
|
66929
|
-
|
|
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) {
|
|
66930
67565
|
throw new Error("Could not find required actions in bulk response");
|
|
66931
67566
|
}
|
|
66932
67567
|
const actionIdsData = {
|
|
66933
67568
|
assembly: assemblyAction.id,
|
|
66934
|
-
|
|
67569
|
+
output: outputAction.id
|
|
66935
67570
|
};
|
|
66936
67571
|
setActionIds(actionIdsData);
|
|
66937
67572
|
const newAllShiftsData = {};
|
|
@@ -66976,12 +67611,16 @@ var TargetsView = ({
|
|
|
66976
67611
|
let actionType = "assembly";
|
|
66977
67612
|
let actionId = actionIdsData.assembly;
|
|
66978
67613
|
const effectiveActionId = threshold?.action_id ?? ws.action_id;
|
|
66979
|
-
|
|
66980
|
-
|
|
66981
|
-
|
|
66982
|
-
}
|
|
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") {
|
|
66983
67622
|
actionType = "assembly";
|
|
66984
|
-
actionId = assemblyAction.id;
|
|
67623
|
+
actionId = effectiveActionId || assemblyAction.id;
|
|
66985
67624
|
}
|
|
66986
67625
|
return {
|
|
66987
67626
|
id: ws.id,
|
|
@@ -67253,7 +67892,9 @@ var TargetsView = ({
|
|
|
67253
67892
|
// Round to whole number
|
|
67254
67893
|
ideal_cycle_time: Number(ws.targetCycleTime) || 0,
|
|
67255
67894
|
total_day_output: Number(ws.targetDayOutput) || 0,
|
|
67256
|
-
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,
|
|
67257
67898
|
updated_by: currentEffectiveUserId,
|
|
67258
67899
|
// Use the potentially hardcoded ID
|
|
67259
67900
|
...skuEnabled && lineDataToSave.selectedSKU ? { sku_id: lineDataToSave.selectedSKU.id } : {}
|
|
@@ -67261,7 +67902,7 @@ var TargetsView = ({
|
|
|
67261
67902
|
console.log(`[handleSaveLine] workspaceThresholdUpdates for ${lineId}:`, workspaceThresholdUpdates);
|
|
67262
67903
|
await workspaceService.updateActionThresholds(workspaceThresholdUpdates);
|
|
67263
67904
|
console.log(`[handleSaveLine] Successfully updated action thresholds for ${lineId}`);
|
|
67264
|
-
const
|
|
67905
|
+
const outputWorkspaces = lineDataToSave.workspaces.filter((ws) => ws.actionType === "output");
|
|
67265
67906
|
let resolvedLineThresholdSkuId = lineDataToSave.selectedSKU?.id || null;
|
|
67266
67907
|
if (!resolvedLineThresholdSkuId) {
|
|
67267
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);
|
|
@@ -67279,8 +67920,8 @@ var TargetsView = ({
|
|
|
67279
67920
|
date: currentDate,
|
|
67280
67921
|
shift_id: selectedShift,
|
|
67281
67922
|
product_code: lineDataToSave.productId,
|
|
67282
|
-
threshold_day_output:
|
|
67283
|
-
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),
|
|
67284
67925
|
// Round each PPH value
|
|
67285
67926
|
sku_id: resolvedLineThresholdSkuId
|
|
67286
67927
|
};
|
|
@@ -67808,6 +68449,7 @@ var WorkspaceDetailView = ({
|
|
|
67808
68449
|
avg_efficiency: Number(cachedOverviewMetrics.efficiency || 0),
|
|
67809
68450
|
total_actions: totalActions,
|
|
67810
68451
|
hourly_action_counts: [],
|
|
68452
|
+
hourly_cycle_times: [],
|
|
67811
68453
|
workspace_rank: 0,
|
|
67812
68454
|
total_workspaces: 0,
|
|
67813
68455
|
ideal_output_until_now: idealOutput,
|
|
@@ -67818,6 +68460,22 @@ var WorkspaceDetailView = ({
|
|
|
67818
68460
|
}, [cachedOverviewMetrics, shiftConfig?.shifts]);
|
|
67819
68461
|
const workspace = (isHistoricView ? historicMetrics : liveMetrics) || cachedDetailedMetrics || overviewFallback;
|
|
67820
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
|
+
);
|
|
67821
68479
|
const hasWorkspaceSnapshot = Boolean(workspace);
|
|
67822
68480
|
const loading = ((isHistoricView ? historicLoading : liveLoading) || isShiftConfigLoading) && !hasWorkspaceSnapshot;
|
|
67823
68481
|
const error = isHistoricView ? historicError : liveError;
|
|
@@ -68059,10 +68717,47 @@ var WorkspaceDetailView = ({
|
|
|
68059
68717
|
return filterDataByDateKeyRange(monthlyData, range);
|
|
68060
68718
|
}, [monthlyData, range]);
|
|
68061
68719
|
const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
|
|
68062
|
-
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);
|
|
68063
68724
|
const showIdleBreakdownChart = !shouldShowCycleTimeChart && idleTimeVlmEnabled;
|
|
68064
68725
|
const idleClipDate = date || workspace?.date || calculatedOperationalDate || getOperationalDate(timezone);
|
|
68065
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]);
|
|
68066
68761
|
const shiftDurationMinutes = React141.useMemo(
|
|
68067
68762
|
() => getShiftDurationMinutes(workspace?.shift_start, workspace?.shift_end),
|
|
68068
68763
|
[workspace?.shift_start, workspace?.shift_end]
|
|
@@ -68135,7 +68830,7 @@ var WorkspaceDetailView = ({
|
|
|
68135
68830
|
}
|
|
68136
68831
|
}, [returnUrl]);
|
|
68137
68832
|
const handleBackNavigation = () => {
|
|
68138
|
-
if (
|
|
68833
|
+
if (isHistoricView) {
|
|
68139
68834
|
setActiveTab("monthly_history");
|
|
68140
68835
|
if (onNavigate) {
|
|
68141
68836
|
const params = new URLSearchParams();
|
|
@@ -68299,7 +68994,7 @@ var WorkspaceDetailView = ({
|
|
|
68299
68994
|
BackButtonMinimal,
|
|
68300
68995
|
{
|
|
68301
68996
|
onClick: handleBackNavigation,
|
|
68302
|
-
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",
|
|
68303
68998
|
size: "default",
|
|
68304
68999
|
"aria-label": "Navigate back to previous page"
|
|
68305
69000
|
}
|
|
@@ -68476,7 +69171,8 @@ var WorkspaceDetailView = ({
|
|
|
68476
69171
|
{
|
|
68477
69172
|
workspace,
|
|
68478
69173
|
idleTimeReasons: idleTimeChartData,
|
|
68479
|
-
efficiencyLegend
|
|
69174
|
+
efficiencyLegend,
|
|
69175
|
+
hourlyCycleTimes: cycleTimeChartData
|
|
68480
69176
|
}
|
|
68481
69177
|
) }),
|
|
68482
69178
|
activeTab === "monthly_history" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
@@ -68557,7 +69253,7 @@ var WorkspaceDetailView = ({
|
|
|
68557
69253
|
animate: "animate",
|
|
68558
69254
|
children: [
|
|
68559
69255
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-4", children: [
|
|
68560
|
-
/* @__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" }),
|
|
68561
69257
|
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
68562
69258
|
"button",
|
|
68563
69259
|
{
|
|
@@ -68590,9 +69286,14 @@ var WorkspaceDetailView = ({
|
|
|
68590
69286
|
) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
68591
69287
|
CycleTimeOverTimeChart,
|
|
68592
69288
|
{
|
|
68593
|
-
data:
|
|
69289
|
+
data: cycleTimeChartData,
|
|
68594
69290
|
idealCycleTime: workspace.ideal_cycle_time || 0,
|
|
68595
|
-
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
|
|
68596
69297
|
}
|
|
68597
69298
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
68598
69299
|
HourlyOutputChart2,
|
|
@@ -68639,7 +69340,8 @@ var WorkspaceDetailView = ({
|
|
|
68639
69340
|
{
|
|
68640
69341
|
workspace,
|
|
68641
69342
|
legend: efficiencyLegend,
|
|
68642
|
-
layout: "stack"
|
|
69343
|
+
layout: "stack",
|
|
69344
|
+
idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0
|
|
68643
69345
|
}
|
|
68644
69346
|
) : /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, legend: efficiencyLegend, className: "flex-1" }) })
|
|
68645
69347
|
] }),
|
|
@@ -68684,7 +69386,7 @@ var WorkspaceDetailView = ({
|
|
|
68684
69386
|
animate: "animate",
|
|
68685
69387
|
children: [
|
|
68686
69388
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 mb-4 flex-none", children: [
|
|
68687
|
-
/* @__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" }),
|
|
68688
69390
|
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
68689
69391
|
"button",
|
|
68690
69392
|
{
|
|
@@ -68713,9 +69415,14 @@ var WorkspaceDetailView = ({
|
|
|
68713
69415
|
) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
68714
69416
|
CycleTimeOverTimeChart,
|
|
68715
69417
|
{
|
|
68716
|
-
data:
|
|
69418
|
+
data: cycleTimeChartData,
|
|
68717
69419
|
idealCycleTime: workspace.ideal_cycle_time || 0,
|
|
68718
|
-
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
|
|
68719
69426
|
}
|
|
68720
69427
|
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
68721
69428
|
HourlyOutputChart2,
|
|
@@ -68767,7 +69474,8 @@ var WorkspaceDetailView = ({
|
|
|
68767
69474
|
workspace,
|
|
68768
69475
|
legend: efficiencyLegend,
|
|
68769
69476
|
layout: "grid",
|
|
68770
|
-
className: desktopBottomSectionClass
|
|
69477
|
+
className: desktopBottomSectionClass,
|
|
69478
|
+
idleTimeData: idleTimeVlmEnabled ? idleTimeData : void 0
|
|
68771
69479
|
}
|
|
68772
69480
|
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("flex min-h-0", desktopBottomSectionClass), children: /* @__PURE__ */ jsxRuntime.jsx(WorkspaceMetricCards, { workspace, legend: efficiencyLegend, className: "flex-1" }) })
|
|
68773
69481
|
] })
|
|
@@ -68797,6 +69505,7 @@ var WorkspaceDetailView = ({
|
|
|
68797
69505
|
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
68798
69506
|
legend: efficiencyLegend,
|
|
68799
69507
|
trendSummary: workspaceMonthlyTrend,
|
|
69508
|
+
isAssemblyWorkspace,
|
|
68800
69509
|
onDateSelect: (selectedDate, shiftId) => {
|
|
68801
69510
|
if (onDateSelect) {
|
|
68802
69511
|
onDateSelect(selectedDate, shiftId);
|
|
@@ -74884,6 +75593,11 @@ var normalizeTrend = (value) => ({
|
|
|
74884
75593
|
});
|
|
74885
75594
|
var normalizeIdleBreakdown = (value) => (value || []).map((item) => ({
|
|
74886
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,
|
|
74887
75601
|
percentage: normalizeNumber(item?.percentage),
|
|
74888
75602
|
total_duration_seconds: normalizeNumber(item?.total_duration_seconds),
|
|
74889
75603
|
efficiency_loss_percentage: normalizeNumber(item?.efficiency_loss_percentage),
|
|
@@ -75935,7 +76649,12 @@ var IdleBreakdownCard = React141__namespace.default.memo(({
|
|
|
75935
76649
|
const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
|
|
75936
76650
|
const idleBreakdown = React141__namespace.default.useMemo(() => {
|
|
75937
76651
|
return idle.data.map((item) => ({
|
|
75938
|
-
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,
|
|
75939
76658
|
value: toNumber3(item.percentage) || 0,
|
|
75940
76659
|
totalDurationSeconds: toNumber3(item.total_duration_seconds),
|
|
75941
76660
|
efficiencyLossPercentage: toNumber3(item.efficiency_loss_percentage),
|
|
@@ -77227,6 +77946,7 @@ var streamProxyConfig = {
|
|
|
77227
77946
|
}
|
|
77228
77947
|
};
|
|
77229
77948
|
|
|
77949
|
+
exports.ACTION_FAMILIES = ACTION_FAMILIES;
|
|
77230
77950
|
exports.ACTION_NAMES = ACTION_NAMES;
|
|
77231
77951
|
exports.AIAgentView = AIAgentView_default;
|
|
77232
77952
|
exports.AcceptInvite = AcceptInvite;
|
|
@@ -77339,7 +78059,7 @@ exports.LINE_1_UUID = LINE_1_UUID;
|
|
|
77339
78059
|
exports.LINE_2_UUID = LINE_2_UUID;
|
|
77340
78060
|
exports.LargeOutputProgressChart = LargeOutputProgressChart;
|
|
77341
78061
|
exports.LeaderboardDetailView = LeaderboardDetailView_default;
|
|
77342
|
-
exports.Legend =
|
|
78062
|
+
exports.Legend = Legend5;
|
|
77343
78063
|
exports.LineAssignmentDropdown = LineAssignmentDropdown;
|
|
77344
78064
|
exports.LineChart = LineChart;
|
|
77345
78065
|
exports.LineHistoryCalendar = LineHistoryCalendar;
|
|
@@ -77521,6 +78241,7 @@ exports.formatReasonLabel = formatReasonLabel;
|
|
|
77521
78241
|
exports.formatRelativeTime = formatRelativeTime;
|
|
77522
78242
|
exports.formatTimeInZone = formatTimeInZone;
|
|
77523
78243
|
exports.fromUrlFriendlyName = fromUrlFriendlyName;
|
|
78244
|
+
exports.getActionDisplayName = getActionDisplayName;
|
|
77524
78245
|
exports.getAllLineDisplayNames = getAllLineDisplayNames;
|
|
77525
78246
|
exports.getAllThreadMessages = getAllThreadMessages;
|
|
77526
78247
|
exports.getAllWorkspaceDisplayNamesAsync = getAllWorkspaceDisplayNamesAsync;
|
|
@@ -77559,7 +78280,6 @@ exports.getMonthKeyBounds = getMonthKeyBounds;
|
|
|
77559
78280
|
exports.getMonthWeekRanges = getMonthWeekRanges;
|
|
77560
78281
|
exports.getNextUpdateInterval = getNextUpdateInterval;
|
|
77561
78282
|
exports.getOperationalDate = getOperationalDate;
|
|
77562
|
-
exports.getReasonColor = getReasonColor;
|
|
77563
78283
|
exports.getRoleAssignmentKind = getRoleAssignmentKind;
|
|
77564
78284
|
exports.getRoleDescription = getRoleDescription;
|
|
77565
78285
|
exports.getRoleLabel = getRoleLabel;
|
|
@@ -77594,6 +78314,7 @@ exports.isFactoryScopedRole = isFactoryScopedRole;
|
|
|
77594
78314
|
exports.isFullMonthRange = isFullMonthRange;
|
|
77595
78315
|
exports.isLegacyConfiguration = isLegacyConfiguration;
|
|
77596
78316
|
exports.isPrefetchError = isPrefetchError;
|
|
78317
|
+
exports.isRecentFlowVideoGridMetricMode = isRecentFlowVideoGridMetricMode;
|
|
77597
78318
|
exports.isSafari = isSafari;
|
|
77598
78319
|
exports.isSupervisorRole = isSupervisorRole;
|
|
77599
78320
|
exports.isTransitionPeriod = isTransitionPeriod;
|
|
@@ -77604,14 +78325,17 @@ exports.isValidPrefetchParams = isValidPrefetchParams;
|
|
|
77604
78325
|
exports.isValidPrefetchStatus = isValidPrefetchStatus;
|
|
77605
78326
|
exports.isValidWorkspaceDetailedMetricsPayload = isValidWorkspaceDetailedMetricsPayload;
|
|
77606
78327
|
exports.isValidWorkspaceMetricsPayload = isValidWorkspaceMetricsPayload;
|
|
78328
|
+
exports.isWipGatedVideoGridMetricMode = isWipGatedVideoGridMetricMode;
|
|
77607
78329
|
exports.isWorkspaceDisplayNamesLoaded = isWorkspaceDisplayNamesLoaded;
|
|
77608
78330
|
exports.isWorkspaceDisplayNamesLoading = isWorkspaceDisplayNamesLoading;
|
|
77609
78331
|
exports.lineLeaderboardService = lineLeaderboardService;
|
|
77610
78332
|
exports.linesService = linesService;
|
|
77611
78333
|
exports.mergeWithDefaultConfig = mergeWithDefaultConfig;
|
|
77612
78334
|
exports.migrateLegacyConfiguration = migrateLegacyConfiguration;
|
|
78335
|
+
exports.normalizeActionFamily = normalizeActionFamily;
|
|
77613
78336
|
exports.normalizeDateKeyRange = normalizeDateKeyRange;
|
|
77614
78337
|
exports.normalizeRoleLevel = normalizeRoleLevel;
|
|
78338
|
+
exports.normalizeVideoGridMetricMode = normalizeVideoGridMetricMode;
|
|
77615
78339
|
exports.optifyeAgentClient = optifyeAgentClient;
|
|
77616
78340
|
exports.parseDateKeyToDate = parseDateKeyToDate;
|
|
77617
78341
|
exports.parseS3Uri = parseS3Uri;
|