@optifye/dashboard-core 6.12.21 → 6.12.23
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/{automation-Hl2PFMb3.d.mts → automation-C3vudVDH.d.mts} +8 -0
- package/dist/{automation-Hl2PFMb3.d.ts → automation-C3vudVDH.d.ts} +8 -0
- package/dist/automation.d.mts +1 -1
- package/dist/automation.d.ts +1 -1
- package/dist/automation.js +18 -7
- package/dist/automation.mjs +18 -7
- package/dist/index.css +83 -22
- package/dist/index.d.mts +36 -5
- package/dist/index.d.ts +36 -5
- package/dist/index.js +1047 -385
- package/dist/index.mjs +1048 -387
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9933,7 +9933,8 @@ var LinesService = class {
|
|
|
9933
9933
|
line.video_grid_metric_mode,
|
|
9934
9934
|
line.assembly ?? false
|
|
9935
9935
|
),
|
|
9936
|
-
recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7
|
|
9936
|
+
recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7,
|
|
9937
|
+
factoryAreaId: line.factory_area_id ?? null
|
|
9937
9938
|
}));
|
|
9938
9939
|
} catch (error) {
|
|
9939
9940
|
console.error("Error fetching lines:", error);
|
|
@@ -9992,7 +9993,8 @@ var LinesService = class {
|
|
|
9992
9993
|
line.video_grid_metric_mode,
|
|
9993
9994
|
line.assembly ?? false
|
|
9994
9995
|
),
|
|
9995
|
-
recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7
|
|
9996
|
+
recentFlowWindowMinutes: line.recent_flow_window_minutes ?? 7,
|
|
9997
|
+
factoryAreaId: line.factory_area_id ?? null
|
|
9996
9998
|
}));
|
|
9997
9999
|
} catch (error) {
|
|
9998
10000
|
console.error("Error fetching all lines:", error);
|
|
@@ -10059,7 +10061,8 @@ var LinesService = class {
|
|
|
10059
10061
|
data.video_grid_metric_mode,
|
|
10060
10062
|
data.assembly ?? false
|
|
10061
10063
|
),
|
|
10062
|
-
recentFlowWindowMinutes: data.recent_flow_window_minutes ?? 7
|
|
10064
|
+
recentFlowWindowMinutes: data.recent_flow_window_minutes ?? 7,
|
|
10065
|
+
factoryAreaId: data.factory_area_id ?? null
|
|
10063
10066
|
};
|
|
10064
10067
|
} catch (error) {
|
|
10065
10068
|
console.error("Error fetching line:", error);
|
|
@@ -11673,6 +11676,9 @@ var lineLeaderboardService = {
|
|
|
11673
11676
|
if (typeof params.limit === "number") {
|
|
11674
11677
|
searchParams.set("limit", params.limit.toString());
|
|
11675
11678
|
}
|
|
11679
|
+
if (params.includeBelowThreshold) {
|
|
11680
|
+
searchParams.set("include_below_threshold", "true");
|
|
11681
|
+
}
|
|
11676
11682
|
const data = await fetchBackendJson(
|
|
11677
11683
|
supabase,
|
|
11678
11684
|
`/api/dashboard/line-leaderboard-daily?${searchParams.toString()}`
|
|
@@ -14697,11 +14703,22 @@ var transformMonitorWorkspaceMetrics = ({
|
|
|
14697
14703
|
actionType: item.action_type,
|
|
14698
14704
|
actionName: item.action_name
|
|
14699
14705
|
}),
|
|
14706
|
+
factory_area_id: item.factory_area_id ?? null,
|
|
14707
|
+
factory_area_key: item.factory_area_key ?? null,
|
|
14708
|
+
factory_area_name: item.factory_area_name ?? null,
|
|
14709
|
+
factory_area_enabled: item.factory_area_enabled ?? null,
|
|
14710
|
+
leaderboard_metric_kind: item.leaderboard_metric_kind ?? void 0,
|
|
14711
|
+
leaderboard_value: item.leaderboard_value ?? null,
|
|
14712
|
+
avg_recent_flow: item.avg_recent_flow ?? null,
|
|
14700
14713
|
recent_flow_percent: item.recent_flow_percent ?? null,
|
|
14701
14714
|
recent_flow_window_minutes: item.recent_flow_window_minutes ?? null,
|
|
14702
14715
|
recent_flow_effective_end_at: item.recent_flow_effective_end_at ?? null,
|
|
14703
14716
|
recent_flow_computed_at: item.recent_flow_computed_at ?? null,
|
|
14704
14717
|
recent_flow_forced_zero_after_shift: item.recent_flow_forced_zero_after_shift ?? null,
|
|
14718
|
+
video_grid_green_streak_active: item.video_grid_green_streak_active ?? null,
|
|
14719
|
+
video_grid_green_streak_minutes: item.video_grid_green_streak_minutes ?? null,
|
|
14720
|
+
video_grid_green_streak_anchor_at: item.video_grid_green_streak_anchor_at ?? null,
|
|
14721
|
+
video_grid_green_streak_started_at: item.video_grid_green_streak_started_at ?? null,
|
|
14705
14722
|
scheduled_break_active: item.scheduled_break_active ?? false,
|
|
14706
14723
|
incoming_wip_current: item.incoming_wip_current ?? null,
|
|
14707
14724
|
incoming_wip_effective_at: item.incoming_wip_effective_at ?? null,
|
|
@@ -14721,12 +14738,12 @@ var logDebug = (...args) => {
|
|
|
14721
14738
|
if (!DEBUG_DASHBOARD_LOGS) return;
|
|
14722
14739
|
console.log(...args);
|
|
14723
14740
|
};
|
|
14724
|
-
var buildMetricsScopeKey = (lineId, lineIds) => {
|
|
14741
|
+
var buildMetricsScopeKey = (lineId, lineIds, blueComparisonLineIds) => {
|
|
14725
14742
|
const normalizedLineIds = Array.from(new Set((lineIds || []).filter(Boolean))).sort();
|
|
14726
|
-
|
|
14727
|
-
|
|
14728
|
-
|
|
14729
|
-
return lineId
|
|
14743
|
+
const normalizedBlueComparisonLineIds = Array.from(new Set((blueComparisonLineIds || []).filter(Boolean))).sort();
|
|
14744
|
+
const lineKey = normalizedLineIds.length > 0 ? normalizedLineIds.join(",") : lineId;
|
|
14745
|
+
const comparisonKey = normalizedBlueComparisonLineIds.length > 0 ? normalizedBlueComparisonLineIds.join(",") : lineKey;
|
|
14746
|
+
return `${lineId}|${lineKey}|blue:${comparisonKey}`;
|
|
14730
14747
|
};
|
|
14731
14748
|
var parseEfficiencyLegend = (legend) => {
|
|
14732
14749
|
if (!legend) return null;
|
|
@@ -14748,6 +14765,7 @@ var useDashboardMetrics = ({
|
|
|
14748
14765
|
onLineMetricsUpdate,
|
|
14749
14766
|
lineId,
|
|
14750
14767
|
lineIds,
|
|
14768
|
+
blueComparisonLineIds,
|
|
14751
14769
|
userAccessibleLineIds,
|
|
14752
14770
|
enabled = true
|
|
14753
14771
|
}) => {
|
|
@@ -14770,6 +14788,10 @@ var useDashboardMetrics = ({
|
|
|
14770
14788
|
const sourceLineIds = lineIds !== void 0 ? lineIds : userAccessibleLineIds !== void 0 ? userAccessibleLineIds : configuredLineIds;
|
|
14771
14789
|
return Array.from(new Set((sourceLineIds || []).filter(Boolean)));
|
|
14772
14790
|
}, [lineIds, userAccessibleLineIds, configuredLineIds]);
|
|
14791
|
+
const normalizedBlueComparisonLineIds = React144.useMemo(
|
|
14792
|
+
() => Array.from(new Set((blueComparisonLineIds || []).filter(Boolean))),
|
|
14793
|
+
[blueComparisonLineIds]
|
|
14794
|
+
);
|
|
14773
14795
|
const { shiftConfig: staticShiftConfig } = useDashboardConfig();
|
|
14774
14796
|
const {
|
|
14775
14797
|
shiftConfigMap: multiLineShiftConfigMap,
|
|
@@ -14807,7 +14829,7 @@ var useDashboardMetrics = ({
|
|
|
14807
14829
|
const supabase = useSupabase();
|
|
14808
14830
|
const [metrics2, setMetrics] = React144.useState({ workspaceMetrics: [], lineMetrics: [] });
|
|
14809
14831
|
const [metricsLineId, setMetricsLineId] = React144.useState(lineId ?? null);
|
|
14810
|
-
const [metricsScopeKey, setMetricsScopeKey] = React144.useState(() => buildMetricsScopeKey(lineId, lineIds));
|
|
14832
|
+
const [metricsScopeKey, setMetricsScopeKey] = React144.useState(() => buildMetricsScopeKey(lineId, lineIds, blueComparisonLineIds));
|
|
14811
14833
|
const [isLoading, setIsLoading] = React144.useState(true);
|
|
14812
14834
|
const [error, setError] = React144.useState(null);
|
|
14813
14835
|
const lineIdRef = React144.useRef(lineId);
|
|
@@ -14849,8 +14871,12 @@ var useDashboardMetrics = ({
|
|
|
14849
14871
|
[entityConfig.companyId]
|
|
14850
14872
|
);
|
|
14851
14873
|
const requestedScopeKey = React144.useMemo(
|
|
14852
|
-
() => buildMetricsScopeKey(
|
|
14853
|
-
|
|
14874
|
+
() => buildMetricsScopeKey(
|
|
14875
|
+
lineId,
|
|
14876
|
+
isFactoryView ? targetFactoryLineIds : void 0,
|
|
14877
|
+
normalizedBlueComparisonLineIds.length ? normalizedBlueComparisonLineIds : void 0
|
|
14878
|
+
),
|
|
14879
|
+
[isFactoryView, lineId, targetFactoryLineIds, normalizedBlueComparisonLineIds]
|
|
14854
14880
|
);
|
|
14855
14881
|
React144.useEffect(() => {
|
|
14856
14882
|
lineIdRef.current = lineId;
|
|
@@ -14880,12 +14906,15 @@ var useDashboardMetrics = ({
|
|
|
14880
14906
|
const isFactory = currentLineIdToUse === factoryViewId;
|
|
14881
14907
|
const targetLineIds = isFactory ? targetFactoryLineIds : [currentLineIdToUse];
|
|
14882
14908
|
const targetLineIdsKey = targetLineIds.slice().sort().join(",");
|
|
14909
|
+
const effectiveBlueComparisonLineIds = normalizedBlueComparisonLineIds.length ? normalizedBlueComparisonLineIds : targetLineIds;
|
|
14910
|
+
const blueComparisonLineIdsKey = effectiveBlueComparisonLineIds.slice().sort().join(",");
|
|
14883
14911
|
const usesShiftGroups = isFactory && shiftGroups.length > 0;
|
|
14884
14912
|
const singleShiftDetails = usesShiftGroups ? null : shiftConfig ? getCurrentShift(defaultTimezone, shiftConfig) : shiftGroups.length === 1 ? { date: shiftGroups[0].date, shiftId: shiftGroups[0].shiftId } : getCurrentShift(defaultTimezone, staticShiftConfig);
|
|
14885
|
-
const fetchKey = usesShiftGroups ? `factory|${companyId || "unknown"}|${shiftGroupsKey}` : isFactory ? `factory|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}|${targetLineIdsKey}` : `${currentLineIdToUse}|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}`;
|
|
14913
|
+
const fetchKey = usesShiftGroups ? `factory|${companyId || "unknown"}|${shiftGroupsKey}|blue:${blueComparisonLineIdsKey}` : isFactory ? `factory|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}|${targetLineIdsKey}|blue:${blueComparisonLineIdsKey}` : `${currentLineIdToUse}|${companyId || "unknown"}|${singleShiftDetails?.date}|${singleShiftDetails?.shiftId}|blue:${blueComparisonLineIdsKey}`;
|
|
14886
14914
|
const responseScopeKey = buildMetricsScopeKey(
|
|
14887
14915
|
currentLineIdToUse,
|
|
14888
|
-
isFactory ? targetLineIds : void 0
|
|
14916
|
+
isFactory ? targetLineIds : void 0,
|
|
14917
|
+
normalizedBlueComparisonLineIds.length ? normalizedBlueComparisonLineIds : void 0
|
|
14889
14918
|
);
|
|
14890
14919
|
logDebug("[useDashboardMetrics] Fetch key details:", {
|
|
14891
14920
|
isFactory,
|
|
@@ -14915,6 +14944,7 @@ var useDashboardMetrics = ({
|
|
|
14915
14944
|
logDebug("[useDashboardMetrics] Skipping fetch: no target line IDs after scope filtering");
|
|
14916
14945
|
setMetrics({
|
|
14917
14946
|
workspaceMetrics: [],
|
|
14947
|
+
blueComparisonWorkspaceMetrics: [],
|
|
14918
14948
|
lineMetrics: [],
|
|
14919
14949
|
metadata: void 0,
|
|
14920
14950
|
efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND
|
|
@@ -14925,6 +14955,7 @@ var useDashboardMetrics = ({
|
|
|
14925
14955
|
return;
|
|
14926
14956
|
}
|
|
14927
14957
|
let allWorkspaceMetrics = [];
|
|
14958
|
+
let allBlueComparisonWorkspaceMetrics = [];
|
|
14928
14959
|
let allLineMetrics = [];
|
|
14929
14960
|
let hasFlowBuffers = false;
|
|
14930
14961
|
let idleTimeVlmByLine = {};
|
|
@@ -14932,7 +14963,8 @@ var useDashboardMetrics = ({
|
|
|
14932
14963
|
const forceParam = force ? "&force_refresh=true" : "";
|
|
14933
14964
|
const buildMetricsEndpoint = (params) => {
|
|
14934
14965
|
const lineIdsParam = isFactory ? `line_ids=${params.groupLineIds.join(",")}` : `line_id=${params.groupLineIds[0]}`;
|
|
14935
|
-
|
|
14966
|
+
const blueComparisonParam = effectiveBlueComparisonLineIds.length ? `&blue_comparison_line_ids=${effectiveBlueComparisonLineIds.join(",")}` : "";
|
|
14967
|
+
return `/api/dashboard/metrics?${lineIdsParam}${blueComparisonParam}&date=${params.date}&shift_id=${params.shiftId}&company_id=${companyId}${forceParam}`;
|
|
14936
14968
|
};
|
|
14937
14969
|
if (usesShiftGroups) {
|
|
14938
14970
|
logDebug("[useDashboardMetrics] Factory view shift groups fetch:", {
|
|
@@ -14982,10 +15014,16 @@ var useDashboardMetrics = ({
|
|
|
14982
15014
|
if (result.workspace_metrics) {
|
|
14983
15015
|
allWorkspaceMetrics.push(...result.workspace_metrics);
|
|
14984
15016
|
}
|
|
15017
|
+
if (result.blue_comparison_workspace_metrics) {
|
|
15018
|
+
allBlueComparisonWorkspaceMetrics.push(...result.blue_comparison_workspace_metrics);
|
|
15019
|
+
}
|
|
14985
15020
|
if (result.line_metrics) {
|
|
14986
15021
|
allLineMetrics.push(...result.line_metrics);
|
|
14987
15022
|
}
|
|
14988
15023
|
});
|
|
15024
|
+
if (allBlueComparisonWorkspaceMetrics.length === 0) {
|
|
15025
|
+
allBlueComparisonWorkspaceMetrics = allWorkspaceMetrics;
|
|
15026
|
+
}
|
|
14989
15027
|
logDebug(`[useDashboardMetrics] \u{1F4CA} Merged metrics from ${results.length} shift groups:`, {
|
|
14990
15028
|
workspaceCount: allWorkspaceMetrics.length,
|
|
14991
15029
|
lineMetricsCount: allLineMetrics.length
|
|
@@ -15023,6 +15061,7 @@ var useDashboardMetrics = ({
|
|
|
15023
15061
|
lineCount: backendData.line_metrics?.length || 0
|
|
15024
15062
|
});
|
|
15025
15063
|
allWorkspaceMetrics = backendData.workspace_metrics || [];
|
|
15064
|
+
allBlueComparisonWorkspaceMetrics = backendData.blue_comparison_workspace_metrics || allWorkspaceMetrics;
|
|
15026
15065
|
allLineMetrics = backendData.line_metrics || [];
|
|
15027
15066
|
hasFlowBuffers = Boolean(backendData?.metadata?.has_flow_buffers);
|
|
15028
15067
|
if (backendData?.metadata?.idle_time_vlm_by_line && typeof backendData.metadata.idle_time_vlm_by_line === "object") {
|
|
@@ -15041,8 +15080,19 @@ var useDashboardMetrics = ({
|
|
|
15041
15080
|
shouldOverrideShiftType: (metricLineId) => isFactoryView ? Boolean(multiLineShiftConfigMap.get(metricLineId)) : Boolean(shiftConfig),
|
|
15042
15081
|
fallbackShiftConfig: staticShiftConfig
|
|
15043
15082
|
});
|
|
15083
|
+
const transformedBlueComparisonWorkspaceData = allBlueComparisonWorkspaceMetrics === allWorkspaceMetrics ? transformedWorkspaceData : transformMonitorWorkspaceMetrics({
|
|
15084
|
+
rows: allBlueComparisonWorkspaceMetrics,
|
|
15085
|
+
companyId: companyId || "",
|
|
15086
|
+
workspaceConfig: effectiveWorkspaceConfig,
|
|
15087
|
+
appTimezone: detailTimezone,
|
|
15088
|
+
lineMetrics: allLineMetrics,
|
|
15089
|
+
resolveShiftConfig: (metricLineId) => isFactoryView ? multiLineShiftConfigMap.get(metricLineId) || staticShiftConfig : shiftConfig || staticShiftConfig,
|
|
15090
|
+
shouldOverrideShiftType: (metricLineId) => isFactoryView ? Boolean(multiLineShiftConfigMap.get(metricLineId)) : Boolean(shiftConfig),
|
|
15091
|
+
fallbackShiftConfig: staticShiftConfig
|
|
15092
|
+
});
|
|
15044
15093
|
const newMetricsState = {
|
|
15045
15094
|
workspaceMetrics: transformedWorkspaceData,
|
|
15095
|
+
blueComparisonWorkspaceMetrics: transformedBlueComparisonWorkspaceData.length ? transformedBlueComparisonWorkspaceData : transformedWorkspaceData,
|
|
15046
15096
|
lineMetrics: allLineMetrics || [],
|
|
15047
15097
|
metadata: { hasFlowBuffers, idleTimeVlmByLine },
|
|
15048
15098
|
efficiencyLegend: efficiencyLegend ?? DEFAULT_EFFICIENCY_LEGEND
|
|
@@ -15113,6 +15163,7 @@ var useDashboardMetrics = ({
|
|
|
15113
15163
|
shiftGroupsKey,
|
|
15114
15164
|
configuredLineIds,
|
|
15115
15165
|
targetFactoryLineIds,
|
|
15166
|
+
normalizedBlueComparisonLineIds,
|
|
15116
15167
|
isFactoryView,
|
|
15117
15168
|
multiLineShiftConfigMap,
|
|
15118
15169
|
staticShiftConfig,
|
|
@@ -15553,9 +15604,10 @@ var useDashboardMetrics = ({
|
|
|
15553
15604
|
const isCurrentScopeResolved = metricsScopeKey === requestedScopeKey;
|
|
15554
15605
|
const hasLastGoodMetrics = metrics2.workspaceMetrics.length > 0 || metrics2.lineMetrics.length > 0;
|
|
15555
15606
|
const canReuseLastGoodMetrics = hasLastGoodMetrics && !isCurrentScopeResolved && (isLoading || !!error);
|
|
15556
|
-
const safeMetrics = isCurrentScopeResolved || canReuseLastGoodMetrics ? metrics2 : { workspaceMetrics: [], lineMetrics: [], metadata: void 0, efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND };
|
|
15607
|
+
const safeMetrics = isCurrentScopeResolved || canReuseLastGoodMetrics ? metrics2 : { workspaceMetrics: [], blueComparisonWorkspaceMetrics: [], lineMetrics: [], metadata: void 0, efficiencyLegend: DEFAULT_EFFICIENCY_LEGEND };
|
|
15557
15608
|
return {
|
|
15558
15609
|
workspaceMetrics: safeMetrics?.workspaceMetrics || [],
|
|
15610
|
+
blueComparisonWorkspaceMetrics: safeMetrics?.blueComparisonWorkspaceMetrics || safeMetrics?.workspaceMetrics || [],
|
|
15559
15611
|
lineMetrics: safeMetrics?.lineMetrics || [],
|
|
15560
15612
|
efficiencyLegend: safeMetrics?.efficiencyLegend || DEFAULT_EFFICIENCY_LEGEND,
|
|
15561
15613
|
metadata: safeMetrics?.metadata,
|
|
@@ -22173,6 +22225,77 @@ var buildKpiLineHierarchy = (lines) => {
|
|
|
22173
22225
|
};
|
|
22174
22226
|
};
|
|
22175
22227
|
|
|
22228
|
+
// src/lib/utils/leaderboardGrouping.ts
|
|
22229
|
+
var isFiniteNumber2 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
22230
|
+
var getEnabledFactoryArea = (line) => {
|
|
22231
|
+
if (!line.factory_area_id) return null;
|
|
22232
|
+
if (line.factory_area_enabled !== true) return null;
|
|
22233
|
+
const areaName = line.factory_area_name?.trim();
|
|
22234
|
+
if (!areaName) return null;
|
|
22235
|
+
return { id: line.factory_area_id, name: areaName };
|
|
22236
|
+
};
|
|
22237
|
+
var getLineEfficiency = (lineId, efficiencyByLineId, isLoading) => {
|
|
22238
|
+
if (efficiencyByLineId.has(lineId)) {
|
|
22239
|
+
const value = efficiencyByLineId.get(lineId);
|
|
22240
|
+
return isFiniteNumber2(value) ? value : null;
|
|
22241
|
+
}
|
|
22242
|
+
if (isLoading) return null;
|
|
22243
|
+
return 0;
|
|
22244
|
+
};
|
|
22245
|
+
var buildLineLeaderboardRows = ({
|
|
22246
|
+
lines,
|
|
22247
|
+
efficiencyByLineId,
|
|
22248
|
+
fallbackEfficiencyByLineId,
|
|
22249
|
+
isLoading
|
|
22250
|
+
}) => {
|
|
22251
|
+
const rows = [];
|
|
22252
|
+
const areaGroups = /* @__PURE__ */ new Map();
|
|
22253
|
+
lines.forEach((line) => {
|
|
22254
|
+
const area = getEnabledFactoryArea(line);
|
|
22255
|
+
if (!area) {
|
|
22256
|
+
const efficiency = getLineEfficiency(line.id, efficiencyByLineId, isLoading);
|
|
22257
|
+
rows.push({
|
|
22258
|
+
rowType: "line",
|
|
22259
|
+
id: line.id,
|
|
22260
|
+
displayName: line.line_name,
|
|
22261
|
+
line,
|
|
22262
|
+
lines: [line],
|
|
22263
|
+
efficiency,
|
|
22264
|
+
sortValue: isFiniteNumber2(efficiency) ? efficiency : -1
|
|
22265
|
+
});
|
|
22266
|
+
return;
|
|
22267
|
+
}
|
|
22268
|
+
const group = areaGroups.get(area.id);
|
|
22269
|
+
if (group) {
|
|
22270
|
+
group.lines.push(line);
|
|
22271
|
+
return;
|
|
22272
|
+
}
|
|
22273
|
+
areaGroups.set(area.id, {
|
|
22274
|
+
areaId: area.id,
|
|
22275
|
+
areaName: area.name,
|
|
22276
|
+
lines: [line]
|
|
22277
|
+
});
|
|
22278
|
+
});
|
|
22279
|
+
areaGroups.forEach((group) => {
|
|
22280
|
+
const validEfficiencies = group.lines.map((line) => efficiencyByLineId.get(line.id)).filter(isFiniteNumber2);
|
|
22281
|
+
const fallbackEfficiencies = validEfficiencies.length === 0 ? group.lines.map((line) => fallbackEfficiencyByLineId?.get(line.id)).filter(isFiniteNumber2) : [];
|
|
22282
|
+
const efficiencyValues = validEfficiencies.length > 0 ? validEfficiencies : fallbackEfficiencies;
|
|
22283
|
+
const shouldRenderZeroFallback = efficiencyValues.length === 0 && !!fallbackEfficiencyByLineId && !isLoading;
|
|
22284
|
+
if (efficiencyValues.length === 0 && !shouldRenderZeroFallback) return;
|
|
22285
|
+
const efficiency = shouldRenderZeroFallback ? 0 : efficiencyValues.reduce((sum, value) => sum + value, 0) / efficiencyValues.length;
|
|
22286
|
+
rows.push({
|
|
22287
|
+
rowType: "area",
|
|
22288
|
+
id: `area:${group.areaId}`,
|
|
22289
|
+
displayName: group.areaName,
|
|
22290
|
+
areaId: group.areaId,
|
|
22291
|
+
lines: group.lines,
|
|
22292
|
+
efficiency,
|
|
22293
|
+
sortValue: efficiency
|
|
22294
|
+
});
|
|
22295
|
+
});
|
|
22296
|
+
return rows.sort((left, right) => right.sortValue - left.sortValue).map((row, index) => ({ ...row, rank: index + 1 }));
|
|
22297
|
+
};
|
|
22298
|
+
|
|
22176
22299
|
// src/lib/utils/awards.ts
|
|
22177
22300
|
var toNumber2 = (value) => {
|
|
22178
22301
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
@@ -37459,7 +37582,58 @@ HourlyOutputChart.displayName = "HourlyOutputChart";
|
|
|
37459
37582
|
// src/components/dashboard/grid/videoGridMetricUtils.ts
|
|
37460
37583
|
var VIDEO_GRID_LEGEND_LABEL = "Real-Time efficiency";
|
|
37461
37584
|
var MAP_GRID_LEGEND_LABEL = "Efficiency";
|
|
37462
|
-
var
|
|
37585
|
+
var GREEN_STREAK_FRESHNESS_GRACE_MS = 2 * 60 * 1e3;
|
|
37586
|
+
var CONFIRMED_MINUTE_DURATION_MS = 60 * 1e3;
|
|
37587
|
+
var RECENT_FLOW_COMPUTED_FRESHNESS_MS = 120 * 1e3;
|
|
37588
|
+
var isFiniteNumber3 = (value) => typeof value === "number" && Number.isFinite(value);
|
|
37589
|
+
var padTwoDigits = (value) => String(value).padStart(2, "0");
|
|
37590
|
+
var parseTimestampMs = (value) => {
|
|
37591
|
+
if (!value) {
|
|
37592
|
+
return Number.NaN;
|
|
37593
|
+
}
|
|
37594
|
+
const timestampMs = Date.parse(value);
|
|
37595
|
+
return Number.isFinite(timestampMs) ? timestampMs : Number.NaN;
|
|
37596
|
+
};
|
|
37597
|
+
var isAllGreenStreakFresh = (workspace, anchorAtMs, nowMs2) => {
|
|
37598
|
+
const computedAt = workspace.recent_flow_computed_at;
|
|
37599
|
+
if (typeof computedAt === "string" && computedAt.trim()) {
|
|
37600
|
+
const computedAtMs = parseTimestampMs(computedAt);
|
|
37601
|
+
return Number.isFinite(computedAtMs) && nowMs2 - computedAtMs <= RECENT_FLOW_COMPUTED_FRESHNESS_MS;
|
|
37602
|
+
}
|
|
37603
|
+
return Number.isFinite(anchorAtMs) && nowMs2 <= anchorAtMs + CONFIRMED_MINUTE_DURATION_MS + GREEN_STREAK_FRESHNESS_GRACE_MS;
|
|
37604
|
+
};
|
|
37605
|
+
var formatAllGreenStreakDuration = (elapsedSeconds) => {
|
|
37606
|
+
const safeElapsedSeconds = Math.max(0, Math.floor(elapsedSeconds));
|
|
37607
|
+
const hours = Math.floor(safeElapsedSeconds / 3600);
|
|
37608
|
+
const minutes = Math.floor(safeElapsedSeconds % 3600 / 60);
|
|
37609
|
+
const seconds = safeElapsedSeconds % 60;
|
|
37610
|
+
if (hours > 0) {
|
|
37611
|
+
return `${hours}h ${padTwoDigits(minutes)}m ${padTwoDigits(seconds)}s`;
|
|
37612
|
+
}
|
|
37613
|
+
if (minutes > 0) {
|
|
37614
|
+
return `${minutes}m ${padTwoDigits(seconds)}s`;
|
|
37615
|
+
}
|
|
37616
|
+
return `${seconds}s`;
|
|
37617
|
+
};
|
|
37618
|
+
var getAllGreenStreakMilestone = (elapsedSeconds) => {
|
|
37619
|
+
const safeElapsedSeconds = Math.max(0, Math.floor(elapsedSeconds));
|
|
37620
|
+
const thirtyMinutesSeconds = 30 * 60;
|
|
37621
|
+
const oneHourSeconds = 60 * 60;
|
|
37622
|
+
if (safeElapsedSeconds < thirtyMinutesSeconds) {
|
|
37623
|
+
return null;
|
|
37624
|
+
}
|
|
37625
|
+
if (safeElapsedSeconds < oneHourSeconds) {
|
|
37626
|
+
return {
|
|
37627
|
+
milestoneSeconds: thirtyMinutesSeconds,
|
|
37628
|
+
headline: "30 min"
|
|
37629
|
+
};
|
|
37630
|
+
}
|
|
37631
|
+
const hours = Math.floor(safeElapsedSeconds / oneHourSeconds);
|
|
37632
|
+
return {
|
|
37633
|
+
milestoneSeconds: hours * oneHourSeconds,
|
|
37634
|
+
headline: `${hours * 60} min`
|
|
37635
|
+
};
|
|
37636
|
+
};
|
|
37463
37637
|
var isVideoGridRecentFlowEnabled = (workspace) => isRecentFlowVideoGridMetricMode(
|
|
37464
37638
|
workspace.video_grid_metric_mode,
|
|
37465
37639
|
workspace.assembly_enabled === true
|
|
@@ -37468,11 +37642,11 @@ var isVideoGridWipGated = (workspace) => isWipGatedVideoGridMetricMode(
|
|
|
37468
37642
|
workspace.video_grid_metric_mode,
|
|
37469
37643
|
workspace.assembly_enabled === true
|
|
37470
37644
|
);
|
|
37471
|
-
var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) &&
|
|
37645
|
+
var hasVideoGridRecentFlow = (workspace) => isVideoGridRecentFlowEnabled(workspace) && isFiniteNumber3(workspace.recent_flow_percent);
|
|
37472
37646
|
var isVideoGridRecentFlowUnavailable = (workspace) => isVideoGridRecentFlowEnabled(workspace) && !hasVideoGridRecentFlow(workspace);
|
|
37473
37647
|
var getRawVideoGridMetricValue = (workspace) => {
|
|
37474
37648
|
const recentFlowPercent = workspace.recent_flow_percent;
|
|
37475
|
-
if (hasVideoGridRecentFlow(workspace) &&
|
|
37649
|
+
if (hasVideoGridRecentFlow(workspace) && isFiniteNumber3(recentFlowPercent)) {
|
|
37476
37650
|
return recentFlowPercent;
|
|
37477
37651
|
}
|
|
37478
37652
|
if (isVideoGridRecentFlowUnavailable(workspace)) {
|
|
@@ -37481,9 +37655,63 @@ var getRawVideoGridMetricValue = (workspace) => {
|
|
|
37481
37655
|
return workspace.efficiency;
|
|
37482
37656
|
};
|
|
37483
37657
|
var hasIncomingWipMapping = (workspace) => Boolean(workspace.incoming_wip_buffer_name);
|
|
37658
|
+
var getVideoGridWorkspaceKey = (workspace) => workspace.workspace_uuid || `${workspace.line_id || "unknown"}:${workspace.workspace_name || "unknown"}`;
|
|
37659
|
+
var getVideoGridBlueComparisonGroupKey = (workspace) => {
|
|
37660
|
+
const factoryAreaId = typeof workspace.factory_area_id === "string" ? workspace.factory_area_id.trim() : "";
|
|
37661
|
+
if (factoryAreaId && workspace.factory_area_enabled === true) {
|
|
37662
|
+
return `area:${factoryAreaId}`;
|
|
37663
|
+
}
|
|
37664
|
+
const lineId = typeof workspace.line_id === "string" ? workspace.line_id.trim() : "";
|
|
37665
|
+
return lineId ? `line:${lineId}` : null;
|
|
37666
|
+
};
|
|
37667
|
+
var isVideoGridBlueCandidate = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => hasVideoGridRecentFlow(workspace) && isFiniteNumber3(workspace.recent_flow_percent) && workspace.recent_flow_percent >= legend.green_min;
|
|
37668
|
+
var selectVideoGridBlueWinnerIds = (workspaces, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
37669
|
+
const candidatesByGroup = /* @__PURE__ */ new Map();
|
|
37670
|
+
for (const workspace of workspaces) {
|
|
37671
|
+
if (!isVideoGridBlueCandidate(workspace, legend)) {
|
|
37672
|
+
continue;
|
|
37673
|
+
}
|
|
37674
|
+
const groupKey = getVideoGridBlueComparisonGroupKey(workspace);
|
|
37675
|
+
if (!groupKey) {
|
|
37676
|
+
continue;
|
|
37677
|
+
}
|
|
37678
|
+
const candidates = candidatesByGroup.get(groupKey) || [];
|
|
37679
|
+
candidates.push(workspace);
|
|
37680
|
+
candidatesByGroup.set(groupKey, candidates);
|
|
37681
|
+
}
|
|
37682
|
+
const winners = /* @__PURE__ */ new Set();
|
|
37683
|
+
for (const candidates of candidatesByGroup.values()) {
|
|
37684
|
+
candidates.sort((left, right) => {
|
|
37685
|
+
const leftCurrent = left.recent_flow_percent;
|
|
37686
|
+
const rightCurrent = right.recent_flow_percent;
|
|
37687
|
+
if (rightCurrent !== leftCurrent) {
|
|
37688
|
+
return rightCurrent - leftCurrent;
|
|
37689
|
+
}
|
|
37690
|
+
const leftAverage = isFiniteNumber3(left.avg_recent_flow) ? left.avg_recent_flow : Number.NEGATIVE_INFINITY;
|
|
37691
|
+
const rightAverage = isFiniteNumber3(right.avg_recent_flow) ? right.avg_recent_flow : Number.NEGATIVE_INFINITY;
|
|
37692
|
+
if (rightAverage !== leftAverage) {
|
|
37693
|
+
return rightAverage - leftAverage;
|
|
37694
|
+
}
|
|
37695
|
+
const lineCompare = (left.line_id || "").localeCompare(right.line_id || "");
|
|
37696
|
+
if (lineCompare !== 0) {
|
|
37697
|
+
return lineCompare;
|
|
37698
|
+
}
|
|
37699
|
+
const nameCompare = (left.workspace_name || "").localeCompare(right.workspace_name || "");
|
|
37700
|
+
if (nameCompare !== 0) {
|
|
37701
|
+
return nameCompare;
|
|
37702
|
+
}
|
|
37703
|
+
return getVideoGridWorkspaceKey(left).localeCompare(getVideoGridWorkspaceKey(right));
|
|
37704
|
+
});
|
|
37705
|
+
const winner = candidates[0];
|
|
37706
|
+
if (winner) {
|
|
37707
|
+
winners.add(getVideoGridWorkspaceKey(winner));
|
|
37708
|
+
}
|
|
37709
|
+
}
|
|
37710
|
+
return winners;
|
|
37711
|
+
};
|
|
37484
37712
|
var getVideoGridBaseColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
37485
37713
|
const metricValue = getRawVideoGridMetricValue(workspace);
|
|
37486
|
-
if (!
|
|
37714
|
+
if (!isFiniteNumber3(metricValue)) {
|
|
37487
37715
|
return "neutral";
|
|
37488
37716
|
}
|
|
37489
37717
|
return getEfficiencyColor(metricValue, legend);
|
|
@@ -37504,7 +37732,7 @@ var isLowWipGreenOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
|
37504
37732
|
if (!hasIncomingWipMapping(workspace)) {
|
|
37505
37733
|
return false;
|
|
37506
37734
|
}
|
|
37507
|
-
return
|
|
37735
|
+
return isFiniteNumber3(workspace.incoming_wip_current) && workspace.incoming_wip_current <= 1;
|
|
37508
37736
|
};
|
|
37509
37737
|
var isHighEfficiencyRedFlowOverride = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
37510
37738
|
if (workspace.scheduled_break_active === true) {
|
|
@@ -37522,7 +37750,7 @@ var isHighEfficiencyRedFlowOverride = (workspace, legend = DEFAULT_EFFICIENCY_LE
|
|
|
37522
37750
|
if (getVideoGridBaseColorState(workspace, legend) !== "red") {
|
|
37523
37751
|
return false;
|
|
37524
37752
|
}
|
|
37525
|
-
return
|
|
37753
|
+
return isFiniteNumber3(workspace.efficiency) && workspace.efficiency > 100;
|
|
37526
37754
|
};
|
|
37527
37755
|
var getVideoGridMetricValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => isHighEfficiencyRedFlowOverride(workspace, legend) ? workspace.efficiency : getRawVideoGridMetricValue(workspace);
|
|
37528
37756
|
var toMinuteBucket = (minuteBucket) => Number.isFinite(minuteBucket) ? Math.floor(minuteBucket) : Math.floor(Date.now() / 6e4);
|
|
@@ -37551,7 +37779,10 @@ var getSyntheticLowWipDisplayValue = (workspace, minuteBucket) => {
|
|
|
37551
37779
|
return 100 + offset;
|
|
37552
37780
|
};
|
|
37553
37781
|
var getVideoGridDisplayValue = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, minuteBucket) => isLowWipGreenOverride(workspace, legend) ? getSyntheticLowWipDisplayValue(workspace, minuteBucket) : getVideoGridMetricValue(workspace, legend);
|
|
37554
|
-
var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
37782
|
+
var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND, blueWinnerIds) => {
|
|
37783
|
+
if (blueWinnerIds?.has(getVideoGridWorkspaceKey(workspace)) && isVideoGridBlueCandidate(workspace, legend)) {
|
|
37784
|
+
return "blue";
|
|
37785
|
+
}
|
|
37555
37786
|
const baseColor = getVideoGridBaseColorState(workspace, legend);
|
|
37556
37787
|
if (!hasVideoGridRecentFlow(workspace)) {
|
|
37557
37788
|
return baseColor;
|
|
@@ -37571,11 +37802,56 @@ var getVideoGridColorState = (workspace, legend = DEFAULT_EFFICIENCY_LEGEND) =>
|
|
|
37571
37802
|
if (!hasIncomingWipMapping(workspace)) {
|
|
37572
37803
|
return baseColor;
|
|
37573
37804
|
}
|
|
37574
|
-
if (!
|
|
37805
|
+
if (!isFiniteNumber3(workspace.incoming_wip_current)) {
|
|
37575
37806
|
return "neutral";
|
|
37576
37807
|
}
|
|
37577
37808
|
return baseColor;
|
|
37578
37809
|
};
|
|
37810
|
+
var hasAllVideoGridWorkspacesGreen = (workspaces, legend = DEFAULT_EFFICIENCY_LEGEND) => {
|
|
37811
|
+
const visibleWorkspaces = workspaces.filter((workspace) => Boolean(workspace.workspace_uuid || workspace.workspace_name));
|
|
37812
|
+
return visibleWorkspaces.length > 0 && visibleWorkspaces.every((workspace) => getVideoGridColorState(workspace, legend) === "green");
|
|
37813
|
+
};
|
|
37814
|
+
var getAllVideoGridGreenStreakDisplay = (workspaces, legend = DEFAULT_EFFICIENCY_LEGEND, nowMs2 = Date.now()) => {
|
|
37815
|
+
const visibleWorkspaces = workspaces.filter((workspace) => Boolean(workspace.workspace_uuid || workspace.workspace_name));
|
|
37816
|
+
if (visibleWorkspaces.length === 0 || !hasAllVideoGridWorkspacesGreen(visibleWorkspaces, legend)) {
|
|
37817
|
+
return null;
|
|
37818
|
+
}
|
|
37819
|
+
const activeStreaks = visibleWorkspaces.map((workspace) => {
|
|
37820
|
+
const startedAt = workspace.video_grid_green_streak_started_at;
|
|
37821
|
+
const anchorAt = workspace.video_grid_green_streak_anchor_at;
|
|
37822
|
+
const streakMinutes = workspace.video_grid_green_streak_minutes;
|
|
37823
|
+
const computedAt = workspace.recent_flow_computed_at;
|
|
37824
|
+
const startedAtMs = parseTimestampMs(startedAt);
|
|
37825
|
+
const anchorAtMs = parseTimestampMs(anchorAt);
|
|
37826
|
+
const computedAtMs = typeof computedAt === "string" && computedAt.trim() ? parseTimestampMs(computedAt) : Number.NaN;
|
|
37827
|
+
const isFresh = isAllGreenStreakFresh(workspace, anchorAtMs, nowMs2);
|
|
37828
|
+
const tickOriginAtMs = Number.isFinite(computedAtMs) ? computedAtMs : anchorAtMs + CONFIRMED_MINUTE_DURATION_MS;
|
|
37829
|
+
if (workspace.video_grid_green_streak_active === true && isFiniteNumber3(streakMinutes) && streakMinutes > 0 && startedAt && anchorAt && Number.isFinite(startedAtMs) && isFresh) {
|
|
37830
|
+
return {
|
|
37831
|
+
startedAt,
|
|
37832
|
+
startedAtMs,
|
|
37833
|
+
anchorAt,
|
|
37834
|
+
streakMinutes,
|
|
37835
|
+
tickOriginAtMs
|
|
37836
|
+
};
|
|
37837
|
+
}
|
|
37838
|
+
return null;
|
|
37839
|
+
});
|
|
37840
|
+
if (activeStreaks.some((streak) => streak === null)) {
|
|
37841
|
+
return null;
|
|
37842
|
+
}
|
|
37843
|
+
const strictestStartedAt = activeStreaks.reduce((latest, current) => current.streakMinutes < latest.streakMinutes || current.streakMinutes === latest.streakMinutes && current.startedAtMs > latest.startedAtMs ? current : latest);
|
|
37844
|
+
const confirmedSeconds = Math.max(0, Math.floor(strictestStartedAt.streakMinutes * 60));
|
|
37845
|
+
return {
|
|
37846
|
+
label: "All green",
|
|
37847
|
+
elapsedSeconds: confirmedSeconds,
|
|
37848
|
+
confirmedSeconds,
|
|
37849
|
+
durationText: formatAllGreenStreakDuration(confirmedSeconds),
|
|
37850
|
+
startedAt: strictestStartedAt.startedAt,
|
|
37851
|
+
anchorAt: strictestStartedAt.anchorAt,
|
|
37852
|
+
tickOriginAtMs: strictestStartedAt.tickOriginAtMs
|
|
37853
|
+
};
|
|
37854
|
+
};
|
|
37579
37855
|
var getVideoGridLegendLabel = (workspaces) => {
|
|
37580
37856
|
const visibleWorkspaces = workspaces;
|
|
37581
37857
|
if (visibleWorkspaces.length === 0) {
|
|
@@ -37606,6 +37882,7 @@ var VideoCard = React144__namespace.default.memo(({
|
|
|
37606
37882
|
compact = false,
|
|
37607
37883
|
displayMinuteBucket,
|
|
37608
37884
|
displayName,
|
|
37885
|
+
isBlueBest = false,
|
|
37609
37886
|
lastSeenLabel,
|
|
37610
37887
|
hasRecentHealthSignal: hasRecentHealthSignal2 = false,
|
|
37611
37888
|
onMouseEnter,
|
|
@@ -37627,7 +37904,11 @@ var VideoCard = React144__namespace.default.memo(({
|
|
|
37627
37904
|
const workspaceDisplayName = displayName || workspace.displayName || workspace.workspace_name;
|
|
37628
37905
|
const videoGridMetricValue = getVideoGridMetricValue(workspace, effectiveLegend);
|
|
37629
37906
|
const videoGridDisplayValue = getVideoGridDisplayValue(workspace, effectiveLegend, displayMinuteBucket);
|
|
37630
|
-
const videoGridColorState = getVideoGridColorState(
|
|
37907
|
+
const videoGridColorState = getVideoGridColorState(
|
|
37908
|
+
workspace,
|
|
37909
|
+
effectiveLegend,
|
|
37910
|
+
isBlueBest ? /* @__PURE__ */ new Set([getVideoGridWorkspaceKey(workspace)]) : void 0
|
|
37911
|
+
);
|
|
37631
37912
|
const isRecentFlowCard = isVideoGridRecentFlowEnabled(workspace);
|
|
37632
37913
|
const isHighEfficiencyOverride = isHighEfficiencyRedFlowOverride(workspace, effectiveLegend);
|
|
37633
37914
|
const hasDisplayMetric = typeof videoGridDisplayValue === "number" && Number.isFinite(videoGridDisplayValue);
|
|
@@ -37635,9 +37916,9 @@ var VideoCard = React144__namespace.default.memo(({
|
|
|
37635
37916
|
const shouldRenderMetricBadge = hasDisplayMetric;
|
|
37636
37917
|
const badgeTitle = isHighEfficiencyOverride ? `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%` : hasVideoGridRecentFlow(workspace) ? `Flow ${Math.round(videoGridDisplayValue ?? 0)}%` : isRecentFlowCard ? "Flow unavailable" : `Efficiency ${Math.round(videoGridDisplayValue ?? 0)}%`;
|
|
37637
37918
|
const badgeLabel = `${Math.round(videoGridDisplayValue ?? 0)}%`;
|
|
37638
|
-
const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
|
|
37639
|
-
const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
|
|
37640
|
-
const efficiencyStatus = videoGridColorState === "green" ? "High" : videoGridColorState === "yellow" ? "Medium" : videoGridColorState === "red" ? "Low" : "Neutral";
|
|
37919
|
+
const efficiencyOverlayClass = videoGridColorState === "green" ? "bg-[#00D654]/25" : videoGridColorState === "blue" ? "bg-[#0EA5E9]/30" : videoGridColorState === "yellow" ? "bg-[#FFD700]/30" : videoGridColorState === "red" ? "bg-[#FF2D0A]/30" : "bg-transparent";
|
|
37920
|
+
const efficiencyBarClass = videoGridColorState === "green" ? "bg-[#00AB45]" : videoGridColorState === "blue" ? "bg-[#0EA5E9]" : videoGridColorState === "yellow" ? "bg-[#FFB020]" : videoGridColorState === "red" ? "bg-[#E34329]" : "bg-gray-500/70";
|
|
37921
|
+
const efficiencyStatus = videoGridColorState === "green" ? "High" : videoGridColorState === "blue" ? "Best" : videoGridColorState === "yellow" ? "Medium" : videoGridColorState === "red" ? "Low" : "Neutral";
|
|
37641
37922
|
const trendInfo = workspace.trend !== void 0 ? getTrendArrowAndColor(workspace.trend) : null;
|
|
37642
37923
|
const handleClick = React144.useCallback(() => {
|
|
37643
37924
|
trackCoreEvent("Workspace Card Clicked", {
|
|
@@ -37758,6 +38039,9 @@ var VideoCard = React144__namespace.default.memo(({
|
|
|
37758
38039
|
if (prevProps.displayName !== nextProps.displayName) {
|
|
37759
38040
|
return false;
|
|
37760
38041
|
}
|
|
38042
|
+
if (prevProps.isBlueBest !== nextProps.isBlueBest) {
|
|
38043
|
+
return false;
|
|
38044
|
+
}
|
|
37761
38045
|
if (prevProps.lastSeenLabel !== nextProps.lastSeenLabel) {
|
|
37762
38046
|
return false;
|
|
37763
38047
|
}
|
|
@@ -37799,6 +38083,7 @@ var hasRecentHealthSignal = (lastHeartbeat) => {
|
|
|
37799
38083
|
};
|
|
37800
38084
|
var VideoGridView = React144__namespace.default.memo(({
|
|
37801
38085
|
workspaces,
|
|
38086
|
+
blueComparisonWorkspaces,
|
|
37802
38087
|
selectedLine,
|
|
37803
38088
|
className = "",
|
|
37804
38089
|
legend,
|
|
@@ -37927,6 +38212,7 @@ var VideoGridView = React144__namespace.default.memo(({
|
|
|
37927
38212
|
return a.workspace_name.localeCompare(b.workspace_name);
|
|
37928
38213
|
});
|
|
37929
38214
|
}, [filteredWorkspaces]);
|
|
38215
|
+
const blueWinnerIds = React144.useMemo(() => selectVideoGridBlueWinnerIds(blueComparisonWorkspaces || sortedWorkspaces, effectiveLegend), [blueComparisonWorkspaces, sortedWorkspaces, effectiveLegend]);
|
|
37930
38216
|
const streamsResolvedForWorkspaceSet = resolvedStreamWorkspaceKey === workspaceIdsKey;
|
|
37931
38217
|
const resolveWorkspaceDisplayName = React144.useCallback((workspace) => {
|
|
37932
38218
|
return workspace.displayName || displayNames[`${workspace.line_id}_${workspace.workspace_name}`] || workspace.workspace_name;
|
|
@@ -38135,11 +38421,13 @@ var VideoGridView = React144__namespace.default.memo(({
|
|
|
38135
38421
|
isR2Stream,
|
|
38136
38422
|
shouldPlay,
|
|
38137
38423
|
lastSeenLabel,
|
|
38138
|
-
hasRecentHealthSignal: hasRecentHealthSignal(workspaceHealth?.lastHeartbeat)
|
|
38424
|
+
hasRecentHealthSignal: hasRecentHealthSignal(workspaceHealth?.lastHeartbeat),
|
|
38425
|
+
isBlueBest: blueWinnerIds.has(getVideoGridWorkspaceKey(workspace))
|
|
38139
38426
|
};
|
|
38140
38427
|
});
|
|
38141
38428
|
}, [
|
|
38142
38429
|
sortedWorkspaces,
|
|
38430
|
+
blueWinnerIds,
|
|
38143
38431
|
visibleWorkspaces,
|
|
38144
38432
|
getWorkspaceCropping,
|
|
38145
38433
|
videoStreamsByWorkspaceId,
|
|
@@ -38186,6 +38474,7 @@ var VideoGridView = React144__namespace.default.memo(({
|
|
|
38186
38474
|
useRAF: effectiveUseRAF,
|
|
38187
38475
|
displayMinuteBucket,
|
|
38188
38476
|
compact: !selectedLine,
|
|
38477
|
+
isBlueBest: card.isBlueBest,
|
|
38189
38478
|
onMouseEnter: onWorkspaceHover ? () => onWorkspaceHover(card.workspaceId) : void 0,
|
|
38190
38479
|
onMouseLeave: onWorkspaceHoverEnd ? () => onWorkspaceHoverEnd(card.workspaceId) : void 0
|
|
38191
38480
|
}
|
|
@@ -39819,7 +40108,7 @@ var BreakNotificationPopup = ({
|
|
|
39819
40108
|
return null;
|
|
39820
40109
|
}
|
|
39821
40110
|
const currentBreak = visibleBreaks[currentIndex];
|
|
39822
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `fixed right-4 top-24 z-
|
|
40111
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `fixed right-4 top-24 z-[110] max-w-xs w-full ${className}`, children: [
|
|
39823
40112
|
visibleBreaks.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
39824
40113
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
39825
40114
|
"div",
|
|
@@ -54743,6 +55032,10 @@ var Legend5 = ({
|
|
|
54743
55032
|
":"
|
|
54744
55033
|
] }),
|
|
54745
55034
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 sm:gap-4", children: [
|
|
55035
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
55036
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 sm:w-2.5 sm:h-2.5 rounded-full bg-[#0EA5E9]" }),
|
|
55037
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Best" })
|
|
55038
|
+
] }),
|
|
54746
55039
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
54747
55040
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 sm:w-2.5 sm:h-2.5 rounded-full bg-[#00AB45]" }),
|
|
54748
55041
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatPercentRange(effectiveLegend.green_min, effectiveLegend.green_max) })
|
|
@@ -54861,6 +55154,7 @@ var WorkspaceGridItem = React144__namespace.default.memo(({
|
|
|
54861
55154
|
WorkspaceGridItem.displayName = "WorkspaceGridItem";
|
|
54862
55155
|
var WorkspaceGrid = React144__namespace.default.memo(({
|
|
54863
55156
|
workspaces,
|
|
55157
|
+
blueComparisonWorkspaces,
|
|
54864
55158
|
isPdfMode = false,
|
|
54865
55159
|
customWorkspacePositions,
|
|
54866
55160
|
lineNames = {},
|
|
@@ -54877,13 +55171,8 @@ var WorkspaceGrid = React144__namespace.default.memo(({
|
|
|
54877
55171
|
onWorkspaceHoverEnd,
|
|
54878
55172
|
toolbarRightContent
|
|
54879
55173
|
}) => {
|
|
54880
|
-
const
|
|
54881
|
-
const mapViewEnabled = dashboardConfig?.mapViewConfig?.enabled ?? false;
|
|
55174
|
+
const mapViewEnabled = false;
|
|
54882
55175
|
const [viewMode, setViewMode] = React144.useState(() => {
|
|
54883
|
-
if (typeof window !== "undefined" && mapViewEnabled) {
|
|
54884
|
-
const saved = localStorage.getItem("home-view-mode");
|
|
54885
|
-
return saved === "map" || saved === "video" ? saved : "video";
|
|
54886
|
-
}
|
|
54887
55176
|
return "video";
|
|
54888
55177
|
});
|
|
54889
55178
|
React144.useEffect(() => {
|
|
@@ -54892,7 +55181,7 @@ var WorkspaceGrid = React144__namespace.default.memo(({
|
|
|
54892
55181
|
total_workspaces: workspaces.length
|
|
54893
55182
|
});
|
|
54894
55183
|
}, [workspaces.length]);
|
|
54895
|
-
|
|
55184
|
+
React144.useCallback(() => {
|
|
54896
55185
|
const newMode = viewMode === "video" ? "map" : "video";
|
|
54897
55186
|
setViewMode(newMode);
|
|
54898
55187
|
if (typeof window !== "undefined") {
|
|
@@ -54906,8 +55195,8 @@ var WorkspaceGrid = React144__namespace.default.memo(({
|
|
|
54906
55195
|
}, [viewMode]);
|
|
54907
55196
|
const { VideoGridView: VideoGridViewComponent, MapGridView: MapGridViewComponent } = useRegistry();
|
|
54908
55197
|
const legendMetricLabel = React144.useMemo(
|
|
54909
|
-
() =>
|
|
54910
|
-
[
|
|
55198
|
+
() => getVideoGridLegendLabel(workspaces),
|
|
55199
|
+
[workspaces]
|
|
54911
55200
|
);
|
|
54912
55201
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col w-full h-full overflow-hidden bg-slate-50/50 ${className}`, children: [
|
|
54913
55202
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -54919,21 +55208,7 @@ var WorkspaceGrid = React144__namespace.default.memo(({
|
|
|
54919
55208
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex bg-white/95 rounded-lg shadow-sm px-4 py-2 border border-slate-200/60 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, metricLabel: legendMetricLabel }) }) }),
|
|
54920
55209
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-3 shrink-0", children: [
|
|
54921
55210
|
toolbarRightContent,
|
|
54922
|
-
mapViewEnabled
|
|
54923
|
-
"button",
|
|
54924
|
-
{
|
|
54925
|
-
onClick: handleViewModeToggle,
|
|
54926
|
-
className: "flex items-center gap-2 px-3 py-1.5 bg-white border border-slate-200 rounded-md shadow-sm hover:bg-slate-50 transition-colors duration-200 text-slate-700",
|
|
54927
|
-
title: viewMode === "video" ? "Switch to Map View" : "Switch to Video View",
|
|
54928
|
-
children: viewMode === "video" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
54929
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Map, { className: "w-4 h-4 text-slate-500" }),
|
|
54930
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Map View" })
|
|
54931
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
54932
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { className: "w-4 h-4 text-slate-500" }),
|
|
54933
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Video View" })
|
|
54934
|
-
] })
|
|
54935
|
-
}
|
|
54936
|
-
)
|
|
55211
|
+
mapViewEnabled
|
|
54937
55212
|
] })
|
|
54938
55213
|
]
|
|
54939
55214
|
}
|
|
@@ -54951,6 +55226,7 @@ var WorkspaceGrid = React144__namespace.default.memo(({
|
|
|
54951
55226
|
VideoGridViewComponent,
|
|
54952
55227
|
{
|
|
54953
55228
|
workspaces,
|
|
55229
|
+
blueComparisonWorkspaces,
|
|
54954
55230
|
lineNames,
|
|
54955
55231
|
lineOrder,
|
|
54956
55232
|
videoSources,
|
|
@@ -57247,12 +57523,25 @@ var SideNavBar = React144.memo(({
|
|
|
57247
57523
|
console.log("\u{1F50D} [SideNavBar] ticketsConfig:", dashboardConfig?.ticketsConfig);
|
|
57248
57524
|
console.log("\u{1F50D} [SideNavBar] ticketsEnabled:", ticketsEnabled);
|
|
57249
57525
|
const pathname = propPathname || router$1.pathname;
|
|
57526
|
+
const rawCurrentTabQuery = currentQuery?.tab ?? router$1.query?.tab;
|
|
57527
|
+
const currentTabQuery = Array.isArray(rawCurrentTabQuery) ? rawCurrentTabQuery[0] : rawCurrentTabQuery;
|
|
57528
|
+
const isKpisLeaderboardRoute = pathname === "/kpis" && currentTabQuery === "leaderboard";
|
|
57529
|
+
const isPathActive = React144.useCallback((path) => {
|
|
57530
|
+
if (path === "/") return pathname === "/";
|
|
57531
|
+
if (path === "/leaderboard") {
|
|
57532
|
+
return pathname === "/leaderboard" || pathname.startsWith("/leaderboard/");
|
|
57533
|
+
}
|
|
57534
|
+
if (path === "/kpis") {
|
|
57535
|
+
return pathname === "/kpis" || pathname.startsWith("/kpis/");
|
|
57536
|
+
}
|
|
57537
|
+
return pathname === path || pathname.startsWith(path + "/");
|
|
57538
|
+
}, [pathname]);
|
|
57250
57539
|
const getButtonClasses = React144.useCallback((path) => {
|
|
57251
|
-
const isActive =
|
|
57540
|
+
const isActive = isPathActive(path);
|
|
57252
57541
|
return `w-full flex flex-col items-center justify-center py-4 sm:py-3 px-2 sm:px-1 rounded-lg relative group min-h-[44px] sm:min-h-0
|
|
57253
57542
|
${isActive ? "bg-blue-50/80 text-blue-600 font-medium" : "hover:bg-gray-50 text-gray-500 hover:text-gray-700 font-medium active:bg-gray-100"}
|
|
57254
57543
|
transition-all duration-200 ease-out focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2`;
|
|
57255
|
-
}, [
|
|
57544
|
+
}, [isPathActive]);
|
|
57256
57545
|
const buildDashboardSurfaceTrackingEvent = React144.useCallback((source, destinationPath, dashboardSurface) => ({
|
|
57257
57546
|
name: ROOT_DASHBOARD_EVENT_NAMES[dashboardSurface],
|
|
57258
57547
|
properties: {
|
|
@@ -57285,17 +57574,24 @@ var SideNavBar = React144.memo(({
|
|
|
57285
57574
|
onMobileMenuClose?.();
|
|
57286
57575
|
}, [navigate, onMobileMenuClose, buildDashboardSurfaceTrackingEvent]);
|
|
57287
57576
|
const handleKPIsClick = React144.useCallback(() => {
|
|
57288
|
-
|
|
57289
|
-
|
|
57290
|
-
|
|
57291
|
-
|
|
57292
|
-
|
|
57293
|
-
page_type: "overview"
|
|
57294
|
-
}
|
|
57577
|
+
const trackingEvent = {
|
|
57578
|
+
name: "KPI Page Clicked",
|
|
57579
|
+
properties: {
|
|
57580
|
+
source: "side_nav",
|
|
57581
|
+
page_type: "overview"
|
|
57295
57582
|
}
|
|
57583
|
+
};
|
|
57584
|
+
if (isKpisLeaderboardRoute) {
|
|
57585
|
+
trackCoreEvent(trackingEvent.name, trackingEvent.properties);
|
|
57586
|
+
void router$1.replace("/kpis", void 0, { shallow: false });
|
|
57587
|
+
onMobileMenuClose?.();
|
|
57588
|
+
return;
|
|
57589
|
+
}
|
|
57590
|
+
navigate(`/kpis`, {
|
|
57591
|
+
trackingEvent
|
|
57296
57592
|
});
|
|
57297
57593
|
onMobileMenuClose?.();
|
|
57298
|
-
}, [navigate, onMobileMenuClose]);
|
|
57594
|
+
}, [isKpisLeaderboardRoute, navigate, onMobileMenuClose, router$1]);
|
|
57299
57595
|
const handleImprovementClick = React144.useCallback(() => {
|
|
57300
57596
|
navigate("/improvement-center", {
|
|
57301
57597
|
trackingEvent: {
|
|
@@ -57565,14 +57861,14 @@ var SideNavBar = React144.memo(({
|
|
|
57565
57861
|
});
|
|
57566
57862
|
onMobileMenuClose?.();
|
|
57567
57863
|
}, [navigate, onMobileMenuClose, buildDashboardSurfaceTrackingEvent, rootDashboardSurface]);
|
|
57568
|
-
const homeButtonClasses = React144.useMemo(() => getButtonClasses("/"), [getButtonClasses
|
|
57569
|
-
const liveButtonClasses = React144.useMemo(() => getButtonClasses("/live-monitor"), [getButtonClasses
|
|
57570
|
-
const leaderboardButtonClasses = React144.useMemo(() => getButtonClasses("/leaderboard"), [getButtonClasses
|
|
57571
|
-
const kpisButtonClasses = React144.useMemo(() => getButtonClasses("/kpis"), [getButtonClasses
|
|
57572
|
-
const improvementButtonClasses = React144.useMemo(() => getButtonClasses("/improvement-center"), [getButtonClasses
|
|
57573
|
-
React144.useMemo(() => getButtonClasses("/supervisor-management"), [getButtonClasses
|
|
57574
|
-
const skusButtonClasses = React144.useMemo(() => getButtonClasses("/skus"), [getButtonClasses
|
|
57575
|
-
const healthButtonClasses = React144.useMemo(() => getButtonClasses("/health"), [getButtonClasses
|
|
57864
|
+
const homeButtonClasses = React144.useMemo(() => getButtonClasses("/"), [getButtonClasses]);
|
|
57865
|
+
const liveButtonClasses = React144.useMemo(() => getButtonClasses("/live-monitor"), [getButtonClasses]);
|
|
57866
|
+
const leaderboardButtonClasses = React144.useMemo(() => getButtonClasses("/leaderboard"), [getButtonClasses]);
|
|
57867
|
+
const kpisButtonClasses = React144.useMemo(() => getButtonClasses("/kpis"), [getButtonClasses]);
|
|
57868
|
+
const improvementButtonClasses = React144.useMemo(() => getButtonClasses("/improvement-center"), [getButtonClasses]);
|
|
57869
|
+
React144.useMemo(() => getButtonClasses("/supervisor-management"), [getButtonClasses]);
|
|
57870
|
+
const skusButtonClasses = React144.useMemo(() => getButtonClasses("/skus"), [getButtonClasses]);
|
|
57871
|
+
const healthButtonClasses = React144.useMemo(() => getButtonClasses("/health"), [getButtonClasses]);
|
|
57576
57872
|
const settingsButtonClasses = React144.useMemo(() => {
|
|
57577
57873
|
const isAnyItemActive = settingsItems.some((item) => item.isActive);
|
|
57578
57874
|
const isActive = isSettingsOpen || isAnyItemActive;
|
|
@@ -57606,7 +57902,7 @@ var SideNavBar = React144.memo(({
|
|
|
57606
57902
|
"aria-label": "Home",
|
|
57607
57903
|
tabIndex: 0,
|
|
57608
57904
|
role: "tab",
|
|
57609
|
-
"aria-selected":
|
|
57905
|
+
"aria-selected": isPathActive("/"),
|
|
57610
57906
|
children: [
|
|
57611
57907
|
/* @__PURE__ */ jsxRuntime.jsx(outline.HomeIcon, { className: "w-5 h-5 mb-1" }),
|
|
57612
57908
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Home" })
|
|
@@ -57621,7 +57917,7 @@ var SideNavBar = React144.memo(({
|
|
|
57621
57917
|
"aria-label": "Monitor",
|
|
57622
57918
|
tabIndex: 0,
|
|
57623
57919
|
role: "tab",
|
|
57624
|
-
"aria-selected":
|
|
57920
|
+
"aria-selected": isPathActive("/live-monitor"),
|
|
57625
57921
|
children: [
|
|
57626
57922
|
/* @__PURE__ */ jsxRuntime.jsx(outline.VideoCameraIcon, { className: "w-5 h-5 mb-1" }),
|
|
57627
57923
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Monitor" })
|
|
@@ -57638,7 +57934,7 @@ var SideNavBar = React144.memo(({
|
|
|
57638
57934
|
"aria-label": "Leaderboard",
|
|
57639
57935
|
tabIndex: 0,
|
|
57640
57936
|
role: "tab",
|
|
57641
|
-
"aria-selected":
|
|
57937
|
+
"aria-selected": isPathActive("/leaderboard"),
|
|
57642
57938
|
children: [
|
|
57643
57939
|
/* @__PURE__ */ jsxRuntime.jsx(outline.TrophyIcon, { className: "w-5 h-5 mb-1" }),
|
|
57644
57940
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Leaders" })
|
|
@@ -57653,7 +57949,7 @@ var SideNavBar = React144.memo(({
|
|
|
57653
57949
|
"aria-label": "Lines",
|
|
57654
57950
|
tabIndex: 0,
|
|
57655
57951
|
role: "tab",
|
|
57656
|
-
"aria-selected":
|
|
57952
|
+
"aria-selected": isPathActive("/kpis"),
|
|
57657
57953
|
children: [
|
|
57658
57954
|
/* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: "w-5 h-5 mb-1" }),
|
|
57659
57955
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Lines" })
|
|
@@ -57668,7 +57964,7 @@ var SideNavBar = React144.memo(({
|
|
|
57668
57964
|
"aria-label": "Improvement Center",
|
|
57669
57965
|
tabIndex: 0,
|
|
57670
57966
|
role: "tab",
|
|
57671
|
-
"aria-selected":
|
|
57967
|
+
"aria-selected": isPathActive("/improvement-center"),
|
|
57672
57968
|
children: [
|
|
57673
57969
|
/* @__PURE__ */ jsxRuntime.jsx(outline.LightBulbIcon, { className: "w-5 h-5 mb-1" }),
|
|
57674
57970
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight text-center", children: "Improve" })
|
|
@@ -57684,7 +57980,7 @@ var SideNavBar = React144.memo(({
|
|
|
57684
57980
|
"aria-label": "SKU Management",
|
|
57685
57981
|
tabIndex: 0,
|
|
57686
57982
|
role: "tab",
|
|
57687
|
-
"aria-selected":
|
|
57983
|
+
"aria-selected": isPathActive("/skus"),
|
|
57688
57984
|
children: [
|
|
57689
57985
|
/* @__PURE__ */ jsxRuntime.jsx(outline.CubeIcon, { className: "w-5 h-5 mb-1" }),
|
|
57690
57986
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "SKUs" })
|
|
@@ -57699,7 +57995,7 @@ var SideNavBar = React144.memo(({
|
|
|
57699
57995
|
"aria-label": "System Health",
|
|
57700
57996
|
tabIndex: 0,
|
|
57701
57997
|
role: "tab",
|
|
57702
|
-
"aria-selected":
|
|
57998
|
+
"aria-selected": isPathActive("/health"),
|
|
57703
57999
|
children: [
|
|
57704
58000
|
/* @__PURE__ */ jsxRuntime.jsx(outline.HeartIcon, { className: "w-5 h-5 mb-1" }),
|
|
57705
58001
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Health" })
|
|
@@ -57729,17 +58025,12 @@ var SideNavBar = React144.memo(({
|
|
|
57729
58025
|
) })
|
|
57730
58026
|
] });
|
|
57731
58027
|
const MobileNavigationContent = () => {
|
|
57732
|
-
const isActive = (path) => {
|
|
57733
|
-
if (path === "/" && pathname === "/") return true;
|
|
57734
|
-
if (path !== "/" && pathname.startsWith(path)) return true;
|
|
57735
|
-
return false;
|
|
57736
|
-
};
|
|
57737
58028
|
const getMobileButtonClass = (path) => {
|
|
57738
|
-
const active =
|
|
58029
|
+
const active = isPathActive(path);
|
|
57739
58030
|
return `w-full flex items-center gap-3 px-5 py-3.5 rounded-lg transition-colors active:scale-[0.98] ${active ? "bg-blue-50 text-blue-700" : "text-gray-700 hover:bg-gray-100 active:bg-gray-200"}`;
|
|
57740
58031
|
};
|
|
57741
58032
|
const getIconClass = (path) => {
|
|
57742
|
-
const active =
|
|
58033
|
+
const active = isPathActive(path);
|
|
57743
58034
|
return `w-7 h-7 ${active ? "text-blue-600" : "text-gray-600"}`;
|
|
57744
58035
|
};
|
|
57745
58036
|
const handleMobileNavClick = (handler) => {
|
|
@@ -63696,6 +63987,7 @@ var createEmptyState = () => ({
|
|
|
63696
63987
|
scopeKey: null,
|
|
63697
63988
|
lines: [],
|
|
63698
63989
|
workspaceMetrics: [],
|
|
63990
|
+
blueComparisonWorkspaceMetrics: [],
|
|
63699
63991
|
lineMetrics: [],
|
|
63700
63992
|
kpiTrend: null,
|
|
63701
63993
|
activeBreaks: [],
|
|
@@ -63712,6 +64004,7 @@ var normalizeMetadata = (metadata) => ({
|
|
|
63712
64004
|
});
|
|
63713
64005
|
var useLiveMonitorBootstrap = ({
|
|
63714
64006
|
lineIds,
|
|
64007
|
+
blueComparisonLineIds,
|
|
63715
64008
|
companyId,
|
|
63716
64009
|
enabled = true,
|
|
63717
64010
|
appTimezone,
|
|
@@ -63726,13 +64019,18 @@ var useLiveMonitorBootstrap = ({
|
|
|
63726
64019
|
const effectiveWorkspaceConfig = workspaceConfig || DEFAULT_WORKSPACE_CONFIG;
|
|
63727
64020
|
const effectiveTimezone = appTimezone || "Asia/Kolkata";
|
|
63728
64021
|
const rawLineIdsKey = (lineIds || []).filter(Boolean).join(",");
|
|
64022
|
+
const rawBlueComparisonLineIdsKey = (blueComparisonLineIds || lineIds || []).filter(Boolean).join(",");
|
|
63729
64023
|
const normalizedLineIds = React144.useMemo(
|
|
63730
64024
|
() => Array.from(new Set(rawLineIdsKey ? rawLineIdsKey.split(",") : [])),
|
|
63731
64025
|
[rawLineIdsKey]
|
|
63732
64026
|
);
|
|
64027
|
+
const normalizedBlueComparisonLineIds = React144.useMemo(
|
|
64028
|
+
() => Array.from(new Set(rawBlueComparisonLineIdsKey ? rawBlueComparisonLineIdsKey.split(",") : [])),
|
|
64029
|
+
[rawBlueComparisonLineIdsKey]
|
|
64030
|
+
);
|
|
63733
64031
|
const requestKey = React144.useMemo(
|
|
63734
|
-
() => normalizedLineIds.slice().sort().join(","),
|
|
63735
|
-
[normalizedLineIds]
|
|
64032
|
+
() => `${normalizedLineIds.slice().sort().join(",")}|blue:${normalizedBlueComparisonLineIds.slice().sort().join(",")}`,
|
|
64033
|
+
[normalizedLineIds, normalizedBlueComparisonLineIds]
|
|
63736
64034
|
);
|
|
63737
64035
|
const [state, setState] = React144.useState(() => createEmptyState());
|
|
63738
64036
|
const [rawState, setRawState] = React144.useState(null);
|
|
@@ -63750,6 +64048,9 @@ var useLiveMonitorBootstrap = ({
|
|
|
63750
64048
|
const searchParams = new URLSearchParams();
|
|
63751
64049
|
searchParams.set("company_id", resolvedCompanyId);
|
|
63752
64050
|
searchParams.set("line_ids", normalizedLineIds.join(","));
|
|
64051
|
+
if (normalizedBlueComparisonLineIds.length) {
|
|
64052
|
+
searchParams.set("blue_comparison_line_ids", normalizedBlueComparisonLineIds.join(","));
|
|
64053
|
+
}
|
|
63753
64054
|
if (force) {
|
|
63754
64055
|
searchParams.set("force_refresh", "true");
|
|
63755
64056
|
}
|
|
@@ -63781,6 +64082,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
63781
64082
|
extras: {
|
|
63782
64083
|
company_id: resolvedCompanyId,
|
|
63783
64084
|
line_ids: normalizedLineIds,
|
|
64085
|
+
blue_comparison_line_ids: normalizedBlueComparisonLineIds,
|
|
63784
64086
|
force_refresh: force,
|
|
63785
64087
|
pathname: typeof window !== "undefined" ? window.location.pathname : "unknown"
|
|
63786
64088
|
}
|
|
@@ -63796,6 +64098,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
63796
64098
|
supabase,
|
|
63797
64099
|
resolvedCompanyId,
|
|
63798
64100
|
normalizedLineIds,
|
|
64101
|
+
normalizedBlueComparisonLineIds,
|
|
63799
64102
|
requestKey
|
|
63800
64103
|
]);
|
|
63801
64104
|
React144.useEffect(() => {
|
|
@@ -63814,6 +64117,16 @@ var useLiveMonitorBootstrap = ({
|
|
|
63814
64117
|
fallbackShiftConfig
|
|
63815
64118
|
});
|
|
63816
64119
|
const activeBreaks = transformActiveBreaks(rawState.response.active_breaks_by_line);
|
|
64120
|
+
const blueComparisonWorkspaceMetrics = rawState.response.blue_comparison_workspace_metrics ? transformMonitorWorkspaceMetrics({
|
|
64121
|
+
rows: rawState.response.blue_comparison_workspace_metrics,
|
|
64122
|
+
companyId: resolvedCompanyId,
|
|
64123
|
+
workspaceConfig: effectiveWorkspaceConfig,
|
|
64124
|
+
appTimezone: effectiveTimezone,
|
|
64125
|
+
lineMetrics: rawState.response.line_metrics || [],
|
|
64126
|
+
resolveShiftConfig: (lineId) => lineShiftConfigs?.get(lineId) || fallbackShiftConfig,
|
|
64127
|
+
shouldOverrideShiftType: (lineId) => Boolean(lineShiftConfigs?.get(lineId)),
|
|
64128
|
+
fallbackShiftConfig
|
|
64129
|
+
}) : workspaceMetrics;
|
|
63817
64130
|
const metadata = normalizeMetadata(rawState.response.metadata);
|
|
63818
64131
|
const workspaceIds = workspaceMetrics.map((metric) => metric.workspace_uuid).filter((workspaceId) => Boolean(workspaceId));
|
|
63819
64132
|
const videoStreamsByWorkspaceId = rawState.response.video_streams_by_workspace_id || {};
|
|
@@ -63831,6 +64144,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
63831
64144
|
scopeKey: rawState.response.scope_key || null,
|
|
63832
64145
|
lines: rawState.response.lines || [],
|
|
63833
64146
|
workspaceMetrics,
|
|
64147
|
+
blueComparisonWorkspaceMetrics: blueComparisonWorkspaceMetrics.length ? blueComparisonWorkspaceMetrics : workspaceMetrics,
|
|
63834
64148
|
lineMetrics: rawState.response.line_metrics || [],
|
|
63835
64149
|
kpiTrend: rawState.response.kpi_trend || null,
|
|
63836
64150
|
activeBreaks,
|
|
@@ -63898,6 +64212,7 @@ var useLiveMonitorBootstrap = ({
|
|
|
63898
64212
|
scopeKey: state.scopeKey,
|
|
63899
64213
|
lines: state.lines,
|
|
63900
64214
|
workspaceMetrics: state.workspaceMetrics,
|
|
64215
|
+
blueComparisonWorkspaceMetrics: state.blueComparisonWorkspaceMetrics,
|
|
63901
64216
|
lineMetrics: state.lineMetrics,
|
|
63902
64217
|
kpiTrend: state.kpiTrend,
|
|
63903
64218
|
activeBreaks: state.activeBreaks,
|
|
@@ -64168,6 +64483,22 @@ var logDebug3 = (...args) => {
|
|
|
64168
64483
|
};
|
|
64169
64484
|
var EMPTY_LINE_IDS = [];
|
|
64170
64485
|
var EMPTY_WORKSPACES = [];
|
|
64486
|
+
var ALL_GREEN_CELEBRATION_DURATION_MS = 6e3;
|
|
64487
|
+
var ALL_GREEN_MILESTONE_DURATION_MS = 6e3;
|
|
64488
|
+
var ALL_GREEN_STREAK_LOCAL_SECOND_CAP = 59;
|
|
64489
|
+
var formatAllGreenCelebrationTimer = (elapsedSeconds) => {
|
|
64490
|
+
const safeElapsedSeconds = Math.max(1, Math.floor(elapsedSeconds));
|
|
64491
|
+
const minutes = Math.floor(safeElapsedSeconds / 60);
|
|
64492
|
+
const seconds = safeElapsedSeconds % 60;
|
|
64493
|
+
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}s`;
|
|
64494
|
+
};
|
|
64495
|
+
var getAllGreenBackendVisibleSeconds = (confirmedSeconds, tickOriginAtMs, nowMs2) => {
|
|
64496
|
+
const localSecondOffset = Math.min(
|
|
64497
|
+
ALL_GREEN_STREAK_LOCAL_SECOND_CAP,
|
|
64498
|
+
Math.max(0, Math.floor((nowMs2 - tickOriginAtMs) / 1e3))
|
|
64499
|
+
);
|
|
64500
|
+
return confirmedSeconds + localSecondOffset;
|
|
64501
|
+
};
|
|
64171
64502
|
var LoadingPageCmp = LoadingPage_default;
|
|
64172
64503
|
var LoadingOverlayCmp = LoadingOverlay_default;
|
|
64173
64504
|
function HomeView({
|
|
@@ -64309,6 +64640,31 @@ function HomeView({
|
|
|
64309
64640
|
() => new Set(selectedLineIds),
|
|
64310
64641
|
[selectedLineIds]
|
|
64311
64642
|
);
|
|
64643
|
+
const blueComparisonLineIds = React144.useMemo(() => {
|
|
64644
|
+
const selectedFactoryAreaIds = /* @__PURE__ */ new Set();
|
|
64645
|
+
for (const line of dbLines) {
|
|
64646
|
+
if (!selectedLineIdSet.has(line.id)) {
|
|
64647
|
+
continue;
|
|
64648
|
+
}
|
|
64649
|
+
const factoryAreaId = typeof line.factory_area_id === "string" ? line.factory_area_id.trim() : "";
|
|
64650
|
+
if (factoryAreaId) {
|
|
64651
|
+
selectedFactoryAreaIds.add(factoryAreaId);
|
|
64652
|
+
}
|
|
64653
|
+
}
|
|
64654
|
+
if (selectedFactoryAreaIds.size === 0) {
|
|
64655
|
+
return selectedLineIds;
|
|
64656
|
+
}
|
|
64657
|
+
const dbLinesById = new Map(dbLines.map((line) => [line.id, line]));
|
|
64658
|
+
const selectedIds = new Set(selectedLineIds);
|
|
64659
|
+
return visibleLineIds.filter((lineId) => {
|
|
64660
|
+
if (selectedIds.has(lineId)) {
|
|
64661
|
+
return true;
|
|
64662
|
+
}
|
|
64663
|
+
const line = dbLinesById.get(lineId);
|
|
64664
|
+
const factoryAreaId = typeof line?.factory_area_id === "string" ? line.factory_area_id.trim() : "";
|
|
64665
|
+
return factoryAreaId ? selectedFactoryAreaIds.has(factoryAreaId) : false;
|
|
64666
|
+
});
|
|
64667
|
+
}, [dbLines, selectedLineIdSet, selectedLineIds, visibleLineIds]);
|
|
64312
64668
|
const metricsScopeLineId = isMultiLineSelection ? factoryViewId : primarySelectedLineId;
|
|
64313
64669
|
const userCompanyId = React144.useMemo(() => {
|
|
64314
64670
|
return user?.properties?.company_id || user?.company_id || entityConfig.companyId;
|
|
@@ -64349,6 +64705,7 @@ function HomeView({
|
|
|
64349
64705
|
}, []);
|
|
64350
64706
|
const {
|
|
64351
64707
|
workspaceMetrics: legacyWorkspaceMetrics,
|
|
64708
|
+
blueComparisonWorkspaceMetrics: legacyMetricsBlueComparisonWorkspaceMetrics,
|
|
64352
64709
|
lineMetrics: legacyLineMetrics,
|
|
64353
64710
|
efficiencyLegend: legacyEfficiencyLegend,
|
|
64354
64711
|
metadata: legacyMetricsMetadata,
|
|
@@ -64359,6 +64716,7 @@ function HomeView({
|
|
|
64359
64716
|
} = useDashboardMetrics({
|
|
64360
64717
|
lineId: metricsScopeLineId,
|
|
64361
64718
|
lineIds: selectedLineIds,
|
|
64719
|
+
blueComparisonLineIds,
|
|
64362
64720
|
onLineMetricsUpdate: handleLineMetricsUpdate,
|
|
64363
64721
|
userAccessibleLineIds: visibleLineIds,
|
|
64364
64722
|
enabled: shouldEnableMetricsFetch && !isBootstrapMonitorMode
|
|
@@ -64413,6 +64771,7 @@ function HomeView({
|
|
|
64413
64771
|
const { trend: legacyKpiTrend } = useKpiTrends(legacyTrendOptions);
|
|
64414
64772
|
const bootstrapMonitor = useLiveMonitorBootstrap({
|
|
64415
64773
|
lineIds: selectedLineIds,
|
|
64774
|
+
blueComparisonLineIds,
|
|
64416
64775
|
companyId: userCompanyId,
|
|
64417
64776
|
enabled: shouldEnableMetricsFetch && !isLegacyMonitorMode,
|
|
64418
64777
|
appTimezone: timezone,
|
|
@@ -64421,6 +64780,7 @@ function HomeView({
|
|
|
64421
64780
|
lineShiftConfigs
|
|
64422
64781
|
});
|
|
64423
64782
|
const currentWorkspaceMetrics = isBootstrapMonitorMode ? bootstrapMonitor.workspaceMetrics : legacyWorkspaceMetrics;
|
|
64783
|
+
const currentBlueComparisonWorkspaceMetrics = isBootstrapMonitorMode ? bootstrapMonitor.blueComparisonWorkspaceMetrics : legacyMetricsBlueComparisonWorkspaceMetrics;
|
|
64424
64784
|
const currentLineMetrics = isBootstrapMonitorMode ? bootstrapMonitor.lineMetrics : legacyLineMetrics;
|
|
64425
64785
|
const currentEfficiencyLegend = isBootstrapMonitorMode ? bootstrapMonitor.efficiencyLegend : legacyEfficiencyLegend;
|
|
64426
64786
|
const currentMetricsMetadata = isBootstrapMonitorMode ? bootstrapMonitor.metadata : legacyMetricsMetadata;
|
|
@@ -64558,6 +64918,218 @@ function HomeView({
|
|
|
64558
64918
|
setBreakNotificationsDismissed(false);
|
|
64559
64919
|
}
|
|
64560
64920
|
}, [currentActiveBreaks.length]);
|
|
64921
|
+
const effectiveEfficiencyLegend = currentEfficiencyLegend || DEFAULT_EFFICIENCY_LEGEND;
|
|
64922
|
+
React144.useMemo(
|
|
64923
|
+
() => workspaceMetricsWithBreakState.filter((workspace) => Boolean(workspace.workspace_uuid || workspace.workspace_name)).length,
|
|
64924
|
+
[workspaceMetricsWithBreakState]
|
|
64925
|
+
);
|
|
64926
|
+
const allGreenCelebrationSignature = React144.useMemo(() => {
|
|
64927
|
+
const workspaceSignature = workspaceMetricsWithBreakState.map((workspace) => workspace.workspace_uuid || `${workspace.line_id}:${workspace.workspace_name}`).filter(Boolean).sort().join(",");
|
|
64928
|
+
return `${selectedLineIds.join(",")}::${workspaceSignature}`;
|
|
64929
|
+
}, [selectedLineIds, workspaceMetricsWithBreakState]);
|
|
64930
|
+
const allGreenTransitionRef = React144.useRef({ signature: null, previousValidStreakIdentity: null });
|
|
64931
|
+
const allGreenCelebrationTimerRef = React144.useRef(null);
|
|
64932
|
+
const allGreenMilestoneTimerRef = React144.useRef(null);
|
|
64933
|
+
const allGreenMilestoneTrackingRef = React144.useRef({ identity: null, lastMilestoneSeconds: null });
|
|
64934
|
+
const allGreenStreakTimerBaselineRef = React144.useRef(null);
|
|
64935
|
+
const [showAllGreenCelebration, setShowAllGreenCelebration] = React144.useState(false);
|
|
64936
|
+
const [allGreenCelebrationStartedAtMs, setAllGreenCelebrationStartedAtMs] = React144.useState(null);
|
|
64937
|
+
const [greenStreakMilestoneBanner, setGreenStreakMilestoneBanner] = React144.useState(null);
|
|
64938
|
+
const [allGreenStreakNowMs, setAllGreenStreakNowMs] = React144.useState(() => Date.now());
|
|
64939
|
+
const currentAllGreenStreakNowMs = Math.max(allGreenStreakNowMs, Date.now());
|
|
64940
|
+
const allGreenStreakDisplay = React144.useMemo(
|
|
64941
|
+
() => getAllVideoGridGreenStreakDisplay(
|
|
64942
|
+
workspaceMetricsWithBreakState,
|
|
64943
|
+
effectiveEfficiencyLegend,
|
|
64944
|
+
currentAllGreenStreakNowMs
|
|
64945
|
+
),
|
|
64946
|
+
[currentAllGreenStreakNowMs, effectiveEfficiencyLegend, workspaceMetricsWithBreakState]
|
|
64947
|
+
);
|
|
64948
|
+
const allGreenMilestoneIdentity = React144.useMemo(() => allGreenStreakDisplay ? `${allGreenCelebrationSignature}::${allGreenStreakDisplay.startedAt}` : null, [allGreenCelebrationSignature, allGreenStreakDisplay]);
|
|
64949
|
+
const visibleAllGreenStreakDisplay = React144.useMemo(() => {
|
|
64950
|
+
if (!allGreenStreakDisplay || !allGreenMilestoneIdentity) {
|
|
64951
|
+
allGreenStreakTimerBaselineRef.current = null;
|
|
64952
|
+
return null;
|
|
64953
|
+
}
|
|
64954
|
+
const confirmedSeconds = allGreenStreakDisplay.confirmedSeconds;
|
|
64955
|
+
const backendVisibleSeconds = getAllGreenBackendVisibleSeconds(
|
|
64956
|
+
confirmedSeconds,
|
|
64957
|
+
allGreenStreakDisplay.tickOriginAtMs,
|
|
64958
|
+
currentAllGreenStreakNowMs
|
|
64959
|
+
);
|
|
64960
|
+
const backendMaxVisibleSeconds = confirmedSeconds + ALL_GREEN_STREAK_LOCAL_SECOND_CAP;
|
|
64961
|
+
const currentBaseline = allGreenStreakTimerBaselineRef.current;
|
|
64962
|
+
if (!currentBaseline || currentBaseline.identity !== allGreenMilestoneIdentity) {
|
|
64963
|
+
allGreenStreakTimerBaselineRef.current = {
|
|
64964
|
+
identity: allGreenMilestoneIdentity,
|
|
64965
|
+
baseSeconds: backendVisibleSeconds,
|
|
64966
|
+
baseReceivedAtMs: currentAllGreenStreakNowMs,
|
|
64967
|
+
maxVisibleSeconds: backendMaxVisibleSeconds
|
|
64968
|
+
};
|
|
64969
|
+
} else {
|
|
64970
|
+
currentBaseline.maxVisibleSeconds = Math.max(
|
|
64971
|
+
currentBaseline.maxVisibleSeconds,
|
|
64972
|
+
backendMaxVisibleSeconds
|
|
64973
|
+
);
|
|
64974
|
+
const visibleSeconds = Math.min(
|
|
64975
|
+
currentBaseline.maxVisibleSeconds,
|
|
64976
|
+
currentBaseline.baseSeconds + Math.max(0, Math.floor((currentAllGreenStreakNowMs - currentBaseline.baseReceivedAtMs) / 1e3))
|
|
64977
|
+
);
|
|
64978
|
+
if (backendVisibleSeconds > visibleSeconds) {
|
|
64979
|
+
allGreenStreakTimerBaselineRef.current = {
|
|
64980
|
+
identity: allGreenMilestoneIdentity,
|
|
64981
|
+
baseSeconds: backendVisibleSeconds,
|
|
64982
|
+
baseReceivedAtMs: currentAllGreenStreakNowMs,
|
|
64983
|
+
maxVisibleSeconds: currentBaseline.maxVisibleSeconds
|
|
64984
|
+
};
|
|
64985
|
+
}
|
|
64986
|
+
}
|
|
64987
|
+
const baseline = allGreenStreakTimerBaselineRef.current;
|
|
64988
|
+
const elapsedSeconds = baseline ? Math.min(
|
|
64989
|
+
baseline.maxVisibleSeconds,
|
|
64990
|
+
baseline.baseSeconds + Math.max(0, Math.floor((currentAllGreenStreakNowMs - baseline.baseReceivedAtMs) / 1e3))
|
|
64991
|
+
) : backendVisibleSeconds;
|
|
64992
|
+
return {
|
|
64993
|
+
...allGreenStreakDisplay,
|
|
64994
|
+
elapsedSeconds,
|
|
64995
|
+
durationText: formatAllGreenStreakDuration(elapsedSeconds)
|
|
64996
|
+
};
|
|
64997
|
+
}, [allGreenMilestoneIdentity, allGreenStreakDisplay, currentAllGreenStreakNowMs]);
|
|
64998
|
+
const allGreenCelebrationTimerText = React144.useMemo(() => {
|
|
64999
|
+
if (!showAllGreenCelebration || allGreenCelebrationStartedAtMs === null) {
|
|
65000
|
+
return null;
|
|
65001
|
+
}
|
|
65002
|
+
return formatAllGreenCelebrationTimer(
|
|
65003
|
+
Math.max(0, Math.floor((currentAllGreenStreakNowMs - allGreenCelebrationStartedAtMs) / 1e3))
|
|
65004
|
+
);
|
|
65005
|
+
}, [allGreenCelebrationStartedAtMs, currentAllGreenStreakNowMs, showAllGreenCelebration]);
|
|
65006
|
+
React144.useEffect(() => {
|
|
65007
|
+
const hasPossibleStreakTimer = showAllGreenCelebration || Boolean(allGreenStreakDisplay) || workspaceMetricsWithBreakState.some((workspace) => workspace.video_grid_green_streak_active === true);
|
|
65008
|
+
if (!hasPossibleStreakTimer) {
|
|
65009
|
+
return void 0;
|
|
65010
|
+
}
|
|
65011
|
+
const timerId = setInterval(() => {
|
|
65012
|
+
setAllGreenStreakNowMs(Date.now());
|
|
65013
|
+
}, 1e3);
|
|
65014
|
+
return () => {
|
|
65015
|
+
clearInterval(timerId);
|
|
65016
|
+
};
|
|
65017
|
+
}, [allGreenStreakDisplay, showAllGreenCelebration, workspaceMetricsWithBreakState]);
|
|
65018
|
+
const dismissAllGreenCelebration = React144.useCallback(() => {
|
|
65019
|
+
if (allGreenCelebrationTimerRef.current) {
|
|
65020
|
+
clearTimeout(allGreenCelebrationTimerRef.current);
|
|
65021
|
+
allGreenCelebrationTimerRef.current = null;
|
|
65022
|
+
}
|
|
65023
|
+
setShowAllGreenCelebration(false);
|
|
65024
|
+
setAllGreenCelebrationStartedAtMs(null);
|
|
65025
|
+
}, []);
|
|
65026
|
+
const triggerAllGreenCelebration = React144.useCallback(() => {
|
|
65027
|
+
setAllGreenCelebrationStartedAtMs(Date.now());
|
|
65028
|
+
setShowAllGreenCelebration(true);
|
|
65029
|
+
if (allGreenCelebrationTimerRef.current) {
|
|
65030
|
+
clearTimeout(allGreenCelebrationTimerRef.current);
|
|
65031
|
+
}
|
|
65032
|
+
allGreenCelebrationTimerRef.current = setTimeout(() => {
|
|
65033
|
+
setShowAllGreenCelebration(false);
|
|
65034
|
+
setAllGreenCelebrationStartedAtMs(null);
|
|
65035
|
+
allGreenCelebrationTimerRef.current = null;
|
|
65036
|
+
}, ALL_GREEN_CELEBRATION_DURATION_MS);
|
|
65037
|
+
}, []);
|
|
65038
|
+
const dismissGreenStreakMilestoneBanner = React144.useCallback(() => {
|
|
65039
|
+
if (allGreenMilestoneTimerRef.current) {
|
|
65040
|
+
clearTimeout(allGreenMilestoneTimerRef.current);
|
|
65041
|
+
allGreenMilestoneTimerRef.current = null;
|
|
65042
|
+
}
|
|
65043
|
+
setGreenStreakMilestoneBanner(null);
|
|
65044
|
+
}, []);
|
|
65045
|
+
const triggerGreenStreakMilestoneBanner = React144.useCallback((milestone) => {
|
|
65046
|
+
setGreenStreakMilestoneBanner(milestone);
|
|
65047
|
+
if (allGreenMilestoneTimerRef.current) {
|
|
65048
|
+
clearTimeout(allGreenMilestoneTimerRef.current);
|
|
65049
|
+
}
|
|
65050
|
+
allGreenMilestoneTimerRef.current = setTimeout(() => {
|
|
65051
|
+
setGreenStreakMilestoneBanner(null);
|
|
65052
|
+
allGreenMilestoneTimerRef.current = null;
|
|
65053
|
+
}, ALL_GREEN_MILESTONE_DURATION_MS);
|
|
65054
|
+
}, []);
|
|
65055
|
+
React144.useEffect(() => {
|
|
65056
|
+
return () => {
|
|
65057
|
+
if (allGreenCelebrationTimerRef.current) {
|
|
65058
|
+
clearTimeout(allGreenCelebrationTimerRef.current);
|
|
65059
|
+
}
|
|
65060
|
+
if (allGreenMilestoneTimerRef.current) {
|
|
65061
|
+
clearTimeout(allGreenMilestoneTimerRef.current);
|
|
65062
|
+
}
|
|
65063
|
+
};
|
|
65064
|
+
}, []);
|
|
65065
|
+
React144.useEffect(() => {
|
|
65066
|
+
const milestoneTracking = allGreenMilestoneTrackingRef.current;
|
|
65067
|
+
if (currentMetricsLoading) {
|
|
65068
|
+
return;
|
|
65069
|
+
}
|
|
65070
|
+
if (!visibleAllGreenStreakDisplay || !allGreenMilestoneIdentity) {
|
|
65071
|
+
milestoneTracking.identity = null;
|
|
65072
|
+
milestoneTracking.lastMilestoneSeconds = null;
|
|
65073
|
+
dismissGreenStreakMilestoneBanner();
|
|
65074
|
+
return;
|
|
65075
|
+
}
|
|
65076
|
+
const currentMilestone = getAllGreenStreakMilestone(visibleAllGreenStreakDisplay.elapsedSeconds);
|
|
65077
|
+
const currentMilestoneSeconds = currentMilestone?.milestoneSeconds ?? null;
|
|
65078
|
+
if (milestoneTracking.identity !== allGreenMilestoneIdentity) {
|
|
65079
|
+
milestoneTracking.identity = allGreenMilestoneIdentity;
|
|
65080
|
+
milestoneTracking.lastMilestoneSeconds = currentMilestoneSeconds;
|
|
65081
|
+
dismissGreenStreakMilestoneBanner();
|
|
65082
|
+
return;
|
|
65083
|
+
}
|
|
65084
|
+
if (!currentMilestone) {
|
|
65085
|
+
milestoneTracking.lastMilestoneSeconds = null;
|
|
65086
|
+
return;
|
|
65087
|
+
}
|
|
65088
|
+
if ((milestoneTracking.lastMilestoneSeconds ?? 0) < currentMilestone.milestoneSeconds) {
|
|
65089
|
+
milestoneTracking.lastMilestoneSeconds = currentMilestone.milestoneSeconds;
|
|
65090
|
+
triggerGreenStreakMilestoneBanner(currentMilestone);
|
|
65091
|
+
}
|
|
65092
|
+
}, [
|
|
65093
|
+
allGreenMilestoneIdentity,
|
|
65094
|
+
currentMetricsLoading,
|
|
65095
|
+
dismissGreenStreakMilestoneBanner,
|
|
65096
|
+
triggerGreenStreakMilestoneBanner,
|
|
65097
|
+
visibleAllGreenStreakDisplay
|
|
65098
|
+
]);
|
|
65099
|
+
React144.useEffect(() => {
|
|
65100
|
+
if (currentMetricsLoading) {
|
|
65101
|
+
return;
|
|
65102
|
+
}
|
|
65103
|
+
const currentValidStreakIdentity = visibleAllGreenStreakDisplay && allGreenMilestoneIdentity ? allGreenMilestoneIdentity : null;
|
|
65104
|
+
const transitionState = allGreenTransitionRef.current;
|
|
65105
|
+
if (transitionState.signature !== allGreenCelebrationSignature) {
|
|
65106
|
+
transitionState.signature = allGreenCelebrationSignature;
|
|
65107
|
+
transitionState.previousValidStreakIdentity = currentValidStreakIdentity;
|
|
65108
|
+
dismissAllGreenCelebration();
|
|
65109
|
+
return;
|
|
65110
|
+
}
|
|
65111
|
+
if (!currentValidStreakIdentity) {
|
|
65112
|
+
transitionState.previousValidStreakIdentity = null;
|
|
65113
|
+
dismissAllGreenCelebration();
|
|
65114
|
+
return;
|
|
65115
|
+
}
|
|
65116
|
+
if (transitionState.previousValidStreakIdentity === null) {
|
|
65117
|
+
transitionState.previousValidStreakIdentity = currentValidStreakIdentity;
|
|
65118
|
+
triggerAllGreenCelebration();
|
|
65119
|
+
return;
|
|
65120
|
+
}
|
|
65121
|
+
if (transitionState.previousValidStreakIdentity !== currentValidStreakIdentity) {
|
|
65122
|
+
transitionState.previousValidStreakIdentity = currentValidStreakIdentity;
|
|
65123
|
+
dismissAllGreenCelebration();
|
|
65124
|
+
}
|
|
65125
|
+
}, [
|
|
65126
|
+
allGreenCelebrationSignature,
|
|
65127
|
+
allGreenMilestoneIdentity,
|
|
65128
|
+
currentMetricsLoading,
|
|
65129
|
+
dismissAllGreenCelebration,
|
|
65130
|
+
triggerAllGreenCelebration,
|
|
65131
|
+
visibleAllGreenStreakDisplay
|
|
65132
|
+
]);
|
|
64561
65133
|
const {
|
|
64562
65134
|
streamsByWorkspaceId: legacyVideoStreamsByWorkspaceId,
|
|
64563
65135
|
isLoading: legacyVideoStreamsLoading
|
|
@@ -65124,6 +65696,28 @@ function HomeView({
|
|
|
65124
65696
|
updateSelectedLineIds,
|
|
65125
65697
|
isAllLinesSelection
|
|
65126
65698
|
]);
|
|
65699
|
+
const gridToolbarControls = React144.useMemo(() => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-2", children: [
|
|
65700
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: visibleAllGreenStreakDisplay ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
65701
|
+
motion.div,
|
|
65702
|
+
{
|
|
65703
|
+
initial: { opacity: 0, y: -4 },
|
|
65704
|
+
animate: { opacity: 1, y: 0 },
|
|
65705
|
+
exit: { opacity: 0, y: -4 },
|
|
65706
|
+
transition: { duration: 0.18, ease: "easeOut" },
|
|
65707
|
+
className: "inline-flex items-center gap-1.5 rounded-md border border-[#00AB45]/20 bg-[#00AB45]/10 px-3 py-1.5 text-sm font-semibold text-[#00AB45] shadow-sm",
|
|
65708
|
+
"aria-label": "All green streak",
|
|
65709
|
+
children: [
|
|
65710
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle2, { className: "h-4 w-4" }),
|
|
65711
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: `${visibleAllGreenStreakDisplay.label} \xB7 ${visibleAllGreenStreakDisplay.durationText}` })
|
|
65712
|
+
]
|
|
65713
|
+
},
|
|
65714
|
+
visibleAllGreenStreakDisplay.startedAt
|
|
65715
|
+
) : null }),
|
|
65716
|
+
lineSelectorComponent
|
|
65717
|
+
] }), [
|
|
65718
|
+
lineSelectorComponent,
|
|
65719
|
+
visibleAllGreenStreakDisplay
|
|
65720
|
+
]);
|
|
65127
65721
|
const useSmoothLoading = (isLoading, minDuration = 400) => {
|
|
65128
65722
|
const [showLoading, setShowLoading] = React144.useState(isLoading);
|
|
65129
65723
|
const loadingStartRef2 = React144.useRef(null);
|
|
@@ -65296,17 +65890,18 @@ function HomeView({
|
|
|
65296
65890
|
className: "h-full",
|
|
65297
65891
|
children: React144__namespace.default.createElement(WorkspaceGrid, {
|
|
65298
65892
|
workspaces: workspaceMetricsWithBreakState,
|
|
65893
|
+
blueComparisonWorkspaces: currentBlueComparisonWorkspaceMetrics || workspaceMetricsWithBreakState,
|
|
65299
65894
|
lineNames: mergedLineNames,
|
|
65300
65895
|
lineOrder: selectedLineIds,
|
|
65301
65896
|
factoryView: factoryViewId,
|
|
65302
|
-
legend:
|
|
65897
|
+
legend: effectiveEfficiencyLegend,
|
|
65303
65898
|
videoSources,
|
|
65304
65899
|
videoStreamsByWorkspaceId: currentVideoStreamsByWorkspaceId,
|
|
65305
65900
|
videoStreamsLoading: currentVideoStreamsLoading,
|
|
65306
65901
|
displayNames: metricsDisplayNames,
|
|
65307
65902
|
hasFlowBuffers,
|
|
65308
65903
|
className: "h-full",
|
|
65309
|
-
toolbarRightContent:
|
|
65904
|
+
toolbarRightContent: gridToolbarControls,
|
|
65310
65905
|
onWorkspaceHover: handleWorkspaceHover,
|
|
65311
65906
|
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
65312
65907
|
})
|
|
@@ -65329,17 +65924,18 @@ function HomeView({
|
|
|
65329
65924
|
children: React144__namespace.default.createElement(WorkspaceGrid, {
|
|
65330
65925
|
workspaces: [],
|
|
65331
65926
|
// Show empty grid while loading
|
|
65927
|
+
blueComparisonWorkspaces: [],
|
|
65332
65928
|
lineNames: mergedLineNames,
|
|
65333
65929
|
lineOrder: selectedLineIds,
|
|
65334
65930
|
factoryView: factoryViewId,
|
|
65335
|
-
legend:
|
|
65931
|
+
legend: effectiveEfficiencyLegend,
|
|
65336
65932
|
videoSources,
|
|
65337
65933
|
videoStreamsByWorkspaceId: currentVideoStreamsByWorkspaceId,
|
|
65338
65934
|
videoStreamsLoading: currentVideoStreamsLoading,
|
|
65339
65935
|
displayNames: metricsDisplayNames,
|
|
65340
65936
|
hasFlowBuffers,
|
|
65341
65937
|
className: "h-full",
|
|
65342
|
-
toolbarRightContent:
|
|
65938
|
+
toolbarRightContent: gridToolbarControls,
|
|
65343
65939
|
onWorkspaceHover: handleWorkspaceHover,
|
|
65344
65940
|
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
65345
65941
|
})
|
|
@@ -65372,6 +65968,149 @@ function HomeView({
|
|
|
65372
65968
|
contentVariant: "plain"
|
|
65373
65969
|
}
|
|
65374
65970
|
),
|
|
65971
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxRuntime.jsxs(React144__namespace.default.Fragment, { children: [
|
|
65972
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
65973
|
+
motion.div,
|
|
65974
|
+
{
|
|
65975
|
+
initial: { opacity: 0 },
|
|
65976
|
+
animate: { opacity: 1 },
|
|
65977
|
+
exit: { opacity: 0 },
|
|
65978
|
+
transition: { duration: 0.4 },
|
|
65979
|
+
className: "pointer-events-none fixed inset-0 z-[9998] bg-slate-900/40 backdrop-blur-sm",
|
|
65980
|
+
"aria-hidden": "true"
|
|
65981
|
+
},
|
|
65982
|
+
"all-green-backdrop"
|
|
65983
|
+
),
|
|
65984
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
65985
|
+
motion.div,
|
|
65986
|
+
{
|
|
65987
|
+
initial: { opacity: 0 },
|
|
65988
|
+
animate: { opacity: 1 },
|
|
65989
|
+
exit: { opacity: 0, y: -50, scale: 0.9, filter: "blur(10px)" },
|
|
65990
|
+
transition: { duration: 0.4 },
|
|
65991
|
+
className: "pointer-events-none fixed inset-0 z-[10000] flex flex-col items-center justify-center px-4",
|
|
65992
|
+
role: "status",
|
|
65993
|
+
"aria-live": "polite",
|
|
65994
|
+
"aria-label": "All green celebration",
|
|
65995
|
+
children: [
|
|
65996
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
65997
|
+
motion.div,
|
|
65998
|
+
{
|
|
65999
|
+
initial: { opacity: 0, y: 8, filter: "blur(6px)" },
|
|
66000
|
+
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
|
66001
|
+
transition: { duration: 0.28, ease: [0.16, 1, 0.3, 1] },
|
|
66002
|
+
className: "flex flex-wrap items-center justify-center gap-x-4 sm:gap-x-8",
|
|
66003
|
+
children: [
|
|
66004
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
66005
|
+
"span",
|
|
66006
|
+
{
|
|
66007
|
+
className: "text-[100px] font-black uppercase leading-none tracking-tight text-white drop-shadow-2xl sm:text-[140px]",
|
|
66008
|
+
style: { textShadow: "0 18px 36px rgba(0,0,0,0.34)" },
|
|
66009
|
+
children: "ALL"
|
|
66010
|
+
}
|
|
66011
|
+
),
|
|
66012
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
66013
|
+
"span",
|
|
66014
|
+
{
|
|
66015
|
+
className: "text-[100px] font-black uppercase leading-none tracking-tight text-[#00AB45] drop-shadow-2xl sm:text-[140px]",
|
|
66016
|
+
style: { filter: "drop-shadow(0 18px 36px rgba(0,171,69,0.28))" },
|
|
66017
|
+
children: "GREEN"
|
|
66018
|
+
}
|
|
66019
|
+
)
|
|
66020
|
+
]
|
|
66021
|
+
}
|
|
66022
|
+
),
|
|
66023
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
66024
|
+
motion.div,
|
|
66025
|
+
{
|
|
66026
|
+
initial: { opacity: 0, scaleX: 0 },
|
|
66027
|
+
animate: { opacity: 1, scaleX: 1 },
|
|
66028
|
+
transition: { delay: 0.18, duration: 0.45, ease: [0.16, 1, 0.3, 1] },
|
|
66029
|
+
className: "mt-4 h-1 w-44 origin-left rounded-full bg-[#00AB45] shadow-[0_0_16px_rgba(0,171,69,0.44)] sm:w-64"
|
|
66030
|
+
}
|
|
66031
|
+
),
|
|
66032
|
+
allGreenCelebrationTimerText && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
66033
|
+
motion.div,
|
|
66034
|
+
{
|
|
66035
|
+
initial: { opacity: 0, y: 4 },
|
|
66036
|
+
animate: { opacity: 1, y: 0 },
|
|
66037
|
+
transition: { delay: 0.28, duration: 0.18, ease: "easeOut" },
|
|
66038
|
+
className: "mt-3 flex items-center justify-center gap-2 text-2xl font-semibold tracking-tight text-white drop-shadow-[0_4px_18px_rgba(0,0,0,0.45)] sm:mt-4 sm:text-3xl",
|
|
66039
|
+
children: [
|
|
66040
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-2.5 w-2.5 rounded-full bg-[#00AB45] shadow-[0_0_10px_rgba(0,171,69,0.72)]" }),
|
|
66041
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: allGreenCelebrationTimerText })
|
|
66042
|
+
]
|
|
66043
|
+
}
|
|
66044
|
+
)
|
|
66045
|
+
]
|
|
66046
|
+
},
|
|
66047
|
+
"all-green-center-toast"
|
|
66048
|
+
)
|
|
66049
|
+
] }, "all-green-celebration") : null }),
|
|
66050
|
+
/* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxRuntime.jsxs(React144__namespace.default.Fragment, { children: [
|
|
66051
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
66052
|
+
motion.div,
|
|
66053
|
+
{
|
|
66054
|
+
initial: { opacity: 0 },
|
|
66055
|
+
animate: { opacity: 1 },
|
|
66056
|
+
exit: { opacity: 0 },
|
|
66057
|
+
transition: { duration: 0.4 },
|
|
66058
|
+
className: "pointer-events-none fixed inset-0 z-[9998] bg-slate-900/40 backdrop-blur-sm",
|
|
66059
|
+
"aria-hidden": "true"
|
|
66060
|
+
},
|
|
66061
|
+
`green-streak-backdrop-${greenStreakMilestoneBanner.milestoneSeconds}`
|
|
66062
|
+
),
|
|
66063
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
66064
|
+
motion.div,
|
|
66065
|
+
{
|
|
66066
|
+
initial: { opacity: 0 },
|
|
66067
|
+
animate: { opacity: 1 },
|
|
66068
|
+
exit: { opacity: 0, y: -50, scale: 0.9, filter: "blur(10px)" },
|
|
66069
|
+
transition: { duration: 0.4 },
|
|
66070
|
+
className: "pointer-events-none fixed inset-0 z-[10000] flex flex-col items-center justify-center px-4",
|
|
66071
|
+
role: "status",
|
|
66072
|
+
"aria-live": "polite",
|
|
66073
|
+
"aria-label": `Green streak milestone: ${greenStreakMilestoneBanner.headline}`,
|
|
66074
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center gap-y-4", children: [
|
|
66075
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
66076
|
+
motion.div,
|
|
66077
|
+
{
|
|
66078
|
+
initial: { opacity: 0, y: 8, filter: "blur(6px)" },
|
|
66079
|
+
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
|
66080
|
+
transition: { delay: 0.08, duration: 0.28, ease: [0.16, 1, 0.3, 1] },
|
|
66081
|
+
className: "text-[80px] font-black uppercase leading-none tracking-tight text-white drop-shadow-2xl sm:text-[120px]",
|
|
66082
|
+
style: { textShadow: "0 18px 36px rgba(0,0,0,0.34)" },
|
|
66083
|
+
children: greenStreakMilestoneBanner.headline
|
|
66084
|
+
}
|
|
66085
|
+
) }),
|
|
66086
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
66087
|
+
motion.div,
|
|
66088
|
+
{
|
|
66089
|
+
initial: { opacity: 0, scaleX: 0 },
|
|
66090
|
+
animate: { opacity: 1, scaleX: 1 },
|
|
66091
|
+
transition: { delay: 0.22, duration: 0.45, ease: [0.16, 1, 0.3, 1] },
|
|
66092
|
+
className: "h-1 w-40 origin-left rounded-full bg-[#00AB45] shadow-[0_0_16px_rgba(0,171,69,0.44)] sm:w-56"
|
|
66093
|
+
}
|
|
66094
|
+
),
|
|
66095
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
66096
|
+
motion.div,
|
|
66097
|
+
{
|
|
66098
|
+
initial: { opacity: 0, y: 8, filter: "blur(6px)" },
|
|
66099
|
+
animate: { opacity: 1, y: 0, filter: "blur(0px)" },
|
|
66100
|
+
transition: { delay: 0.28, duration: 0.28, ease: [0.16, 1, 0.3, 1] },
|
|
66101
|
+
className: "flex flex-wrap items-center justify-center gap-x-4 text-[60px] font-black uppercase leading-none tracking-tight text-[#00AB45] drop-shadow-2xl sm:gap-x-8 sm:text-[90px]",
|
|
66102
|
+
style: { filter: "drop-shadow(0 18px 36px rgba(0,171,69,0.28))" },
|
|
66103
|
+
children: [
|
|
66104
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "ALL" }),
|
|
66105
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "GREEN" })
|
|
66106
|
+
]
|
|
66107
|
+
}
|
|
66108
|
+
)
|
|
66109
|
+
] })
|
|
66110
|
+
},
|
|
66111
|
+
`green-streak-milestone-${greenStreakMilestoneBanner.milestoneSeconds}`
|
|
66112
|
+
)
|
|
66113
|
+
] }, `green-streak-milestone-wrapper-${greenStreakMilestoneBanner.milestoneSeconds}`) : null }),
|
|
65375
66114
|
diagnosisModalOpen && bottleneckModalData?.clipId && /* @__PURE__ */ jsxRuntime.jsx(
|
|
65376
66115
|
DiagnosisVideoModal,
|
|
65377
66116
|
{
|
|
@@ -68766,6 +69505,7 @@ var LinesLeaderboard = ({
|
|
|
68766
69505
|
timeRange,
|
|
68767
69506
|
setTimeRange,
|
|
68768
69507
|
todayEfficiencyByLineId,
|
|
69508
|
+
dailyFallbackEfficiencyByLineId,
|
|
68769
69509
|
monthlyEfficiencyByLineId,
|
|
68770
69510
|
supervisorsByLineId,
|
|
68771
69511
|
supervisorNamesByLineId,
|
|
@@ -68801,8 +69541,12 @@ var LinesLeaderboard = ({
|
|
|
68801
69541
|
});
|
|
68802
69542
|
setTimeRange(newRange);
|
|
68803
69543
|
}, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
|
|
69544
|
+
const canClickLeaderboardRow = React144__namespace.default.useCallback(
|
|
69545
|
+
(item) => item.rowType === "line" && !!item.line && canClickLine(item.line.id),
|
|
69546
|
+
[canClickLine]
|
|
69547
|
+
);
|
|
68804
69548
|
const handleLeaderboardLineClick = React144__namespace.default.useCallback((item, clickSource) => {
|
|
68805
|
-
if (!
|
|
69549
|
+
if (!canClickLeaderboardRow(item) || !item.line) return;
|
|
68806
69550
|
trackCoreEvent("Leaderboard Line Clicked", {
|
|
68807
69551
|
line_id: item.line.id,
|
|
68808
69552
|
line_name: item.line.line_name,
|
|
@@ -68814,33 +69558,46 @@ var LinesLeaderboard = ({
|
|
|
68814
69558
|
supervisor_name: item.supervisorName || "Unassigned"
|
|
68815
69559
|
});
|
|
68816
69560
|
onLineClick(item.line);
|
|
68817
|
-
}, [
|
|
69561
|
+
}, [canClickLeaderboardRow, onLineClick, timeRange]);
|
|
68818
69562
|
const viewLoadedTrackedRef = React144__namespace.default.useRef(null);
|
|
68819
69563
|
const leaderboardData = React144__namespace.default.useMemo(() => {
|
|
68820
69564
|
const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
|
|
68821
69565
|
const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
|
|
68822
|
-
|
|
68823
|
-
|
|
69566
|
+
const fallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
|
|
69567
|
+
return buildLineLeaderboardRows({
|
|
69568
|
+
lines,
|
|
69569
|
+
efficiencyByLineId: efficiencyMap,
|
|
69570
|
+
fallbackEfficiencyByLineId: fallbackEfficiencyMap,
|
|
69571
|
+
isLoading: loading
|
|
69572
|
+
}).map((row, index) => {
|
|
69573
|
+
const supervisorByUserId = /* @__PURE__ */ new Map();
|
|
69574
|
+
const fallbackSupervisorNames = [];
|
|
69575
|
+
row.lines.forEach((line) => {
|
|
69576
|
+
(supervisorsByLineId?.get(line.id) || []).forEach((supervisor) => {
|
|
69577
|
+
supervisorByUserId.set(supervisor.userId, supervisor);
|
|
69578
|
+
});
|
|
69579
|
+
const fallbackName = supervisorNamesByLineId.get(line.id);
|
|
69580
|
+
if (fallbackName && !fallbackSupervisorNames.includes(fallbackName)) {
|
|
69581
|
+
fallbackSupervisorNames.push(fallbackName);
|
|
69582
|
+
}
|
|
69583
|
+
});
|
|
69584
|
+
const supervisors = Array.from(supervisorByUserId.values());
|
|
68824
69585
|
const primarySupervisor = supervisors[0];
|
|
68825
|
-
const supervisorName =
|
|
69586
|
+
const supervisorName = supervisors.length > 1 ? `${supervisors.length} supervisors` : primarySupervisor?.displayName || fallbackSupervisorNames[0] || "Unassigned";
|
|
68826
69587
|
const supervisorImage = primarySupervisor?.profilePhotoUrl || null;
|
|
68827
|
-
const hasEfficiency = efficiencyMap.has(line.id);
|
|
68828
|
-
const efficiency = hasEfficiency ? efficiencyMap.get(line.id) ?? 0 : loading ? null : timeRange === "monthly" ? 0 : null;
|
|
68829
|
-
const sortValue = typeof efficiency === "number" ? efficiency : -1;
|
|
68830
69588
|
return {
|
|
68831
|
-
|
|
68832
|
-
|
|
69589
|
+
...row,
|
|
69590
|
+
rank: row.rank ?? index + 1,
|
|
68833
69591
|
supervisorName,
|
|
68834
69592
|
supervisorImage,
|
|
68835
|
-
supervisors
|
|
68836
|
-
efficiency,
|
|
68837
|
-
sortValue
|
|
69593
|
+
supervisors
|
|
68838
69594
|
};
|
|
68839
|
-
})
|
|
69595
|
+
});
|
|
68840
69596
|
}, [
|
|
68841
69597
|
lines,
|
|
68842
69598
|
timeRange,
|
|
68843
69599
|
todayEfficiencyByLineId,
|
|
69600
|
+
dailyFallbackEfficiencyByLineId,
|
|
68844
69601
|
monthlyEfficiencyByLineId,
|
|
68845
69602
|
supervisorsByLineId,
|
|
68846
69603
|
supervisorNamesByLineId,
|
|
@@ -68857,11 +69614,11 @@ var LinesLeaderboard = ({
|
|
|
68857
69614
|
trackCoreEvent("Leaderboard View Loaded", {
|
|
68858
69615
|
time_range: timeRange,
|
|
68859
69616
|
lines_count: leaderboardData.length,
|
|
68860
|
-
top_line_id: topLine?.line.id,
|
|
68861
|
-
top_line_name: topLine?.
|
|
69617
|
+
top_line_id: topLine?.rowType === "line" ? topLine.line?.id : topLine?.areaId,
|
|
69618
|
+
top_line_name: topLine?.displayName,
|
|
68862
69619
|
top_efficiency: topLine?.efficiency,
|
|
68863
|
-
bottom_line_id: bottomLine?.line.id,
|
|
68864
|
-
bottom_line_name: bottomLine?.
|
|
69620
|
+
bottom_line_id: bottomLine?.rowType === "line" ? bottomLine.line?.id : bottomLine?.areaId,
|
|
69621
|
+
bottom_line_name: bottomLine?.displayName,
|
|
68865
69622
|
bottom_efficiency: bottomLine?.efficiency,
|
|
68866
69623
|
efficiency_spread: topLine && bottomLine && topLine.efficiency !== null && bottomLine.efficiency !== null ? (topLine.efficiency - bottomLine.efficiency).toFixed(1) : null,
|
|
68867
69624
|
from_page: "kpis_overview"
|
|
@@ -68968,7 +69725,7 @@ var LinesLeaderboard = ({
|
|
|
68968
69725
|
const isFirst = item.rank === 1;
|
|
68969
69726
|
const isSecond = item.rank === 2;
|
|
68970
69727
|
item.rank === 3;
|
|
68971
|
-
const isClickable =
|
|
69728
|
+
const isClickable = canClickLeaderboardRow(item);
|
|
68972
69729
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
68973
69730
|
"div",
|
|
68974
69731
|
{
|
|
@@ -69011,7 +69768,11 @@ var LinesLeaderboard = ({
|
|
|
69011
69768
|
className: `flex flex-col items-center w-32 md:w-40 lg:w-48 xl:w-60 px-2 md:px-3 xl:px-4 pb-3 md:pb-4 pt-8 md:pt-10 rounded-2xl border bg-gradient-to-b shadow-2xl backdrop-blur-sm ${getRankColor(item.rank)} ${isFirst ? "h-44 md:h-52 lg:h-60 xl:h-64" : isSecond ? "h-36 md:h-44 lg:h-52 xl:h-56" : "h-28 md:h-36 lg:h-44 xl:h-48"}`,
|
|
69012
69769
|
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col items-center justify-center w-full", children: [
|
|
69013
69770
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: `font-bold text-gray-900 text-center line-clamp-1 mb-1 ${isFirst ? "text-xs md:text-sm lg:text-base xl:text-lg" : "text-[10px] md:text-xs lg:text-sm xl:text-base"}`, children: item.supervisorName }),
|
|
69014
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-gray-600 text-center line-clamp-1 font-medium opacity-80 bg-white/50 px-2 md:px-3 py-0.5 rounded-full ${isFirst ? "text-[9px] md:text-[10px] lg:text-xs xl:text-sm mb-2 md:mb-3" : "text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs mb-1 md:mb-2"}`, children: item.
|
|
69771
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-gray-600 text-center line-clamp-1 font-medium opacity-80 bg-white/50 px-2 md:px-3 py-0.5 rounded-full ${isFirst ? "text-[9px] md:text-[10px] lg:text-xs xl:text-sm mb-2 md:mb-3" : "text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs mb-1 md:mb-2"}`, children: item.displayName }),
|
|
69772
|
+
item.rowType === "area" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "mb-1 text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs font-semibold uppercase text-gray-500", children: [
|
|
69773
|
+
item.lines.length,
|
|
69774
|
+
" lines"
|
|
69775
|
+
] }),
|
|
69015
69776
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center mt-auto", children: [
|
|
69016
69777
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-bold uppercase tracking-widest mb-0.5 ${isFirst ? "text-yellow-700/70 text-[8px] md:text-[9px] lg:text-[10px] xl:text-xs" : isSecond ? "text-gray-600/70 text-[7px] md:text-[8px] lg:text-[9px] xl:text-[10px]" : "text-orange-700/70 text-[7px] md:text-[8px] lg:text-[9px] xl:text-[10px]"}`, children: viewType === "machine" ? "Utilization" : "Efficiency" }),
|
|
69017
69778
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `font-black tracking-tight leading-none ${isFirst ? "text-lg md:text-xl lg:text-2xl xl:text-3xl text-transparent bg-clip-text bg-gradient-to-br from-yellow-600 to-yellow-800 drop-shadow-sm" : isSecond ? "text-base md:text-lg lg:text-xl xl:text-2xl text-transparent bg-clip-text bg-gradient-to-br from-gray-600 to-gray-800 drop-shadow-sm" : "text-sm md:text-base lg:text-lg xl:text-xl text-transparent bg-clip-text bg-gradient-to-br from-orange-600 to-orange-800 drop-shadow-sm"}`, children: formatEfficiency(item.efficiency) })
|
|
@@ -69034,7 +69795,7 @@ var LinesLeaderboard = ({
|
|
|
69034
69795
|
] }) }),
|
|
69035
69796
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "divide-y divide-gray-100", children: leaderboardData.map((item) => {
|
|
69036
69797
|
const isTopThree = item.rank <= 3;
|
|
69037
|
-
const isClickable =
|
|
69798
|
+
const isClickable = canClickLeaderboardRow(item);
|
|
69038
69799
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
69039
69800
|
"tr",
|
|
69040
69801
|
{
|
|
@@ -69066,7 +69827,13 @@ var LinesLeaderboard = ({
|
|
|
69066
69827
|
] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-full bg-gray-100 flex items-center justify-center text-gray-500 overflow-hidden border border-gray-200 flex-shrink-0", children: item.supervisorImage ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: item.supervisorImage, alt: item.supervisorName, className: "w-full h-full object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-bold", children: getInitials(item.supervisorName) }) }),
|
|
69067
69828
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-900", children: item.supervisorName })
|
|
69068
69829
|
] }) }),
|
|
69069
|
-
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 whitespace-nowrap text-sm text-gray-500", children:
|
|
69830
|
+
/* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-4 py-3 whitespace-nowrap text-sm text-gray-500", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
69831
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-700", children: item.displayName }),
|
|
69832
|
+
item.rowType === "area" && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-400", children: [
|
|
69833
|
+
item.lines.length,
|
|
69834
|
+
" lines"
|
|
69835
|
+
] })
|
|
69836
|
+
] }) }),
|
|
69070
69837
|
/* @__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) }) }) })
|
|
69071
69838
|
]
|
|
69072
69839
|
},
|
|
@@ -69344,17 +70111,6 @@ var KPIsOverviewView = ({
|
|
|
69344
70111
|
const filterRef = React144.useRef(null);
|
|
69345
70112
|
const filterButtonRef = React144.useRef(null);
|
|
69346
70113
|
const [error, setError] = React144.useState(null);
|
|
69347
|
-
const [topPerformer, setTopPerformer] = React144.useState({
|
|
69348
|
-
name: "Top Performer",
|
|
69349
|
-
role: "Sup.",
|
|
69350
|
-
unit: "Line",
|
|
69351
|
-
periodLabel: (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { month: "long", year: "numeric" }),
|
|
69352
|
-
efficiency: null,
|
|
69353
|
-
imageUrl: null,
|
|
69354
|
-
initials: "TP"
|
|
69355
|
-
});
|
|
69356
|
-
const [topPerformerLoading, setTopPerformerLoading] = React144.useState(true);
|
|
69357
|
-
const [topPerformerImageError, setTopPerformerImageError] = React144.useState(false);
|
|
69358
70114
|
const [todayEfficiencyByLineId, setTodayEfficiencyByLineId] = React144.useState(/* @__PURE__ */ new Map());
|
|
69359
70115
|
const [dailyLoading, setDailyLoading] = React144.useState(false);
|
|
69360
70116
|
const [dailyError, setDailyError] = React144.useState(null);
|
|
@@ -69363,6 +70119,9 @@ var KPIsOverviewView = ({
|
|
|
69363
70119
|
const [monthlyError, setMonthlyError] = React144.useState(null);
|
|
69364
70120
|
const dailyRequestKeyRef = React144.useRef(null);
|
|
69365
70121
|
const monthlyRequestKeyRef = React144.useRef(null);
|
|
70122
|
+
const dailyFallbackRequestKeyRef = React144.useRef(null);
|
|
70123
|
+
const pendingTabRouteSyncRef = React144.useRef(null);
|
|
70124
|
+
const [scopedDailyFallbackEfficiencyByLineId, setScopedDailyFallbackEfficiencyByLineId] = React144.useState(/* @__PURE__ */ new Map());
|
|
69366
70125
|
const supabase = useSupabase();
|
|
69367
70126
|
const { user } = useAuth();
|
|
69368
70127
|
const dashboardConfig = useDashboardConfig();
|
|
@@ -69407,8 +70166,23 @@ var KPIsOverviewView = ({
|
|
|
69407
70166
|
const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
|
|
69408
70167
|
const leaderboardLinesForView = React144__namespace.default.useMemo(() => {
|
|
69409
70168
|
const targetMode = viewType === "machine" ? "uptime" : "output";
|
|
69410
|
-
|
|
69411
|
-
|
|
70169
|
+
const metadataByLineId = new Map(lines.map((line) => [line.id, line]));
|
|
70170
|
+
return leaderboardLines.map((line) => {
|
|
70171
|
+
const metadata = metadataByLineId.get(line.id);
|
|
70172
|
+
return metadata ? {
|
|
70173
|
+
...line,
|
|
70174
|
+
factory_id: line.factory_id || metadata.factory_id,
|
|
70175
|
+
factory_name: line.factory_name || metadata.factory_name,
|
|
70176
|
+
company_name: line.company_name || metadata.company_name,
|
|
70177
|
+
monitoring_mode: line.monitoring_mode ?? metadata.monitoring_mode,
|
|
70178
|
+
factory_area_id: line.factory_area_id ?? metadata.factory_area_id ?? null,
|
|
70179
|
+
factory_area_key: line.factory_area_key ?? metadata.factory_area_key ?? null,
|
|
70180
|
+
factory_area_name: line.factory_area_name ?? metadata.factory_area_name ?? null,
|
|
70181
|
+
factory_area_sort_order: line.factory_area_sort_order ?? metadata.factory_area_sort_order ?? null,
|
|
70182
|
+
factory_area_enabled: line.factory_area_enabled ?? metadata.factory_area_enabled ?? null
|
|
70183
|
+
} : line;
|
|
70184
|
+
}).filter((line) => (line.monitoring_mode ?? "output") === targetMode);
|
|
70185
|
+
}, [leaderboardLines, lines, viewType]);
|
|
69412
70186
|
const linesForView = React144__namespace.default.useMemo(() => {
|
|
69413
70187
|
const targetMode = viewType === "machine" ? "uptime" : "output";
|
|
69414
70188
|
return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
|
|
@@ -69528,12 +70302,19 @@ var KPIsOverviewView = ({
|
|
|
69528
70302
|
React144.useEffect(() => {
|
|
69529
70303
|
if (!router$1.isReady || !hasHydratedLeaderboardRouteState) return;
|
|
69530
70304
|
if (activeTab === "today" && loading) return;
|
|
70305
|
+
const currentTab = typeof router$1.query.tab === "string" ? router$1.query.tab : void 0;
|
|
70306
|
+
const currentRouteTab = currentTab === "leaderboard" ? "leaderboard" : "today";
|
|
70307
|
+
if (currentRouteTab !== activeTab) {
|
|
70308
|
+
if (pendingTabRouteSyncRef.current !== activeTab) {
|
|
70309
|
+
return;
|
|
70310
|
+
}
|
|
70311
|
+
pendingTabRouteSyncRef.current = null;
|
|
70312
|
+
}
|
|
69531
70313
|
const expectedTab = activeTab === "leaderboard" ? "leaderboard" : void 0;
|
|
69532
70314
|
const expectedDate = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily ? effectiveLeaderboardDate : void 0;
|
|
69533
70315
|
const expectedShift = expectedDate !== void 0 ? effectiveLeaderboardShiftId.toString() : void 0;
|
|
69534
70316
|
const expectedFactory = activeTab === "today" && selectedFactoryNode ? selectedFactoryNode.id : void 0;
|
|
69535
70317
|
const expectedFactoryArea = activeTab === "today" && selectedFactoryNode && selectedFactoryAreaNode ? selectedFactoryAreaNode.id : void 0;
|
|
69536
|
-
const currentTab = typeof router$1.query.tab === "string" ? router$1.query.tab : void 0;
|
|
69537
70318
|
const currentDateQuery = typeof router$1.query.date === "string" ? router$1.query.date : void 0;
|
|
69538
70319
|
const currentShiftQuery = typeof router$1.query.shift === "string" ? router$1.query.shift : void 0;
|
|
69539
70320
|
const currentFactoryQuery = getSingleQueryValue(router$1.query[KPI_FACTORY_QUERY_PARAM]);
|
|
@@ -69593,6 +70374,35 @@ var KPIsOverviewView = ({
|
|
|
69593
70374
|
});
|
|
69594
70375
|
return map;
|
|
69595
70376
|
}, [lineMetrics, lineModeById]);
|
|
70377
|
+
const liveDailyFallbackEfficiencyByLineId = React144__namespace.default.useMemo(() => {
|
|
70378
|
+
const map = /* @__PURE__ */ new Map();
|
|
70379
|
+
lineMetricRowsByLineId.forEach((row, lineId) => {
|
|
70380
|
+
const value = Number(row?.avg_efficiency);
|
|
70381
|
+
if (!Number.isFinite(value)) return;
|
|
70382
|
+
const rowDate = typeof row?.date === "string" ? row.date : typeof row?.operational_date === "string" ? row.operational_date : void 0;
|
|
70383
|
+
const rawShiftId = row?.shift_id ?? row?.shiftId;
|
|
70384
|
+
const parsedShiftId = typeof rawShiftId === "number" ? rawShiftId : Number.parseInt(String(rawShiftId ?? ""), 10);
|
|
70385
|
+
const hasScopedRow = rowDate !== void 0 || rawShiftId !== void 0;
|
|
70386
|
+
const matchesSelectedScope = rowDate === effectiveLeaderboardDate && Number.isFinite(parsedShiftId) && parsedShiftId === effectiveLeaderboardShiftId;
|
|
70387
|
+
const canUseUnscopedLiveFallback = !isHistoricalLeaderboardDaily && !hasScopedRow;
|
|
70388
|
+
if (matchesSelectedScope || canUseUnscopedLiveFallback) {
|
|
70389
|
+
map.set(lineId, value);
|
|
70390
|
+
}
|
|
70391
|
+
});
|
|
70392
|
+
return map;
|
|
70393
|
+
}, [
|
|
70394
|
+
effectiveLeaderboardDate,
|
|
70395
|
+
effectiveLeaderboardShiftId,
|
|
70396
|
+
isHistoricalLeaderboardDaily,
|
|
70397
|
+
lineMetricRowsByLineId
|
|
70398
|
+
]);
|
|
70399
|
+
const dailyFallbackEfficiencyByLineId = React144__namespace.default.useMemo(() => {
|
|
70400
|
+
const map = new Map(liveDailyFallbackEfficiencyByLineId);
|
|
70401
|
+
scopedDailyFallbackEfficiencyByLineId.forEach((value, lineId) => {
|
|
70402
|
+
map.set(lineId, value);
|
|
70403
|
+
});
|
|
70404
|
+
return map;
|
|
70405
|
+
}, [liveDailyFallbackEfficiencyByLineId, scopedDailyFallbackEfficiencyByLineId]);
|
|
69596
70406
|
const kpisByLineId = React144__namespace.default.useMemo(() => {
|
|
69597
70407
|
const map = /* @__PURE__ */ new Map();
|
|
69598
70408
|
lineMetricRowsByLineId.forEach((row, lineId) => {
|
|
@@ -69614,32 +70424,11 @@ var KPIsOverviewView = ({
|
|
|
69614
70424
|
() => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
|
|
69615
70425
|
[leaderboardLines, lines]
|
|
69616
70426
|
);
|
|
69617
|
-
const { supervisorNamesByLineId, supervisorsByLineId
|
|
70427
|
+
const { supervisorNamesByLineId, supervisorsByLineId } = useSupervisorsByLineIds(supervisorLineIds, {
|
|
69618
70428
|
enabled: supervisorEnabled && supervisorLineIds.length > 0,
|
|
69619
70429
|
companyId: resolvedCompanyId,
|
|
69620
70430
|
useBackend: true
|
|
69621
70431
|
});
|
|
69622
|
-
React144.useEffect(() => {
|
|
69623
|
-
let isMounted = true;
|
|
69624
|
-
const loadTopPerformer = async () => {
|
|
69625
|
-
try {
|
|
69626
|
-
const record = await awardsService.getTopPerformer(supabase, resolvedCompanyId);
|
|
69627
|
-
if (!isMounted) return;
|
|
69628
|
-
if (record) {
|
|
69629
|
-
setTopPerformer(buildTopPerformerDisplay(record));
|
|
69630
|
-
setTopPerformerImageError(false);
|
|
69631
|
-
}
|
|
69632
|
-
} catch (err) {
|
|
69633
|
-
console.error("[KPIsOverviewView] Failed to load top performer:", err);
|
|
69634
|
-
} finally {
|
|
69635
|
-
if (isMounted) setTopPerformerLoading(false);
|
|
69636
|
-
}
|
|
69637
|
-
};
|
|
69638
|
-
loadTopPerformer();
|
|
69639
|
-
return () => {
|
|
69640
|
-
isMounted = false;
|
|
69641
|
-
};
|
|
69642
|
-
}, [supabase, resolvedCompanyId]);
|
|
69643
70432
|
React144.useEffect(() => {
|
|
69644
70433
|
trackCorePageView("KPIs Overview");
|
|
69645
70434
|
}, []);
|
|
@@ -69689,16 +70478,25 @@ var KPIsOverviewView = ({
|
|
|
69689
70478
|
`/api/dashboard/leaderboard-lines?company_id=${encodeURIComponent(resolvedCompanyId)}`
|
|
69690
70479
|
);
|
|
69691
70480
|
if (!isMounted) return;
|
|
69692
|
-
const
|
|
69693
|
-
|
|
69694
|
-
|
|
69695
|
-
|
|
69696
|
-
|
|
69697
|
-
|
|
69698
|
-
|
|
69699
|
-
|
|
69700
|
-
|
|
69701
|
-
|
|
70481
|
+
const metadataByLineId = new Map(lines.map((line) => [line.id, line]));
|
|
70482
|
+
const transformed = (data.lines || []).filter((line) => line.enable !== false).map((line) => {
|
|
70483
|
+
const metadata = metadataByLineId.get(line.id);
|
|
70484
|
+
return {
|
|
70485
|
+
id: line.id,
|
|
70486
|
+
line_name: line.line_name,
|
|
70487
|
+
factory_id: line.factory_id || metadata?.factory_id || "",
|
|
70488
|
+
factory_name: metadata?.factory_name || "N/A",
|
|
70489
|
+
company_id: line.company_id,
|
|
70490
|
+
company_name: metadata?.company_name || "",
|
|
70491
|
+
enable: line.enable ?? true,
|
|
70492
|
+
monitoring_mode: line.monitoring_mode ?? metadata?.monitoring_mode ?? "output",
|
|
70493
|
+
factory_area_id: line.factory_area_id ?? metadata?.factory_area_id ?? null,
|
|
70494
|
+
factory_area_key: line.factory_area_key ?? metadata?.factory_area_key ?? null,
|
|
70495
|
+
factory_area_name: line.factory_area_name ?? metadata?.factory_area_name ?? null,
|
|
70496
|
+
factory_area_sort_order: line.factory_area_sort_order ?? metadata?.factory_area_sort_order ?? null,
|
|
70497
|
+
factory_area_enabled: line.factory_area_enabled ?? metadata?.factory_area_enabled ?? null
|
|
70498
|
+
};
|
|
70499
|
+
});
|
|
69702
70500
|
setLeaderboardLines(transformed);
|
|
69703
70501
|
} catch (err) {
|
|
69704
70502
|
console.error("[KPIsOverviewView] Failed to load leaderboard lines:", err);
|
|
@@ -69713,6 +70511,58 @@ var KPIsOverviewView = ({
|
|
|
69713
70511
|
isMounted = false;
|
|
69714
70512
|
};
|
|
69715
70513
|
}, [supabase, resolvedCompanyId, lines]);
|
|
70514
|
+
React144.useEffect(() => {
|
|
70515
|
+
if (activeTab !== "leaderboard" || timeRange !== "today") return;
|
|
70516
|
+
if (!supabase || !resolvedCompanyId || !effectiveLeaderboardDate || leaderboardLinesForView.length === 0) {
|
|
70517
|
+
setScopedDailyFallbackEfficiencyByLineId(/* @__PURE__ */ new Map());
|
|
70518
|
+
return;
|
|
70519
|
+
}
|
|
70520
|
+
const targetLineIds = leaderboardLinesForView.map((line) => line.id);
|
|
70521
|
+
const lineIdsKey = targetLineIds.slice().sort().join(",");
|
|
70522
|
+
const requestKey = `${effectiveLeaderboardDate}|${effectiveLeaderboardShiftId}|${lineIdsKey}`;
|
|
70523
|
+
if (dailyFallbackRequestKeyRef.current === requestKey) return;
|
|
70524
|
+
dailyFallbackRequestKeyRef.current = requestKey;
|
|
70525
|
+
let isMounted = true;
|
|
70526
|
+
const fetchScopedFallbackEfficiencies = async () => {
|
|
70527
|
+
try {
|
|
70528
|
+
const entries = await lineLeaderboardService.getDailyLineLeaderboard(supabase, {
|
|
70529
|
+
companyId: resolvedCompanyId,
|
|
70530
|
+
date: effectiveLeaderboardDate,
|
|
70531
|
+
shiftId: effectiveLeaderboardShiftId,
|
|
70532
|
+
lineIds: targetLineIds,
|
|
70533
|
+
lineMode: viewType === "machine" ? "uptime" : "output",
|
|
70534
|
+
includeBelowThreshold: true
|
|
70535
|
+
});
|
|
70536
|
+
if (!isMounted) return;
|
|
70537
|
+
const nextMap = /* @__PURE__ */ new Map();
|
|
70538
|
+
entries.forEach((entry) => {
|
|
70539
|
+
const value = Number(entry.avg_efficiency);
|
|
70540
|
+
if (Number.isFinite(value)) {
|
|
70541
|
+
nextMap.set(entry.line_id, value);
|
|
70542
|
+
}
|
|
70543
|
+
});
|
|
70544
|
+
setScopedDailyFallbackEfficiencyByLineId(nextMap);
|
|
70545
|
+
} catch (err) {
|
|
70546
|
+
if (!isMounted) return;
|
|
70547
|
+
console.warn("[KPIsOverviewView] Failed to load daily fallback line efficiencies:", err);
|
|
70548
|
+
setScopedDailyFallbackEfficiencyByLineId(/* @__PURE__ */ new Map());
|
|
70549
|
+
dailyFallbackRequestKeyRef.current = null;
|
|
70550
|
+
}
|
|
70551
|
+
};
|
|
70552
|
+
void fetchScopedFallbackEfficiencies();
|
|
70553
|
+
return () => {
|
|
70554
|
+
isMounted = false;
|
|
70555
|
+
};
|
|
70556
|
+
}, [
|
|
70557
|
+
activeTab,
|
|
70558
|
+
effectiveLeaderboardDate,
|
|
70559
|
+
effectiveLeaderboardShiftId,
|
|
70560
|
+
leaderboardLinesForView,
|
|
70561
|
+
resolvedCompanyId,
|
|
70562
|
+
supabase,
|
|
70563
|
+
timeRange,
|
|
70564
|
+
viewType
|
|
70565
|
+
]);
|
|
69716
70566
|
const fetchMonthlyLeaderboard = React144.useCallback(async () => {
|
|
69717
70567
|
if (!supabase || !resolvedCompanyId || leaderboardLinesForView.length === 0) return;
|
|
69718
70568
|
const targetLineIds = leaderboardLinesForView.map((line) => line.id);
|
|
@@ -69734,10 +70584,11 @@ var KPIsOverviewView = ({
|
|
|
69734
70584
|
lineMode: viewType === "machine" ? "uptime" : "output"
|
|
69735
70585
|
});
|
|
69736
70586
|
const nextMap = /* @__PURE__ */ new Map();
|
|
69737
|
-
targetLineIds.forEach((lineId) => nextMap.set(lineId, 0));
|
|
69738
70587
|
entries.forEach((entry) => {
|
|
69739
70588
|
const value = Number(entry.avg_efficiency);
|
|
69740
|
-
|
|
70589
|
+
if (Number.isFinite(value)) {
|
|
70590
|
+
nextMap.set(entry.line_id, value);
|
|
70591
|
+
}
|
|
69741
70592
|
});
|
|
69742
70593
|
setMonthlyEfficiencyByLineId(nextMap);
|
|
69743
70594
|
trackCoreEvent("Leaderboard Monthly Data Fetched", {
|
|
@@ -69784,10 +70635,11 @@ var KPIsOverviewView = ({
|
|
|
69784
70635
|
lineMode: viewType === "machine" ? "uptime" : "output"
|
|
69785
70636
|
});
|
|
69786
70637
|
const nextMap = /* @__PURE__ */ new Map();
|
|
69787
|
-
targetLineIds.forEach((lineId) => nextMap.set(lineId, 0));
|
|
69788
70638
|
entries.forEach((entry) => {
|
|
69789
70639
|
const value = Number(entry.avg_efficiency);
|
|
69790
|
-
|
|
70640
|
+
if (Number.isFinite(value)) {
|
|
70641
|
+
nextMap.set(entry.line_id, value);
|
|
70642
|
+
}
|
|
69791
70643
|
});
|
|
69792
70644
|
setTodayEfficiencyByLineId(nextMap);
|
|
69793
70645
|
} catch (err) {
|
|
@@ -69827,69 +70679,6 @@ var KPIsOverviewView = ({
|
|
|
69827
70679
|
factoryAreaId: selectedFactoryAreaNode?.id
|
|
69828
70680
|
});
|
|
69829
70681
|
}, [activeTab, selectedFactoryNode, selectedFactoryAreaNode]);
|
|
69830
|
-
const formatTopPerformerWeek = (periodStart, periodEnd) => {
|
|
69831
|
-
const dateToUse = periodStart ? /* @__PURE__ */ new Date(`${periodStart}T00:00:00`) : /* @__PURE__ */ new Date();
|
|
69832
|
-
if (Number.isNaN(dateToUse.getTime())) {
|
|
69833
|
-
return (/* @__PURE__ */ new Date()).toLocaleDateString("en-US", { month: "long", year: "numeric" });
|
|
69834
|
-
}
|
|
69835
|
-
return dateToUse.toLocaleDateString("en-US", { month: "long", year: "numeric" });
|
|
69836
|
-
};
|
|
69837
|
-
const buildTopPerformerDisplay = (record) => {
|
|
69838
|
-
const supervisorAvatars = [];
|
|
69839
|
-
if (record.supervisors && record.supervisors.length > 0) {
|
|
69840
|
-
for (const s of record.supervisors) {
|
|
69841
|
-
let supervisorName = "Supervisor";
|
|
69842
|
-
if (s.first_name) {
|
|
69843
|
-
supervisorName = s.last_name ? `${s.first_name} ${s.last_name}` : s.first_name;
|
|
69844
|
-
}
|
|
69845
|
-
supervisorAvatars.push({
|
|
69846
|
-
userId: s.user_id,
|
|
69847
|
-
name: supervisorName,
|
|
69848
|
-
imageUrl: s.profile_photo_url || null,
|
|
69849
|
-
initials: getInitials(supervisorName)
|
|
69850
|
-
});
|
|
69851
|
-
}
|
|
69852
|
-
}
|
|
69853
|
-
let displayName = record.recipient_name || "Supervisor";
|
|
69854
|
-
if (record.first_name) {
|
|
69855
|
-
displayName = record.last_name ? `${record.first_name} ${record.last_name}` : record.first_name;
|
|
69856
|
-
} else if (record.recipient_user_id && allSupervisorsMap?.has(record.recipient_user_id)) {
|
|
69857
|
-
const supervisor = allSupervisorsMap.get(record.recipient_user_id);
|
|
69858
|
-
if (supervisor) {
|
|
69859
|
-
displayName = supervisor.displayName;
|
|
69860
|
-
}
|
|
69861
|
-
} else if (displayName.includes(".") || displayName.includes("@")) {
|
|
69862
|
-
const parts = displayName.split(/[.@]/);
|
|
69863
|
-
if (parts.length >= 2) {
|
|
69864
|
-
const firstName = parts[0].charAt(0).toUpperCase() + parts[0].slice(1);
|
|
69865
|
-
const lastName = parts[1].charAt(0).toUpperCase() + parts[1].slice(1);
|
|
69866
|
-
displayName = `${firstName} ${lastName}`;
|
|
69867
|
-
} else if (parts.length === 1) {
|
|
69868
|
-
displayName = parts[0].charAt(0).toUpperCase() + parts[0].slice(1);
|
|
69869
|
-
}
|
|
69870
|
-
}
|
|
69871
|
-
if (supervisorAvatars.length === 0 && record.recipient_user_id) {
|
|
69872
|
-
supervisorAvatars.push({
|
|
69873
|
-
userId: record.recipient_user_id,
|
|
69874
|
-
name: displayName,
|
|
69875
|
-
imageUrl: record.profile_photo_url || null,
|
|
69876
|
-
initials: getInitials(displayName)
|
|
69877
|
-
});
|
|
69878
|
-
}
|
|
69879
|
-
const efficiencyValue = typeof record.avg_efficiency === "number" ? record.avg_efficiency : Number.parseFloat(String(record.avg_efficiency));
|
|
69880
|
-
const efficiency = Number.isFinite(efficiencyValue) ? efficiencyValue : null;
|
|
69881
|
-
const unitLabel = record.winning_line_name || record.unit || "Line";
|
|
69882
|
-
return {
|
|
69883
|
-
name: displayName,
|
|
69884
|
-
role: "Sup.",
|
|
69885
|
-
unit: unitLabel,
|
|
69886
|
-
periodLabel: formatTopPerformerWeek(record.period_start, record.period_end),
|
|
69887
|
-
efficiency,
|
|
69888
|
-
imageUrl: record.profile_photo_url || null,
|
|
69889
|
-
initials: getInitials(displayName),
|
|
69890
|
-
supervisors: supervisorAvatars.length > 0 ? supervisorAvatars : void 0
|
|
69891
|
-
};
|
|
69892
|
-
};
|
|
69893
70682
|
const handleLineClick = (line, kpis) => {
|
|
69894
70683
|
if (!isSuperAdmin && !assignedLineIdSet.has(line.id)) {
|
|
69895
70684
|
return;
|
|
@@ -69937,6 +70726,7 @@ var KPIsOverviewView = ({
|
|
|
69937
70726
|
from_page: "kpis_overview",
|
|
69938
70727
|
lines_count: trackedLineCount
|
|
69939
70728
|
});
|
|
70729
|
+
pendingTabRouteSyncRef.current = newTab;
|
|
69940
70730
|
setActiveTab(newTab);
|
|
69941
70731
|
}, [activeTab, leaderboardLines.length, lines.length]);
|
|
69942
70732
|
const formatLocalDate2 = React144.useCallback((dateKey) => {
|
|
@@ -69961,10 +70751,8 @@ var KPIsOverviewView = ({
|
|
|
69961
70751
|
const isMonthlyMode = activeTab === "leaderboard" && timeRange === "monthly";
|
|
69962
70752
|
const isLeaderboardLoading = timeRange === "today" ? dailyLoading : monthlyLoading;
|
|
69963
70753
|
const currentEfficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
|
|
69964
|
-
const
|
|
69965
|
-
const
|
|
69966
|
-
typeof topPerformer.efficiency === "number" && Number.isFinite(topPerformer.efficiency);
|
|
69967
|
-
topPerformerLoading ? "--" : typeof topPerformer.efficiency === "number" && Number.isFinite(topPerformer.efficiency) ? `${topPerformer.efficiency.toFixed(1)}%` : "--";
|
|
70754
|
+
const currentFallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
|
|
70755
|
+
const showLeaderboardLoader = activeTab === "leaderboard" && (leaderboardLinesLoading || isLeaderboardLoading && currentEfficiencyMap.size === 0 && (currentFallbackEfficiencyMap?.size ?? 0) === 0);
|
|
69968
70756
|
const showHistoricalLeaderboardHeader = activeTab === "leaderboard" && timeRange === "today" && isHistoricalLeaderboardDaily;
|
|
69969
70757
|
const headerDateKey = activeTab === "leaderboard" && timeRange === "today" ? effectiveLeaderboardDate : monthEndDateKey;
|
|
69970
70758
|
const headerShiftId = showHistoricalLeaderboardHeader ? effectiveLeaderboardShiftId : currentShiftDetails.shiftId;
|
|
@@ -70169,72 +70957,6 @@ var KPIsOverviewView = ({
|
|
|
70169
70957
|
] }) : /* @__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, {}) }) })
|
|
70170
70958
|
] })
|
|
70171
70959
|
] }),
|
|
70172
|
-
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: [
|
|
70173
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex-shrink-0", children: [
|
|
70174
|
-
(!topPerformer.supervisors || topPerformer.supervisors.length <= 1) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-10 h-10 rounded-full border-2 border-amber-100 overflow-hidden bg-amber-50 shadow-sm transition-transform group-hover:scale-105", children: showTopPerformerImage ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
70175
|
-
"img",
|
|
70176
|
-
{
|
|
70177
|
-
src: topPerformer.imageUrl || "",
|
|
70178
|
-
alt: "Top Performer",
|
|
70179
|
-
className: "w-full h-full object-cover",
|
|
70180
|
-
onError: () => setTopPerformerImageError(true)
|
|
70181
|
-
}
|
|
70182
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center bg-amber-50 text-sm font-bold text-amber-600", children: topPerformer.initials }) }),
|
|
70183
|
-
topPerformer.supervisors && topPerformer.supervisors.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex -space-x-2", children: [
|
|
70184
|
-
topPerformer.supervisors.slice(0, 3).map((supervisor, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
70185
|
-
"div",
|
|
70186
|
-
{
|
|
70187
|
-
className: "relative inline-block w-9 h-9 rounded-full ring-2 ring-white bg-amber-50 shadow-sm z-0 hover:z-10 transition-all hover:scale-110 group/avatar",
|
|
70188
|
-
style: { zIndex: 3 - idx },
|
|
70189
|
-
children: [
|
|
70190
|
-
supervisor.imageUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
70191
|
-
"img",
|
|
70192
|
-
{
|
|
70193
|
-
src: supervisor.imageUrl,
|
|
70194
|
-
alt: supervisor.name,
|
|
70195
|
-
className: "w-full h-full object-cover rounded-full"
|
|
70196
|
-
}
|
|
70197
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center text-xs font-bold text-amber-600 uppercase rounded-full", children: supervisor.initials }),
|
|
70198
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-gray-900 text-white text-[10px] font-medium rounded shadow-lg opacity-0 group-hover/avatar:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-20", children: [
|
|
70199
|
-
supervisor.name,
|
|
70200
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 -mt-[1px] border-4 border-transparent border-t-gray-900" })
|
|
70201
|
-
] })
|
|
70202
|
-
]
|
|
70203
|
-
},
|
|
70204
|
-
supervisor.userId
|
|
70205
|
-
)),
|
|
70206
|
-
topPerformer.supervisors.length > 3 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-9 h-9 rounded-full ring-2 ring-white bg-amber-100 items-center justify-center text-xs font-medium text-amber-700 z-0", children: [
|
|
70207
|
-
"+",
|
|
70208
|
-
topPerformer.supervisors.length - 3
|
|
70209
|
-
] })
|
|
70210
|
-
] })
|
|
70211
|
-
] }),
|
|
70212
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
70213
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 leading-none mb-1", children: [
|
|
70214
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-bold text-amber-600 uppercase tracking-widest", children: "Performer of the month" }),
|
|
70215
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-1 h-1 bg-amber-200 rounded-full" }),
|
|
70216
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] font-semibold text-gray-400", children: topPerformerLoading ? "Loading" : topPerformer.periodLabel })
|
|
70217
|
-
] }),
|
|
70218
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 leading-none", children: [
|
|
70219
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[140px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
70220
|
-
FittingTitle,
|
|
70221
|
-
{
|
|
70222
|
-
title: topPerformer.name,
|
|
70223
|
-
as: "span",
|
|
70224
|
-
className: "text-sm text-gray-900 font-bold"
|
|
70225
|
-
}
|
|
70226
|
-
) }),
|
|
70227
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-px h-3 bg-gray-200 flex-shrink-0" }),
|
|
70228
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[120px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
70229
|
-
FittingTitle,
|
|
70230
|
-
{
|
|
70231
|
-
title: topPerformer.unit,
|
|
70232
|
-
className: "text-xs font-medium text-gray-500"
|
|
70233
|
-
}
|
|
70234
|
-
) })
|
|
70235
|
-
] })
|
|
70236
|
-
] })
|
|
70237
|
-
] }) }),
|
|
70238
70960
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex bg-gray-100/80 p-1 rounded-xl w-full", children: [
|
|
70239
70961
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
70240
70962
|
"button",
|
|
@@ -70269,86 +70991,18 @@ var KPIsOverviewView = ({
|
|
|
70269
70991
|
/* @__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" }),
|
|
70270
70992
|
!showHistoricalLeaderboardHeader && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-2.5 w-2.5 rounded-full ring-4 flex-shrink-0 bg-emerald-500 animate-pulse ring-emerald-500/10" })
|
|
70271
70993
|
] }),
|
|
70272
|
-
/* @__PURE__ */ jsxRuntime.
|
|
70273
|
-
|
|
70274
|
-
|
|
70275
|
-
|
|
70276
|
-
|
|
70277
|
-
|
|
70278
|
-
|
|
70279
|
-
|
|
70280
|
-
|
|
70281
|
-
|
|
70282
|
-
|
|
70283
|
-
|
|
70284
|
-
topPerformer.supervisors && topPerformer.supervisors.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex -space-x-2", children: [
|
|
70285
|
-
topPerformer.supervisors.slice(0, 3).map((supervisor, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
70286
|
-
"div",
|
|
70287
|
-
{
|
|
70288
|
-
className: "relative inline-block w-10 h-10 rounded-full ring-2 ring-white bg-amber-50 shadow-sm z-0 hover:z-10 transition-all hover:scale-110 group/avatar",
|
|
70289
|
-
style: { zIndex: 3 - idx },
|
|
70290
|
-
children: [
|
|
70291
|
-
supervisor.imageUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
70292
|
-
"img",
|
|
70293
|
-
{
|
|
70294
|
-
src: supervisor.imageUrl,
|
|
70295
|
-
alt: supervisor.name,
|
|
70296
|
-
className: "w-full h-full object-cover rounded-full"
|
|
70297
|
-
}
|
|
70298
|
-
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center text-sm font-bold text-amber-600 uppercase rounded-full", children: supervisor.initials }),
|
|
70299
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 px-2 py-1 bg-gray-900 text-white text-[10px] font-medium rounded shadow-lg opacity-0 group-hover/avatar:opacity-100 transition-opacity whitespace-nowrap pointer-events-none z-20", children: [
|
|
70300
|
-
supervisor.name,
|
|
70301
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-full left-1/2 -translate-x-1/2 -mt-[1px] border-4 border-transparent border-t-gray-900" })
|
|
70302
|
-
] })
|
|
70303
|
-
]
|
|
70304
|
-
},
|
|
70305
|
-
supervisor.userId
|
|
70306
|
-
)),
|
|
70307
|
-
topPerformer.supervisors.length > 3 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex w-10 h-10 rounded-full ring-2 ring-white bg-amber-100 items-center justify-center text-sm font-medium text-amber-700 z-0", children: [
|
|
70308
|
-
"+",
|
|
70309
|
-
topPerformer.supervisors.length - 3
|
|
70310
|
-
] })
|
|
70311
|
-
] })
|
|
70312
|
-
] }),
|
|
70313
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col min-w-0", children: [
|
|
70314
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-[10px] leading-tight mb-1", children: [
|
|
70315
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-bold text-amber-600 uppercase tracking-widest", children: "Performer of the month" }),
|
|
70316
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-amber-200 opacity-50", children: "\u2022" }),
|
|
70317
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-gray-400", children: topPerformer.periodLabel })
|
|
70318
|
-
] }),
|
|
70319
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 leading-tight", children: [
|
|
70320
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[140px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
70321
|
-
FittingTitle,
|
|
70322
|
-
{
|
|
70323
|
-
title: topPerformer.name,
|
|
70324
|
-
as: "span",
|
|
70325
|
-
className: "text-sm text-gray-900 font-bold"
|
|
70326
|
-
}
|
|
70327
|
-
) }),
|
|
70328
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "w-px h-3.5 bg-gray-200 flex-shrink-0" }),
|
|
70329
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[150px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
70330
|
-
FittingTitle,
|
|
70331
|
-
{
|
|
70332
|
-
title: topPerformer.unit,
|
|
70333
|
-
className: "text-xs font-medium text-gray-500"
|
|
70334
|
-
}
|
|
70335
|
-
) })
|
|
70336
|
-
] })
|
|
70337
|
-
] })
|
|
70338
|
-
] }),
|
|
70339
|
-
activeTab === "leaderboard" && isHistoricalLeaderboardDaily && /* @__PURE__ */ jsxRuntime.jsx(
|
|
70340
|
-
"button",
|
|
70341
|
-
{
|
|
70342
|
-
type: "button",
|
|
70343
|
-
onClick: () => {
|
|
70344
|
-
setSelectedLeaderboardDate(currentShiftDate);
|
|
70345
|
-
setSelectedLeaderboardShiftId(currentShiftId);
|
|
70346
|
-
},
|
|
70347
|
-
className: "text-xs sm:text-sm font-medium text-blue-600 bg-blue-50 border border-blue-100 hover:bg-blue-100 hover:text-blue-700 px-3 py-1.5 rounded-lg transition-colors shadow-sm ml-4 whitespace-nowrap",
|
|
70348
|
-
children: "Return to Live"
|
|
70349
|
-
}
|
|
70350
|
-
)
|
|
70351
|
-
] })
|
|
70994
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 top-1/2 -translate-y-1/2 z-10 flex items-center", children: activeTab === "leaderboard" && isHistoricalLeaderboardDaily && /* @__PURE__ */ jsxRuntime.jsx(
|
|
70995
|
+
"button",
|
|
70996
|
+
{
|
|
70997
|
+
type: "button",
|
|
70998
|
+
onClick: () => {
|
|
70999
|
+
setSelectedLeaderboardDate(currentShiftDate);
|
|
71000
|
+
setSelectedLeaderboardShiftId(currentShiftId);
|
|
71001
|
+
},
|
|
71002
|
+
className: "text-xs sm:text-sm font-medium text-blue-600 bg-blue-50 border border-blue-100 hover:bg-blue-100 hover:text-blue-700 px-3 py-1.5 rounded-lg transition-colors shadow-sm ml-4 whitespace-nowrap",
|
|
71003
|
+
children: "Return to Live"
|
|
71004
|
+
}
|
|
71005
|
+
) })
|
|
70352
71006
|
] }),
|
|
70353
71007
|
/* @__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: [
|
|
70354
71008
|
!isMonthlyMode && !showHistoricalLeaderboardHeader && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
@@ -70523,6 +71177,7 @@ var KPIsOverviewView = ({
|
|
|
70523
71177
|
timeRange,
|
|
70524
71178
|
setTimeRange,
|
|
70525
71179
|
todayEfficiencyByLineId,
|
|
71180
|
+
dailyFallbackEfficiencyByLineId,
|
|
70526
71181
|
monthlyEfficiencyByLineId,
|
|
70527
71182
|
supervisorsByLineId,
|
|
70528
71183
|
supervisorNamesByLineId,
|
|
@@ -70555,13 +71210,23 @@ var AnimatedEfficiency = React144.memo(({ value }) => {
|
|
|
70555
71210
|
AnimatedEfficiency.displayName = "AnimatedEfficiency";
|
|
70556
71211
|
var getWorkspaceLeaderboardMetricValue = (workspace) => {
|
|
70557
71212
|
if (workspace.leaderboard_metric_kind === "recent_flow_shift_average") {
|
|
70558
|
-
|
|
71213
|
+
const cycleRatio = getCycleRatio(workspace);
|
|
71214
|
+
return cycleRatio === null ? null : cycleRatio * 100;
|
|
70559
71215
|
}
|
|
70560
71216
|
return toFiniteNumber(workspace.leaderboard_value) ?? toFiniteNumber(workspace.efficiency);
|
|
70561
71217
|
};
|
|
70562
71218
|
var getWorkspaceDisplayedMetricValue = (workspace) => getWorkspaceLeaderboardMetricValue(workspace);
|
|
70563
|
-
var getWorkspaceLeaderboardMetricLabel = (workspace, defaultLabel) => workspace.leaderboard_metric_kind === "recent_flow_shift_average" ? "
|
|
71219
|
+
var getWorkspaceLeaderboardMetricLabel = (workspace, defaultLabel) => workspace.leaderboard_metric_kind === "recent_flow_shift_average" ? "Actual CT / Standard CT" : defaultLabel;
|
|
70564
71220
|
var renderWorkspaceLeaderboardMetric = (workspace) => {
|
|
71221
|
+
if (workspace.leaderboard_metric_kind === "recent_flow_shift_average") {
|
|
71222
|
+
const actualCT = formatCycleTimeValue(workspace.avg_cycle_time);
|
|
71223
|
+
const standardCT = formatCycleTimeValue(workspace.ideal_cycle_time);
|
|
71224
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "tabular-nums", children: [
|
|
71225
|
+
actualCT,
|
|
71226
|
+
" / ",
|
|
71227
|
+
standardCT
|
|
71228
|
+
] });
|
|
71229
|
+
}
|
|
70565
71230
|
const displayedMetricValue = getWorkspaceDisplayedMetricValue(workspace);
|
|
70566
71231
|
if (displayedMetricValue === null) {
|
|
70567
71232
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "tabular-nums", children: "--" });
|
|
@@ -70839,12 +71504,8 @@ var LeaderboardDetailView = React144.memo(({
|
|
|
70839
71504
|
return `Line ${lineId2.substring(0, 8)}`;
|
|
70840
71505
|
}, [dbLineNames, configuredLineNames, lineNames, line1Id, line2Id]);
|
|
70841
71506
|
const configuredLineIds = React144.useMemo(() => {
|
|
70842
|
-
|
|
70843
|
-
|
|
70844
|
-
return allLineIds.filter((id3) => userAccessibleLineIds.includes(id3));
|
|
70845
|
-
}
|
|
70846
|
-
return allLineIds;
|
|
70847
|
-
}, [entityConfig, userAccessibleLineIds]);
|
|
71507
|
+
return getConfiguredLineIds(entityConfig);
|
|
71508
|
+
}, [entityConfig]);
|
|
70848
71509
|
const accessibleLineIdSet = React144.useMemo(
|
|
70849
71510
|
() => new Set((userAccessibleLineIds || []).filter(Boolean)),
|
|
70850
71511
|
[userAccessibleLineIds]
|
|
@@ -71532,7 +72193,7 @@ var LeaderboardDetailView = React144.memo(({
|
|
|
71532
72193
|
const hasEfficiencyLeaderboardRows = sortedWorkspaces.some(
|
|
71533
72194
|
(workspace) => workspace.leaderboard_metric_kind !== "recent_flow_shift_average"
|
|
71534
72195
|
);
|
|
71535
|
-
const metricLabel = viewType === "machine" ? "Utilization" : hasRecentFlowLeaderboardRows && !hasEfficiencyLeaderboardRows ? "
|
|
72196
|
+
const metricLabel = viewType === "machine" ? "Utilization" : hasRecentFlowLeaderboardRows && !hasEfficiencyLeaderboardRows ? "Actual CT / Standard CT" : hasRecentFlowLeaderboardRows && hasEfficiencyLeaderboardRows ? "Performance" : "Efficiency";
|
|
71536
72197
|
const descendingSortLabel = "Highest to Lowest";
|
|
71537
72198
|
const ascendingSortLabel = "Lowest to Highest";
|
|
71538
72199
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `min-h-screen bg-slate-50 flex flex-col ${className}`, style: { willChange: "contents" }, children: [
|
|
@@ -86453,6 +87114,7 @@ exports.awardsService = awardsService;
|
|
|
86453
87114
|
exports.buildDateKey = buildDateKey;
|
|
86454
87115
|
exports.buildKPIsFromLineMetricsRow = buildKPIsFromLineMetricsRow;
|
|
86455
87116
|
exports.buildKpiLineHierarchy = buildKpiLineHierarchy;
|
|
87117
|
+
exports.buildLineLeaderboardRows = buildLineLeaderboardRows;
|
|
86456
87118
|
exports.buildLineSkuBreakdown = buildLineSkuBreakdown;
|
|
86457
87119
|
exports.buildShiftGroupsKey = buildShiftGroupsKey;
|
|
86458
87120
|
exports.canRoleAccessDashboardPath = canRoleAccessDashboardPath;
|