@optifye/dashboard-core 6.11.23 → 6.11.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.css +18 -32
- package/dist/index.d.mts +10 -1
- package/dist/index.d.ts +10 -1
- package/dist/index.js +564 -318
- package/dist/index.mjs +564 -318
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13284,7 +13284,7 @@ var parseEfficiencyLegend = (legend) => {
|
|
|
13284
13284
|
critical_threshold: coerce(legend.critical_threshold, DEFAULT_EFFICIENCY_LEGEND.critical_threshold)
|
|
13285
13285
|
};
|
|
13286
13286
|
};
|
|
13287
|
-
var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds }) => {
|
|
13287
|
+
var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, lineIds, userAccessibleLineIds }) => {
|
|
13288
13288
|
const { supabaseUrl, supabaseKey } = useDashboardConfig();
|
|
13289
13289
|
const entityConfig = useEntityConfig();
|
|
13290
13290
|
const databaseConfig = useDatabaseConfig();
|
|
@@ -13301,9 +13301,9 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13301
13301
|
return getConfiguredLineIds(entityConfig);
|
|
13302
13302
|
}, [entityConfig]);
|
|
13303
13303
|
const targetFactoryLineIds = React142.useMemo(() => {
|
|
13304
|
-
const sourceLineIds = userAccessibleLineIds !== void 0 ? userAccessibleLineIds : configuredLineIds;
|
|
13304
|
+
const sourceLineIds = lineIds !== void 0 ? lineIds : userAccessibleLineIds !== void 0 ? userAccessibleLineIds : configuredLineIds;
|
|
13305
13305
|
return Array.from(new Set((sourceLineIds || []).filter(Boolean)));
|
|
13306
|
-
}, [userAccessibleLineIds, configuredLineIds]);
|
|
13306
|
+
}, [lineIds, userAccessibleLineIds, configuredLineIds]);
|
|
13307
13307
|
const { shiftConfig: staticShiftConfig } = useDashboardConfig();
|
|
13308
13308
|
const {
|
|
13309
13309
|
shiftConfigMap: multiLineShiftConfigMap,
|
|
@@ -13356,6 +13356,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13356
13356
|
const operationalShiftKeyRef = React142.useRef(operationalShiftKey);
|
|
13357
13357
|
const configuredLineIdsRef = React142.useRef(configuredLineIds);
|
|
13358
13358
|
const userAccessibleLineIdsRef = React142.useRef(userAccessibleLineIds);
|
|
13359
|
+
const explicitLineIdsRef = React142.useRef(lineIds);
|
|
13359
13360
|
React142.useEffect(() => {
|
|
13360
13361
|
onLineMetricsUpdateRef.current = onLineMetricsUpdate;
|
|
13361
13362
|
}, [onLineMetricsUpdate]);
|
|
@@ -13371,6 +13372,9 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13371
13372
|
React142.useEffect(() => {
|
|
13372
13373
|
userAccessibleLineIdsRef.current = userAccessibleLineIds;
|
|
13373
13374
|
}, [userAccessibleLineIds]);
|
|
13375
|
+
React142.useEffect(() => {
|
|
13376
|
+
explicitLineIdsRef.current = lineIds;
|
|
13377
|
+
}, [lineIds]);
|
|
13374
13378
|
const companySpecificMetricsTable = React142.useMemo(
|
|
13375
13379
|
() => getCompanyMetricsTableName(entityConfig.companyId, "performance_metrics"),
|
|
13376
13380
|
[entityConfig.companyId]
|
|
@@ -13721,6 +13725,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13721
13725
|
isFactoryView,
|
|
13722
13726
|
multiLineShiftConfigMap,
|
|
13723
13727
|
staticShiftConfig,
|
|
13728
|
+
lineIds,
|
|
13724
13729
|
userAccessibleLineIds,
|
|
13725
13730
|
effectiveWorkspaceConfig,
|
|
13726
13731
|
shiftLoading,
|
|
@@ -13838,7 +13843,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
13838
13843
|
logDebug("[useDashboardMetrics] Setting up group subscriptions:", {
|
|
13839
13844
|
groupCount: currentShiftGroups.length
|
|
13840
13845
|
});
|
|
13841
|
-
const targetFactoryLineIdsForSubscriptions = currentUserAccessibleLineIds !== void 0 ? currentUserAccessibleLineIds : currentConfiguredLineIds;
|
|
13846
|
+
const targetFactoryLineIdsForSubscriptions = explicitLineIdsRef.current !== void 0 ? explicitLineIdsRef.current : currentUserAccessibleLineIds !== void 0 ? currentUserAccessibleLineIds : currentConfiguredLineIds;
|
|
13842
13847
|
const targetFactoryLineIdSet = new Set(
|
|
13843
13848
|
(targetFactoryLineIdsForSubscriptions || []).filter(Boolean)
|
|
13844
13849
|
);
|
|
@@ -14009,7 +14014,7 @@ var useDashboardMetrics = ({ onLineMetricsUpdate, lineId, userAccessibleLineIds
|
|
|
14009
14014
|
});
|
|
14010
14015
|
const currentShiftDetails = shiftConfig ? getCurrentShift(defaultTimezone, shiftConfig) : getCurrentShift(defaultTimezone, staticShiftConfig);
|
|
14011
14016
|
const operationalDateForSubscription = currentShiftDetails.date;
|
|
14012
|
-
const targetLineIds = isFactory ? currentUserAccessibleLineIds || currentConfiguredLineIds : [currentLineIdToUse];
|
|
14017
|
+
const targetLineIds = isFactory ? explicitLineIdsRef.current || currentUserAccessibleLineIds || currentConfiguredLineIds : [currentLineIdToUse];
|
|
14013
14018
|
const filteredLineIds = targetLineIds.filter((id3) => id3 && id3 !== factoryViewIdentifier);
|
|
14014
14019
|
if (filteredLineIds.length === 0) {
|
|
14015
14020
|
logDebug("[useDashboardMetrics] Realtime setup skipped: no line IDs after filtering", {
|
|
@@ -20423,13 +20428,15 @@ var buildKPIsFromLineMetricsRow = (row) => {
|
|
|
20423
20428
|
};
|
|
20424
20429
|
var aggregateKPIsFromLineMetricsRows = (rows) => {
|
|
20425
20430
|
if (!rows || rows.length === 0) return createDefaultKPIs();
|
|
20426
|
-
const
|
|
20427
|
-
|
|
20428
|
-
const
|
|
20431
|
+
const eligibleRows = rows.filter((row) => toNumber(row?.avg_efficiency) >= 5);
|
|
20432
|
+
if (eligibleRows.length === 0) return createDefaultKPIs();
|
|
20433
|
+
const currentOutputSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.current_output), 0);
|
|
20434
|
+
const lineThresholdSum = eligibleRows.reduce((sum, row) => sum + toNumber(row.line_threshold), 0);
|
|
20435
|
+
const idealOutputSum = eligibleRows.reduce(
|
|
20429
20436
|
(sum, row) => sum + (toNumber(row.ideal_output) || toNumber(row.line_threshold)),
|
|
20430
20437
|
0
|
|
20431
20438
|
);
|
|
20432
|
-
const efficiencyValues =
|
|
20439
|
+
const efficiencyValues = eligibleRows.map((row) => {
|
|
20433
20440
|
const value = row?.avg_efficiency;
|
|
20434
20441
|
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
20435
20442
|
if (typeof value === "string" && value.trim() !== "") {
|
|
@@ -20439,10 +20446,10 @@ var aggregateKPIsFromLineMetricsRows = (rows) => {
|
|
|
20439
20446
|
return null;
|
|
20440
20447
|
}).filter((value) => value !== null);
|
|
20441
20448
|
const avgEfficiency = efficiencyValues.length > 0 ? efficiencyValues.reduce((sum, value) => sum + value, 0) / efficiencyValues.length : 0;
|
|
20442
|
-
const numLines =
|
|
20443
|
-
const avgCycleTime = numLines > 0 ?
|
|
20444
|
-
const totalUnderperforming =
|
|
20445
|
-
const totalWorkspaces =
|
|
20449
|
+
const numLines = eligibleRows.length;
|
|
20450
|
+
const avgCycleTime = numLines > 0 ? eligibleRows.reduce((sum, row) => sum + toNumber(row.avg_cycle_time), 0) / numLines : 0;
|
|
20451
|
+
const totalUnderperforming = eligibleRows.reduce((sum, row) => sum + toNumber(row.underperforming_workspaces), 0);
|
|
20452
|
+
const totalWorkspaces = eligibleRows.reduce((sum, row) => sum + toNumber(row.total_workspaces), 0);
|
|
20446
20453
|
return {
|
|
20447
20454
|
underperformingWorkers: {
|
|
20448
20455
|
current: totalUnderperforming,
|
|
@@ -34598,6 +34605,8 @@ var logDebug2 = (...args) => {
|
|
|
34598
34605
|
var VideoGridView = React142__namespace.default.memo(({
|
|
34599
34606
|
workspaces,
|
|
34600
34607
|
selectedLine,
|
|
34608
|
+
lineNames = {},
|
|
34609
|
+
lineOrder = [],
|
|
34601
34610
|
className = "",
|
|
34602
34611
|
legend,
|
|
34603
34612
|
videoSources = {},
|
|
@@ -34700,6 +34709,44 @@ var VideoGridView = React142__namespace.default.memo(({
|
|
|
34700
34709
|
}
|
|
34701
34710
|
}) : workspaces;
|
|
34702
34711
|
}, [workspaces, selectedLine]);
|
|
34712
|
+
const sortedWorkspaces = React142.useMemo(() => {
|
|
34713
|
+
return [...filteredWorkspaces].sort((a, b) => {
|
|
34714
|
+
if (a.line_id !== b.line_id) {
|
|
34715
|
+
return (a.line_id || "").localeCompare(b.line_id || "");
|
|
34716
|
+
}
|
|
34717
|
+
const aMatch = a.workspace_name.match(/WS(\d+)/);
|
|
34718
|
+
const bMatch = b.workspace_name.match(/WS(\d+)/);
|
|
34719
|
+
if (aMatch && bMatch) {
|
|
34720
|
+
const aNum = parseInt(aMatch[1], 10);
|
|
34721
|
+
const bNum = parseInt(bMatch[1], 10);
|
|
34722
|
+
return aNum - bNum;
|
|
34723
|
+
}
|
|
34724
|
+
return a.workspace_name.localeCompare(b.workspace_name);
|
|
34725
|
+
});
|
|
34726
|
+
}, [filteredWorkspaces]);
|
|
34727
|
+
const lineGroups = React142.useMemo(() => {
|
|
34728
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
34729
|
+
sortedWorkspaces.forEach((workspace) => {
|
|
34730
|
+
const lineId = workspace.line_id || "unknown";
|
|
34731
|
+
const existing = grouped.get(lineId);
|
|
34732
|
+
if (existing) {
|
|
34733
|
+
existing.push(workspace);
|
|
34734
|
+
return;
|
|
34735
|
+
}
|
|
34736
|
+
grouped.set(lineId, [workspace]);
|
|
34737
|
+
});
|
|
34738
|
+
const sortedRemainingLineIds = Array.from(grouped.keys()).sort((a, b) => a.localeCompare(b));
|
|
34739
|
+
const orderedLineIds = [
|
|
34740
|
+
...lineOrder.filter((lineId) => grouped.has(lineId)),
|
|
34741
|
+
...sortedRemainingLineIds.filter((lineId) => !lineOrder.includes(lineId))
|
|
34742
|
+
];
|
|
34743
|
+
return orderedLineIds.map((lineId) => ({
|
|
34744
|
+
lineId,
|
|
34745
|
+
lineName: lineNames[lineId] || `Line ${lineId.substring(0, 4)}`,
|
|
34746
|
+
workspaces: grouped.get(lineId) || []
|
|
34747
|
+
}));
|
|
34748
|
+
}, [sortedWorkspaces, lineOrder, lineNames]);
|
|
34749
|
+
lineGroups.length > 1;
|
|
34703
34750
|
const streamsReady = !videoStreamsLoading;
|
|
34704
34751
|
const calculateOptimalGrid = React142.useCallback(() => {
|
|
34705
34752
|
if (!containerRef.current) return;
|
|
@@ -34863,108 +34910,130 @@ var VideoGridView = React142__namespace.default.memo(({
|
|
|
34863
34910
|
stream_source: isR2Stream ? "r2" : "media_config"
|
|
34864
34911
|
});
|
|
34865
34912
|
}, []);
|
|
34913
|
+
const workspaceCards = React142.useMemo(() => {
|
|
34914
|
+
return sortedWorkspaces.map((workspace) => {
|
|
34915
|
+
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
34916
|
+
const workspaceKey = `${workspace.line_id || "unknown"}-${workspaceId}`;
|
|
34917
|
+
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
34918
|
+
const isVeryLowEfficiency = workspace.show_exclamation ?? (workspace.efficiency < 50 && workspace.efficiency >= 10);
|
|
34919
|
+
const workspaceCropping = getWorkspaceCropping(workspaceId, workspace.workspace_name);
|
|
34920
|
+
const workspaceStream = videoStreamsByWorkspaceId?.[workspaceId];
|
|
34921
|
+
const lastSeenLabel = workspace.workspace_uuid ? lastSeenByWorkspaceId[workspace.workspace_uuid]?.timeSinceLastUpdate : void 0;
|
|
34922
|
+
const r2Url = workspaceStream?.hls_url;
|
|
34923
|
+
const fallbackUrl = getWorkspaceHlsUrl(workspace.workspace_name, workspace.line_id);
|
|
34924
|
+
const hasR2Stream = Boolean(r2Url);
|
|
34925
|
+
const useFallback = r2FallbackWorkspaces.has(workspaceId) || streamsReady && !hasR2Stream;
|
|
34926
|
+
const hlsUrl = useFallback ? fallbackUrl : r2Url ?? "";
|
|
34927
|
+
const isR2Stream = !useFallback && hasR2Stream;
|
|
34928
|
+
const canAttemptR2 = hasR2Stream && !r2FallbackWorkspaces.has(workspaceId);
|
|
34929
|
+
const shouldPlay = isVisible && Boolean(hlsUrl) && (!failedStreams.has(workspaceId) || canAttemptR2);
|
|
34930
|
+
return {
|
|
34931
|
+
workspace,
|
|
34932
|
+
workspaceId,
|
|
34933
|
+
workspaceKey,
|
|
34934
|
+
isVisible,
|
|
34935
|
+
isVeryLowEfficiency,
|
|
34936
|
+
workspaceCropping,
|
|
34937
|
+
fallbackUrl,
|
|
34938
|
+
hlsUrl,
|
|
34939
|
+
isR2Stream,
|
|
34940
|
+
shouldPlay,
|
|
34941
|
+
lastSeenLabel
|
|
34942
|
+
};
|
|
34943
|
+
});
|
|
34944
|
+
}, [
|
|
34945
|
+
sortedWorkspaces,
|
|
34946
|
+
visibleWorkspaces,
|
|
34947
|
+
getWorkspaceCropping,
|
|
34948
|
+
videoStreamsByWorkspaceId,
|
|
34949
|
+
lastSeenByWorkspaceId,
|
|
34950
|
+
getWorkspaceHlsUrl,
|
|
34951
|
+
r2FallbackWorkspaces,
|
|
34952
|
+
streamsReady,
|
|
34953
|
+
failedStreams
|
|
34954
|
+
]);
|
|
34955
|
+
React142.useMemo(() => {
|
|
34956
|
+
const map = /* @__PURE__ */ new Map();
|
|
34957
|
+
workspaceCards.forEach((card) => {
|
|
34958
|
+
map.set(card.workspaceKey, card);
|
|
34959
|
+
});
|
|
34960
|
+
return map;
|
|
34961
|
+
}, [workspaceCards]);
|
|
34962
|
+
const croppedActiveCount = React142.useMemo(() => {
|
|
34963
|
+
return workspaceCards.reduce((count, card) => {
|
|
34964
|
+
if (card.shouldPlay && card.workspaceCropping) {
|
|
34965
|
+
return count + 1;
|
|
34966
|
+
}
|
|
34967
|
+
return count;
|
|
34968
|
+
}, 0);
|
|
34969
|
+
}, [workspaceCards]);
|
|
34970
|
+
const throttleCropping = croppedActiveCount > 10;
|
|
34971
|
+
const effectiveCanvasFps = throttleCropping ? 10 : canvasConfig?.fps;
|
|
34972
|
+
const effectiveUseRAF = throttleCropping ? false : canvasConfig?.useRAF;
|
|
34866
34973
|
const displayMinuteBucket = Math.floor(Date.now() / 6e4);
|
|
34867
|
-
|
|
34974
|
+
const renderWorkspaceCard = React142.useCallback((card, className2) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34868
34975
|
"div",
|
|
34869
34976
|
{
|
|
34870
|
-
|
|
34871
|
-
|
|
34872
|
-
|
|
34873
|
-
|
|
34874
|
-
|
|
34875
|
-
|
|
34876
|
-
|
|
34877
|
-
|
|
34878
|
-
|
|
34879
|
-
|
|
34880
|
-
|
|
34881
|
-
|
|
34882
|
-
|
|
34883
|
-
|
|
34884
|
-
|
|
34885
|
-
|
|
34886
|
-
|
|
34887
|
-
}
|
|
34888
|
-
|
|
34889
|
-
|
|
34890
|
-
|
|
34891
|
-
|
|
34892
|
-
|
|
34893
|
-
|
|
34894
|
-
|
|
34895
|
-
|
|
34896
|
-
|
|
34897
|
-
|
|
34898
|
-
|
|
34899
|
-
|
|
34900
|
-
|
|
34901
|
-
|
|
34902
|
-
|
|
34903
|
-
|
|
34904
|
-
|
|
34905
|
-
|
|
34906
|
-
|
|
34907
|
-
|
|
34908
|
-
|
|
34909
|
-
|
|
34910
|
-
|
|
34911
|
-
|
|
34912
|
-
|
|
34913
|
-
|
|
34914
|
-
|
|
34915
|
-
|
|
34916
|
-
|
|
34917
|
-
|
|
34918
|
-
|
|
34919
|
-
|
|
34920
|
-
|
|
34921
|
-
|
|
34922
|
-
|
|
34923
|
-
|
|
34924
|
-
}, 0);
|
|
34925
|
-
const throttleCropping = croppedActiveCount > 10;
|
|
34926
|
-
const effectiveCanvasFps = throttleCropping ? 10 : canvasConfig?.fps;
|
|
34927
|
-
const effectiveUseRAF = throttleCropping ? false : canvasConfig?.useRAF;
|
|
34928
|
-
return workspaceCards.map((card) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
34929
|
-
"div",
|
|
34930
|
-
{
|
|
34931
|
-
"data-workspace-id": card.workspaceId,
|
|
34932
|
-
className: "workspace-card relative w-full h-full",
|
|
34933
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
34934
|
-
VideoCard,
|
|
34935
|
-
{
|
|
34936
|
-
workspace: card.workspace,
|
|
34937
|
-
hlsUrl: card.hlsUrl,
|
|
34938
|
-
shouldPlay: card.shouldPlay,
|
|
34939
|
-
onClick: () => handleWorkspaceClick(card.workspace),
|
|
34940
|
-
onFatalError: () => handleStreamError(card.workspaceId, {
|
|
34941
|
-
isR2Stream: card.isR2Stream,
|
|
34942
|
-
fallbackUrl: card.fallbackUrl
|
|
34943
|
-
}),
|
|
34944
|
-
isVeryLowEfficiency: card.isVeryLowEfficiency,
|
|
34945
|
-
legend: effectiveLegend,
|
|
34946
|
-
cropping: card.workspaceCropping,
|
|
34947
|
-
canvasFps: effectiveCanvasFps,
|
|
34948
|
-
displayName: (
|
|
34949
|
-
// Create line-aware lookup key: lineId_workspaceName
|
|
34950
|
-
// This ensures correct mapping when multiple lines have same workspace names
|
|
34951
|
-
displayNames[`${card.workspace.line_id}_${card.workspace.workspace_name}`] || // Always pass line_id to fallback to ensure correct mapping per line
|
|
34952
|
-
getWorkspaceDisplayName(card.workspace.workspace_name, card.workspace.line_id)
|
|
34953
|
-
),
|
|
34954
|
-
lastSeenLabel: card.lastSeenLabel,
|
|
34955
|
-
useRAF: effectiveUseRAF,
|
|
34956
|
-
displayMinuteBucket,
|
|
34957
|
-
compact: !selectedLine,
|
|
34958
|
-
onMouseEnter: onWorkspaceHover ? () => onWorkspaceHover(card.workspaceId) : void 0,
|
|
34959
|
-
onMouseLeave: onWorkspaceHoverEnd ? () => onWorkspaceHoverEnd(card.workspaceId) : void 0
|
|
34960
|
-
}
|
|
34961
|
-
) })
|
|
34977
|
+
"data-workspace-id": card.workspaceId,
|
|
34978
|
+
className: className2,
|
|
34979
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
34980
|
+
VideoCard,
|
|
34981
|
+
{
|
|
34982
|
+
workspace: card.workspace,
|
|
34983
|
+
hlsUrl: card.hlsUrl,
|
|
34984
|
+
shouldPlay: card.shouldPlay,
|
|
34985
|
+
onClick: () => handleWorkspaceClick(card.workspace),
|
|
34986
|
+
onFatalError: () => handleStreamError(card.workspaceId, {
|
|
34987
|
+
isR2Stream: card.isR2Stream,
|
|
34988
|
+
fallbackUrl: card.fallbackUrl
|
|
34989
|
+
}),
|
|
34990
|
+
isVeryLowEfficiency: card.isVeryLowEfficiency,
|
|
34991
|
+
legend: effectiveLegend,
|
|
34992
|
+
cropping: card.workspaceCropping,
|
|
34993
|
+
canvasFps: effectiveCanvasFps,
|
|
34994
|
+
displayName: displayNames[`${card.workspace.line_id}_${card.workspace.workspace_name}`] || getWorkspaceDisplayName(card.workspace.workspace_name, card.workspace.line_id),
|
|
34995
|
+
lastSeenLabel: card.lastSeenLabel,
|
|
34996
|
+
useRAF: effectiveUseRAF,
|
|
34997
|
+
displayMinuteBucket,
|
|
34998
|
+
compact: !selectedLine,
|
|
34999
|
+
onMouseEnter: onWorkspaceHover ? () => onWorkspaceHover(card.workspaceId) : void 0,
|
|
35000
|
+
onMouseLeave: onWorkspaceHoverEnd ? () => onWorkspaceHoverEnd(card.workspaceId) : void 0
|
|
35001
|
+
}
|
|
35002
|
+
) })
|
|
35003
|
+
},
|
|
35004
|
+
card.workspaceKey
|
|
35005
|
+
), [
|
|
35006
|
+
displayNames,
|
|
35007
|
+
displayMinuteBucket,
|
|
35008
|
+
effectiveCanvasFps,
|
|
35009
|
+
effectiveLegend,
|
|
35010
|
+
effectiveUseRAF,
|
|
35011
|
+
getWorkspaceDisplayName,
|
|
35012
|
+
handleStreamError,
|
|
35013
|
+
handleWorkspaceClick,
|
|
35014
|
+
onWorkspaceHover,
|
|
35015
|
+
onWorkspaceHoverEnd,
|
|
35016
|
+
selectedLine
|
|
35017
|
+
]);
|
|
35018
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `relative overflow-hidden h-full w-full bg-slate-50/30 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
35019
|
+
"div",
|
|
35020
|
+
{
|
|
35021
|
+
ref: containerRef,
|
|
35022
|
+
className: "h-full w-full px-1 sm:px-2 py-1 sm:py-2",
|
|
35023
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
35024
|
+
"div",
|
|
35025
|
+
{
|
|
35026
|
+
className: "grid h-full w-full gap-1.5 sm:gap-2",
|
|
35027
|
+
style: {
|
|
35028
|
+
gridTemplateColumns: `repeat(${gridCols}, 1fr)`,
|
|
35029
|
+
gridTemplateRows: `repeat(${gridRows}, 1fr)`,
|
|
35030
|
+
gridAutoFlow: "row"
|
|
34962
35031
|
},
|
|
34963
|
-
card
|
|
34964
|
-
|
|
34965
|
-
|
|
35032
|
+
children: workspaceCards.map((card) => renderWorkspaceCard(card, "workspace-card relative w-full h-full"))
|
|
35033
|
+
}
|
|
35034
|
+
)
|
|
34966
35035
|
}
|
|
34967
|
-
) })
|
|
35036
|
+
) });
|
|
34968
35037
|
});
|
|
34969
35038
|
VideoGridView.displayName = "VideoGridView";
|
|
34970
35039
|
var MapGridView = React142__namespace.default.memo(({
|
|
@@ -47677,7 +47746,7 @@ var LinePdfGenerator = ({
|
|
|
47677
47746
|
doc.text(`${lineInfo.metrics.current_output} / ${lineInfo.metrics.line_threshold}`, 120, kpiStartY);
|
|
47678
47747
|
createKPIBox(kpiStartY + kpiSpacing);
|
|
47679
47748
|
doc.setFont("helvetica", "normal");
|
|
47680
|
-
doc.text("
|
|
47749
|
+
doc.text("Issue Resolution Time:", 25, kpiStartY + kpiSpacing);
|
|
47681
47750
|
doc.setFont("helvetica", "bold");
|
|
47682
47751
|
const resolutionSeconds = issueResolutionSummary ? issueResolutionSummary.mean_resolution_seconds ?? issueResolutionSummary.median_resolution_seconds : null;
|
|
47683
47752
|
const displayValue = resolutionSeconds !== null ? formatResolutionDuration2(resolutionSeconds) : "-";
|
|
@@ -50387,29 +50456,29 @@ var Legend5 = ({
|
|
|
50387
50456
|
}) => {
|
|
50388
50457
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
50389
50458
|
const exclamationLabel = useBottleneckLabel ? "Bottleneck" : "<50% efficiency";
|
|
50390
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-
|
|
50459
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 sm:gap-4 text-xs font-medium text-slate-600", children: [
|
|
50391
50460
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "font-medium text-gray-700 hidden sm:block", children: [
|
|
50392
50461
|
metricLabel,
|
|
50393
50462
|
":"
|
|
50394
50463
|
] }),
|
|
50395
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
50396
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
50397
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-
|
|
50398
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
50464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 sm:gap-4", children: [
|
|
50465
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
50466
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 sm:w-2.5 sm:h-2.5 rounded-full bg-[#00AB45]" }),
|
|
50467
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatPercentRange(effectiveLegend.green_min, effectiveLegend.green_max) })
|
|
50399
50468
|
] }),
|
|
50400
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
50401
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-
|
|
50402
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
50469
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
50470
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 sm:w-2.5 sm:h-2.5 rounded-full bg-[#FFB020]" }),
|
|
50471
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatPercentRange(effectiveLegend.yellow_min, effectiveLegend.yellow_max) })
|
|
50403
50472
|
] }),
|
|
50404
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
50405
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-
|
|
50406
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
50473
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
50474
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 sm:w-2.5 sm:h-2.5 rounded-full bg-[#E34329]" }),
|
|
50475
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: formatPercentRange(effectiveLegend.red_min, effectiveLegend.red_max) })
|
|
50407
50476
|
] })
|
|
50408
50477
|
] }),
|
|
50409
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block w-px h-
|
|
50410
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
|
|
50411
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-3 h-3 sm:w-
|
|
50412
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", {
|
|
50478
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block w-px h-4 bg-slate-200 mx-1" }),
|
|
50479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
50480
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center w-3 h-3 sm:w-4 sm:h-4 bg-[#E34329] rounded-full text-white font-bold text-[8px] sm:text-[10px]", children: "!" }),
|
|
50481
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: exclamationLabel })
|
|
50413
50482
|
] })
|
|
50414
50483
|
] });
|
|
50415
50484
|
};
|
|
@@ -50519,6 +50588,7 @@ var WorkspaceGrid = React142__namespace.default.memo(({
|
|
|
50519
50588
|
isPdfMode = false,
|
|
50520
50589
|
customWorkspacePositions,
|
|
50521
50590
|
lineNames = {},
|
|
50591
|
+
lineOrder = [],
|
|
50522
50592
|
factoryView = "factory",
|
|
50523
50593
|
line2Uuid = "line-2",
|
|
50524
50594
|
className = "",
|
|
@@ -50529,7 +50599,8 @@ var WorkspaceGrid = React142__namespace.default.memo(({
|
|
|
50529
50599
|
videoStreamsLoading = false,
|
|
50530
50600
|
displayNames = {},
|
|
50531
50601
|
onWorkspaceHover,
|
|
50532
|
-
onWorkspaceHoverEnd
|
|
50602
|
+
onWorkspaceHoverEnd,
|
|
50603
|
+
toolbarRightContent
|
|
50533
50604
|
}) => {
|
|
50534
50605
|
const dashboardConfig = useDashboardConfig();
|
|
50535
50606
|
const mapViewEnabled = dashboardConfig?.mapViewConfig?.enabled ?? false;
|
|
@@ -50563,29 +50634,30 @@ var WorkspaceGrid = React142__namespace.default.memo(({
|
|
|
50563
50634
|
() => viewMode === "video" ? getVideoGridLegendLabel(workspaces) : MAP_GRID_LEGEND_LABEL,
|
|
50564
50635
|
[viewMode, workspaces]
|
|
50565
50636
|
);
|
|
50566
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `
|
|
50567
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
50568
|
-
/* @__PURE__ */ jsxRuntime.
|
|
50569
|
-
|
|
50637
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col w-full h-full overflow-hidden bg-slate-50/50 ${className}`, children: [
|
|
50638
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-none px-4 py-3 z-20 flex flex-row items-center justify-between gap-4", children: [
|
|
50639
|
+
/* @__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, useBottleneckLabel: hasFlowBuffers, metricLabel: legendMetricLabel }) }) }),
|
|
50640
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-3 shrink-0", children: [
|
|
50641
|
+
toolbarRightContent,
|
|
50570
50642
|
mapViewEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
50571
50643
|
"button",
|
|
50572
50644
|
{
|
|
50573
50645
|
onClick: handleViewModeToggle,
|
|
50574
|
-
className: "flex items-center gap-2 px-3 py-1.5 bg-white border border-
|
|
50646
|
+
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",
|
|
50575
50647
|
title: viewMode === "video" ? "Switch to Map View" : "Switch to Video View",
|
|
50576
50648
|
children: viewMode === "video" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
50577
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Map, { className: "w-4 h-4 text-
|
|
50578
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm
|
|
50649
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Map, { className: "w-4 h-4 text-slate-500" }),
|
|
50650
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Map View" })
|
|
50579
50651
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
50580
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { className: "w-4 h-4 text-
|
|
50581
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm
|
|
50652
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { className: "w-4 h-4 text-slate-500" }),
|
|
50653
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Video View" })
|
|
50582
50654
|
] })
|
|
50583
50655
|
}
|
|
50584
50656
|
)
|
|
50585
|
-
] })
|
|
50586
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden mt-1 mr-32", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, useBottleneckLabel: hasFlowBuffers, metricLabel: legendMetricLabel }) })
|
|
50657
|
+
] })
|
|
50587
50658
|
] }),
|
|
50588
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
50659
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden px-3 py-2 bg-white border-b border-slate-200/60 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, useBottleneckLabel: hasFlowBuffers, metricLabel: legendMetricLabel }) }),
|
|
50660
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 relative overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { mode: "wait", children: viewMode === "video" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
50589
50661
|
motion.div,
|
|
50590
50662
|
{
|
|
50591
50663
|
initial: { opacity: 0 },
|
|
@@ -50597,6 +50669,8 @@ var WorkspaceGrid = React142__namespace.default.memo(({
|
|
|
50597
50669
|
VideoGridViewComponent,
|
|
50598
50670
|
{
|
|
50599
50671
|
workspaces,
|
|
50672
|
+
lineNames,
|
|
50673
|
+
lineOrder,
|
|
50600
50674
|
videoSources,
|
|
50601
50675
|
videoStreamsByWorkspaceId,
|
|
50602
50676
|
videoStreamsLoading,
|
|
@@ -59459,6 +59533,7 @@ function HomeView({
|
|
|
59459
59533
|
[dbLines]
|
|
59460
59534
|
);
|
|
59461
59535
|
const isSupervisor = user?.role_level === "supervisor";
|
|
59536
|
+
const hasUser = Boolean(user);
|
|
59462
59537
|
const visibleLineIds = React142.useMemo(() => {
|
|
59463
59538
|
const scoped = Array.from(new Set(allLineIds.filter(Boolean)));
|
|
59464
59539
|
if (enabledLineIdSet.size === 0) {
|
|
@@ -59468,57 +59543,100 @@ function HomeView({
|
|
|
59468
59543
|
}, [allLineIds, enabledLineIdSet]);
|
|
59469
59544
|
const fallbackLineId = visibleLineIds[0] || defaultLineId;
|
|
59470
59545
|
const defaultHomeLineId = fallbackLineId;
|
|
59471
|
-
const
|
|
59472
|
-
|
|
59473
|
-
|
|
59474
|
-
|
|
59475
|
-
|
|
59476
|
-
|
|
59477
|
-
|
|
59478
|
-
|
|
59546
|
+
const visibleLineIdsKey = visibleLineIds.join(",");
|
|
59547
|
+
const normalizeSelectedLineIds = (lineIdsToNormalize) => {
|
|
59548
|
+
const allowedLineIds = new Set(visibleLineIds);
|
|
59549
|
+
const requestedLineIds = new Set((lineIdsToNormalize || []).filter(Boolean));
|
|
59550
|
+
const normalized = visibleLineIds.filter((lineId) => requestedLineIds.has(lineId) && allowedLineIds.has(lineId));
|
|
59551
|
+
if (normalized.length > 0) {
|
|
59552
|
+
return normalized;
|
|
59553
|
+
}
|
|
59554
|
+
if (defaultHomeLineId && allowedLineIds.has(defaultHomeLineId)) {
|
|
59555
|
+
return [defaultHomeLineId];
|
|
59556
|
+
}
|
|
59557
|
+
return visibleLineIds.length > 0 ? [visibleLineIds[0]] : [];
|
|
59558
|
+
};
|
|
59559
|
+
const selectedLineIdsEqual = (left, right) => {
|
|
59560
|
+
if (left.length !== right.length) return false;
|
|
59561
|
+
return left.every((value, index) => value === right[index]);
|
|
59562
|
+
};
|
|
59563
|
+
const isAllLinesSelection = (lineIdsToCheck) => visibleLineIds.length > 0 && lineIdsToCheck.length === visibleLineIds.length;
|
|
59564
|
+
const readPersistedSelectedLineIds = () => {
|
|
59479
59565
|
if (typeof window === "undefined") {
|
|
59480
|
-
return
|
|
59566
|
+
return null;
|
|
59481
59567
|
}
|
|
59482
59568
|
try {
|
|
59483
|
-
const
|
|
59484
|
-
if (
|
|
59485
|
-
|
|
59486
|
-
|
|
59569
|
+
const savedLineIds = sessionStorage.getItem("optifye_home_line_filters_v2");
|
|
59570
|
+
if (savedLineIds) {
|
|
59571
|
+
const parsedLineIds = JSON.parse(savedLineIds);
|
|
59572
|
+
if (Array.isArray(parsedLineIds)) {
|
|
59573
|
+
return normalizeSelectedLineIds(parsedLineIds.map((lineId) => String(lineId)));
|
|
59574
|
+
}
|
|
59575
|
+
}
|
|
59576
|
+
const legacyLineId = sessionStorage.getItem("optifye_home_line_filter");
|
|
59577
|
+
if (legacyLineId) {
|
|
59578
|
+
if (legacyLineId === factoryViewId) {
|
|
59579
|
+
return normalizeSelectedLineIds(visibleLineIds);
|
|
59487
59580
|
}
|
|
59581
|
+
return normalizeSelectedLineIds([legacyLineId]);
|
|
59488
59582
|
}
|
|
59489
59583
|
} catch (error) {
|
|
59490
59584
|
console.warn("Failed to read line filter from sessionStorage:", error);
|
|
59491
59585
|
}
|
|
59492
|
-
return
|
|
59493
|
-
}
|
|
59586
|
+
return null;
|
|
59587
|
+
};
|
|
59588
|
+
const [selectedLineIds, setSelectedLineIds] = React142.useState(() => readPersistedSelectedLineIds() || normalizeSelectedLineIds([defaultHomeLineId]));
|
|
59589
|
+
const [isLineSelectorOpen, setIsLineSelectorOpen] = React142.useState(false);
|
|
59590
|
+
const [pendingSelectedLineIds, setPendingSelectedLineIds] = React142.useState([]);
|
|
59591
|
+
const lineSelectorRef = React142.useRef(null);
|
|
59494
59592
|
React142.useEffect(() => {
|
|
59495
|
-
if (
|
|
59593
|
+
if (isLineSelectorOpen) {
|
|
59594
|
+
setPendingSelectedLineIds(selectedLineIds);
|
|
59595
|
+
}
|
|
59596
|
+
}, [isLineSelectorOpen, selectedLineIds]);
|
|
59597
|
+
React142.useEffect(() => {
|
|
59598
|
+
if (!hasUser || visibleLineIds.length === 0) {
|
|
59496
59599
|
return;
|
|
59497
59600
|
}
|
|
59498
|
-
|
|
59499
|
-
|
|
59500
|
-
if (
|
|
59501
|
-
|
|
59502
|
-
setSelectedLineId(savedLineId);
|
|
59503
|
-
}
|
|
59504
|
-
return;
|
|
59601
|
+
const restoredLineIds = readPersistedSelectedLineIds();
|
|
59602
|
+
setSelectedLineIds((previousSelectedLineIds) => {
|
|
59603
|
+
if (restoredLineIds) {
|
|
59604
|
+
return selectedLineIdsEqual(restoredLineIds, previousSelectedLineIds) ? previousSelectedLineIds : restoredLineIds;
|
|
59505
59605
|
}
|
|
59606
|
+
const normalizedCurrentLineIds = normalizeSelectedLineIds(previousSelectedLineIds);
|
|
59607
|
+
return selectedLineIdsEqual(normalizedCurrentLineIds, previousSelectedLineIds) ? previousSelectedLineIds : normalizedCurrentLineIds;
|
|
59608
|
+
});
|
|
59609
|
+
}, [hasUser, visibleLineIdsKey, defaultHomeLineId, factoryViewId]);
|
|
59610
|
+
React142.useEffect(() => {
|
|
59611
|
+
try {
|
|
59612
|
+
sessionStorage.setItem("optifye_home_line_filters_v2", JSON.stringify(selectedLineIds));
|
|
59613
|
+
sessionStorage.removeItem("optifye_home_line_filter");
|
|
59506
59614
|
} catch (error) {
|
|
59507
|
-
console.warn("Failed to
|
|
59615
|
+
console.warn("Failed to save line filter to sessionStorage:", error);
|
|
59508
59616
|
}
|
|
59509
|
-
|
|
59617
|
+
}, [selectedLineIds]);
|
|
59618
|
+
React142.useEffect(() => {
|
|
59619
|
+
if (!isLineSelectorOpen) {
|
|
59510
59620
|
return;
|
|
59511
59621
|
}
|
|
59512
|
-
|
|
59513
|
-
|
|
59514
|
-
|
|
59515
|
-
|
|
59516
|
-
|
|
59517
|
-
|
|
59518
|
-
|
|
59519
|
-
|
|
59520
|
-
|
|
59521
|
-
]);
|
|
59622
|
+
const handleClickOutside = (event) => {
|
|
59623
|
+
if (lineSelectorRef.current && !lineSelectorRef.current.contains(event.target)) {
|
|
59624
|
+
setIsLineSelectorOpen(false);
|
|
59625
|
+
}
|
|
59626
|
+
};
|
|
59627
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
59628
|
+
return () => {
|
|
59629
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
59630
|
+
};
|
|
59631
|
+
}, [isLineSelectorOpen]);
|
|
59632
|
+
const primarySelectedLineId = selectedLineIds[0] || defaultHomeLineId;
|
|
59633
|
+
const isMultiLineSelection = selectedLineIds.length > 1;
|
|
59634
|
+
const selectedLineIdsKey = selectedLineIds.join(",");
|
|
59635
|
+
const selectedLineIdSet = React142.useMemo(
|
|
59636
|
+
() => new Set(selectedLineIds),
|
|
59637
|
+
[selectedLineIds]
|
|
59638
|
+
);
|
|
59639
|
+
const metricsScopeLineId = isMultiLineSelection ? factoryViewId : primarySelectedLineId;
|
|
59522
59640
|
const userCompanyId = React142.useMemo(() => {
|
|
59523
59641
|
return user?.properties?.company_id || user?.company_id || entityConfig.companyId;
|
|
59524
59642
|
}, [user, entityConfig.companyId]);
|
|
@@ -59538,12 +59656,8 @@ function HomeView({
|
|
|
59538
59656
|
React142.useEffect(() => {
|
|
59539
59657
|
const initDisplayNames = async () => {
|
|
59540
59658
|
try {
|
|
59541
|
-
|
|
59542
|
-
|
|
59543
|
-
await preInitializeWorkspaceDisplayNames(lineId);
|
|
59544
|
-
}
|
|
59545
|
-
} else {
|
|
59546
|
-
await preInitializeWorkspaceDisplayNames(selectedLineId);
|
|
59659
|
+
for (const lineId of selectedLineIds) {
|
|
59660
|
+
await preInitializeWorkspaceDisplayNames(lineId);
|
|
59547
59661
|
}
|
|
59548
59662
|
setDisplayNamesInitialized(true);
|
|
59549
59663
|
} catch (error) {
|
|
@@ -59552,8 +59666,8 @@ function HomeView({
|
|
|
59552
59666
|
}
|
|
59553
59667
|
};
|
|
59554
59668
|
initDisplayNames();
|
|
59555
|
-
}, [
|
|
59556
|
-
const displayNameLineId =
|
|
59669
|
+
}, [selectedLineIdsKey]);
|
|
59670
|
+
const displayNameLineId = isMultiLineSelection ? void 0 : primarySelectedLineId;
|
|
59557
59671
|
const {
|
|
59558
59672
|
displayNames: workspaceDisplayNames,
|
|
59559
59673
|
loading: displayNamesLoading,
|
|
@@ -59582,7 +59696,8 @@ function HomeView({
|
|
|
59582
59696
|
error: metricsError,
|
|
59583
59697
|
refetch: refetchMetrics
|
|
59584
59698
|
} = useDashboardMetrics({
|
|
59585
|
-
lineId:
|
|
59699
|
+
lineId: metricsScopeLineId,
|
|
59700
|
+
lineIds: selectedLineIds,
|
|
59586
59701
|
onLineMetricsUpdate: handleLineMetricsUpdate,
|
|
59587
59702
|
userAccessibleLineIds: visibleLineIds
|
|
59588
59703
|
// Pass user's accessible lines for supervisor filtering
|
|
@@ -59590,10 +59705,8 @@ function HomeView({
|
|
|
59590
59705
|
const trendGroups = React142.useMemo(() => {
|
|
59591
59706
|
const lineMetricsRows = lineMetrics || [];
|
|
59592
59707
|
if (!lineMetricsRows.length) return null;
|
|
59593
|
-
if (
|
|
59594
|
-
const
|
|
59595
|
-
if (!candidateLineIds.length) return null;
|
|
59596
|
-
const rowsForLines = lineMetricsRows.filter((row2) => candidateLineIds.includes(row2?.line_id));
|
|
59708
|
+
if (selectedLineIds.length > 1) {
|
|
59709
|
+
const rowsForLines = lineMetricsRows.filter((row2) => selectedLineIdSet.has(row2?.line_id));
|
|
59597
59710
|
if (!rowsForLines.length) return null;
|
|
59598
59711
|
const groupsMap = /* @__PURE__ */ new Map();
|
|
59599
59712
|
rowsForLines.forEach((row2) => {
|
|
@@ -59616,16 +59729,16 @@ function HomeView({
|
|
|
59616
59729
|
shiftId: group.shiftId
|
|
59617
59730
|
}));
|
|
59618
59731
|
}
|
|
59619
|
-
const row = lineMetricsRows.find((r2) => r2?.line_id ===
|
|
59732
|
+
const row = lineMetricsRows.find((r2) => r2?.line_id === primarySelectedLineId);
|
|
59620
59733
|
if (!row?.date || row?.shift_id === void 0 || row?.shift_id === null) {
|
|
59621
59734
|
return null;
|
|
59622
59735
|
}
|
|
59623
59736
|
return [{
|
|
59624
|
-
lineIds: [
|
|
59737
|
+
lineIds: [primarySelectedLineId],
|
|
59625
59738
|
date: row.date,
|
|
59626
59739
|
shiftId: row.shift_id
|
|
59627
59740
|
}];
|
|
59628
|
-
}, [
|
|
59741
|
+
}, [lineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
59629
59742
|
const trendOptions = React142.useMemo(() => {
|
|
59630
59743
|
if (!trendGroups || !userCompanyId) return null;
|
|
59631
59744
|
return {
|
|
@@ -59653,17 +59766,18 @@ function HomeView({
|
|
|
59653
59766
|
}, [workspaceMetrics, metricsLoading, metricsError]);
|
|
59654
59767
|
const kpis = React142.useMemo(() => {
|
|
59655
59768
|
const lineMetricsRows = lineMetrics || [];
|
|
59656
|
-
if (
|
|
59657
|
-
|
|
59658
|
-
|
|
59769
|
+
if (selectedLineIds.length > 1) {
|
|
59770
|
+
const rowsForSelectedLines = lineMetricsRows.filter((row2) => selectedLineIdSet.has(row2?.line_id));
|
|
59771
|
+
if (metricsLoading && rowsForSelectedLines.length === 0) return null;
|
|
59772
|
+
return aggregateKPIsFromLineMetricsRows(rowsForSelectedLines);
|
|
59659
59773
|
}
|
|
59660
|
-
const row = lineMetricsRows.find((r2) => r2?.line_id ===
|
|
59774
|
+
const row = lineMetricsRows.find((r2) => r2?.line_id === primarySelectedLineId);
|
|
59661
59775
|
if (!row) {
|
|
59662
59776
|
if (metricsLoading) return null;
|
|
59663
59777
|
return buildKPIsFromLineMetricsRow(null);
|
|
59664
59778
|
}
|
|
59665
59779
|
return buildKPIsFromLineMetricsRow(row);
|
|
59666
|
-
}, [
|
|
59780
|
+
}, [lineMetrics, metricsLoading, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
59667
59781
|
const kpisWithTrend = React142.useMemo(() => {
|
|
59668
59782
|
if (!kpis) return null;
|
|
59669
59783
|
if (!kpiTrend) return kpis;
|
|
@@ -59688,30 +59802,30 @@ function HomeView({
|
|
|
59688
59802
|
};
|
|
59689
59803
|
}, [kpis, kpiTrend]);
|
|
59690
59804
|
const selectedLineMeta = React142.useMemo(
|
|
59691
|
-
() => dbLines.find((line) => line.id ===
|
|
59692
|
-
[dbLines,
|
|
59805
|
+
() => selectedLineIds.length === 1 ? dbLines.find((line) => line.id === primarySelectedLineId) : void 0,
|
|
59806
|
+
[dbLines, primarySelectedLineId, selectedLineIds.length]
|
|
59693
59807
|
);
|
|
59694
|
-
const selectedMonitoringMode =
|
|
59808
|
+
const selectedMonitoringMode = selectedLineIds.length === 1 ? selectedLineMeta?.monitoring_mode ?? "output" : "output";
|
|
59695
59809
|
const isUptimeMode = selectedMonitoringMode === "uptime";
|
|
59696
59810
|
const averageIdleTimeSeconds = React142.useMemo(() => {
|
|
59697
59811
|
if (!isUptimeMode) return null;
|
|
59698
|
-
const targetWorkspaces =
|
|
59812
|
+
const targetWorkspaces = workspaceMetrics.filter((ws) => ws.line_id === primarySelectedLineId);
|
|
59699
59813
|
const idleValues = targetWorkspaces.map((ws) => ws.idle_time).filter((value) => Number.isFinite(value));
|
|
59700
59814
|
if (idleValues.length === 0) return 0;
|
|
59701
59815
|
const totalIdle = idleValues.reduce((sum, value) => sum + value, 0);
|
|
59702
59816
|
return totalIdle / idleValues.length;
|
|
59703
|
-
}, [isUptimeMode,
|
|
59817
|
+
}, [isUptimeMode, primarySelectedLineId, workspaceMetrics]);
|
|
59704
59818
|
const {
|
|
59705
59819
|
activeBreaks: allActiveBreaks,
|
|
59706
59820
|
isLoading: breaksLoading,
|
|
59707
59821
|
error: breaksError
|
|
59708
|
-
} = useActiveBreaks(
|
|
59822
|
+
} = useActiveBreaks(visibleLineIds);
|
|
59709
59823
|
const activeBreaks = React142.useMemo(() => {
|
|
59710
|
-
if (
|
|
59824
|
+
if (isAllLinesSelection(selectedLineIds)) {
|
|
59711
59825
|
return allActiveBreaks;
|
|
59712
59826
|
}
|
|
59713
|
-
return allActiveBreaks.filter((breakItem) => breakItem.lineId
|
|
59714
|
-
}, [allActiveBreaks,
|
|
59827
|
+
return allActiveBreaks.filter((breakItem) => selectedLineIdSet.has(breakItem.lineId));
|
|
59828
|
+
}, [allActiveBreaks, selectedLineIdSet, selectedLineIds]);
|
|
59715
59829
|
const activeBreakLineIds = React142.useMemo(
|
|
59716
59830
|
() => new Set(activeBreaks.map((breakItem) => breakItem.lineId)),
|
|
59717
59831
|
[activeBreaks]
|
|
@@ -60018,7 +60132,7 @@ function HomeView({
|
|
|
60018
60132
|
// Round to 1 decimal
|
|
60019
60133
|
kpisWithTrend?.avgCycleTime?.change,
|
|
60020
60134
|
kpisWithTrend?.qualityCompliance?.value ? Math.round(kpisWithTrend.qualityCompliance.value) : null,
|
|
60021
|
-
|
|
60135
|
+
selectedLineIdsKey
|
|
60022
60136
|
]);
|
|
60023
60137
|
React142.useEffect(() => {
|
|
60024
60138
|
setIsHydrated(true);
|
|
@@ -60035,27 +60149,62 @@ function HomeView({
|
|
|
60035
60149
|
setErrorMessage(null);
|
|
60036
60150
|
}
|
|
60037
60151
|
}, [metricsError]);
|
|
60038
|
-
const
|
|
60152
|
+
const getTrackedLineScope = React142.useCallback((lineIdsForScope) => {
|
|
60153
|
+
if (isAllLinesSelection(lineIdsForScope)) {
|
|
60154
|
+
return factoryViewId;
|
|
60155
|
+
}
|
|
60156
|
+
if (lineIdsForScope.length === 1) {
|
|
60157
|
+
return lineIdsForScope[0];
|
|
60158
|
+
}
|
|
60159
|
+
return "custom_multi";
|
|
60160
|
+
}, [factoryViewId, visibleLineIds.length]);
|
|
60161
|
+
const getLineSelectionLabel = React142.useCallback((lineIdsForScope) => {
|
|
60162
|
+
if (isAllLinesSelection(lineIdsForScope)) {
|
|
60163
|
+
return "All Lines";
|
|
60164
|
+
}
|
|
60165
|
+
if (lineIdsForScope.length === 1) {
|
|
60166
|
+
const lineId = lineIdsForScope[0];
|
|
60167
|
+
return mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}`;
|
|
60168
|
+
}
|
|
60169
|
+
return `${lineIdsForScope.length} Lines Selected`;
|
|
60170
|
+
}, [mergedLineNames, visibleLineIds.length]);
|
|
60171
|
+
const updateSelectedLineIds = React142.useCallback((nextLineIds) => {
|
|
60172
|
+
const normalizedLineIds = normalizeSelectedLineIds(nextLineIds);
|
|
60173
|
+
if (selectedLineIdsEqual(normalizedLineIds, selectedLineIds)) {
|
|
60174
|
+
return;
|
|
60175
|
+
}
|
|
60039
60176
|
setIsChangingFilter(true);
|
|
60040
|
-
|
|
60177
|
+
setSelectedLineIds(normalizedLineIds);
|
|
60041
60178
|
trackCoreEvent("monitor line filter changed", {
|
|
60042
|
-
previous_line_id:
|
|
60043
|
-
new_line_id:
|
|
60044
|
-
|
|
60179
|
+
previous_line_id: getTrackedLineScope(selectedLineIds),
|
|
60180
|
+
new_line_id: getTrackedLineScope(normalizedLineIds),
|
|
60181
|
+
previous_line_ids: selectedLineIds,
|
|
60182
|
+
new_line_ids: normalizedLineIds,
|
|
60183
|
+
selected_line_count: normalizedLineIds.length,
|
|
60184
|
+
selection_mode: isAllLinesSelection(normalizedLineIds) ? "all" : normalizedLineIds.length === 1 ? "single" : "custom",
|
|
60185
|
+
line_name: getLineSelectionLabel(normalizedLineIds)
|
|
60045
60186
|
});
|
|
60046
|
-
|
|
60047
|
-
|
|
60048
|
-
|
|
60049
|
-
|
|
60187
|
+
}, [factoryViewId, getLineSelectionLabel, getTrackedLineScope, selectedLineIds, selectedLineIdsKey, visibleLineIds]);
|
|
60188
|
+
React142.useCallback(() => {
|
|
60189
|
+
updateSelectedLineIds(visibleLineIds);
|
|
60190
|
+
}, [updateSelectedLineIds, visibleLineIds]);
|
|
60191
|
+
React142.useCallback((lineId) => {
|
|
60192
|
+
const currentSelection = new Set(selectedLineIds);
|
|
60193
|
+
if (currentSelection.has(lineId)) {
|
|
60194
|
+
if (currentSelection.size <= 1) {
|
|
60195
|
+
return;
|
|
60196
|
+
}
|
|
60197
|
+
currentSelection.delete(lineId);
|
|
60198
|
+
} else {
|
|
60199
|
+
currentSelection.add(lineId);
|
|
60050
60200
|
}
|
|
60051
|
-
|
|
60201
|
+
updateSelectedLineIds(Array.from(currentSelection));
|
|
60202
|
+
}, [selectedLineIds, updateSelectedLineIds]);
|
|
60052
60203
|
React142.useEffect(() => {
|
|
60053
60204
|
if (!metricsLoading && isChangingFilter) {
|
|
60054
|
-
|
|
60055
|
-
setIsChangingFilter(false);
|
|
60056
|
-
}
|
|
60205
|
+
setIsChangingFilter(false);
|
|
60057
60206
|
}
|
|
60058
|
-
}, [metricsLoading,
|
|
60207
|
+
}, [metricsLoading, isChangingFilter]);
|
|
60059
60208
|
React142.useEffect(() => {
|
|
60060
60209
|
if (!metricsLoading && !hasInitialDataLoaded) {
|
|
60061
60210
|
setHasInitialDataLoaded(true);
|
|
@@ -60074,11 +60223,107 @@ function HomeView({
|
|
|
60074
60223
|
if (visibleLineIds.length <= 1) {
|
|
60075
60224
|
return null;
|
|
60076
60225
|
}
|
|
60077
|
-
|
|
60078
|
-
|
|
60079
|
-
/* @__PURE__ */ jsxRuntime.
|
|
60226
|
+
const allLinesSelected = isAllLinesSelection(pendingSelectedLineIds);
|
|
60227
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: lineSelectorRef, className: "relative", children: [
|
|
60228
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
60229
|
+
"button",
|
|
60230
|
+
{
|
|
60231
|
+
type: "button",
|
|
60232
|
+
onClick: () => setIsLineSelectorOpen((previous) => !previous),
|
|
60233
|
+
className: "flex min-w-[180px] items-center justify-between gap-2 rounded-md border border-slate-200 bg-white px-3 py-1.5 text-left text-sm font-medium shadow-sm transition-colors hover:bg-slate-50 text-slate-700",
|
|
60234
|
+
"aria-haspopup": "menu",
|
|
60235
|
+
"aria-expanded": isLineSelectorOpen,
|
|
60236
|
+
"aria-label": "Select lines",
|
|
60237
|
+
children: [
|
|
60238
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: getLineSelectionLabel(selectedLineIds) }),
|
|
60239
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: `h-4 w-4 text-slate-400 transition-transform ${isLineSelectorOpen ? "rotate-180" : ""}` })
|
|
60240
|
+
]
|
|
60241
|
+
}
|
|
60242
|
+
),
|
|
60243
|
+
isLineSelectorOpen ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute right-0 top-full z-50 mt-2 w-[280px] rounded-lg border border-slate-200 bg-white p-3 shadow-xl flex flex-col gap-2", children: [
|
|
60244
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pb-2 border-b border-slate-100", children: [
|
|
60245
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-slate-800", children: "Select Lines" }),
|
|
60246
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60247
|
+
"button",
|
|
60248
|
+
{
|
|
60249
|
+
type: "button",
|
|
60250
|
+
onClick: () => setPendingSelectedLineIds([]),
|
|
60251
|
+
className: "text-xs font-medium text-blue-600 hover:text-blue-700 transition-colors",
|
|
60252
|
+
children: "Clear All"
|
|
60253
|
+
}
|
|
60254
|
+
)
|
|
60255
|
+
] }),
|
|
60256
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { className: "flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-1.5 text-sm font-medium text-slate-900 hover:bg-slate-50 transition-colors", children: [
|
|
60257
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60258
|
+
"input",
|
|
60259
|
+
{
|
|
60260
|
+
type: "checkbox",
|
|
60261
|
+
className: "h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500",
|
|
60262
|
+
checked: allLinesSelected,
|
|
60263
|
+
onChange: () => setPendingSelectedLineIds(allLinesSelected ? [] : visibleLineIds)
|
|
60264
|
+
}
|
|
60265
|
+
),
|
|
60266
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "All Lines" })
|
|
60267
|
+
] }),
|
|
60268
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-56 space-y-0.5 overflow-y-auto pr-1", children: visibleLineIds.map((lineId) => {
|
|
60269
|
+
const isChecked = pendingSelectedLineIds.includes(lineId);
|
|
60270
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
60271
|
+
"label",
|
|
60272
|
+
{
|
|
60273
|
+
className: "flex cursor-pointer items-center gap-2.5 rounded-md px-2 py-1.5 text-sm transition-colors text-slate-700 hover:bg-slate-50",
|
|
60274
|
+
children: [
|
|
60275
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60276
|
+
"input",
|
|
60277
|
+
{
|
|
60278
|
+
type: "checkbox",
|
|
60279
|
+
className: "h-4 w-4 rounded border-slate-300 text-blue-600 focus:ring-blue-500",
|
|
60280
|
+
checked: isChecked,
|
|
60281
|
+
onChange: () => {
|
|
60282
|
+
setPendingSelectedLineIds((prev) => {
|
|
60283
|
+
const current = new Set(prev);
|
|
60284
|
+
if (current.has(lineId)) {
|
|
60285
|
+
current.delete(lineId);
|
|
60286
|
+
} else {
|
|
60287
|
+
current.add(lineId);
|
|
60288
|
+
}
|
|
60289
|
+
return Array.from(current);
|
|
60290
|
+
});
|
|
60291
|
+
}
|
|
60292
|
+
}
|
|
60293
|
+
),
|
|
60294
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}` })
|
|
60295
|
+
]
|
|
60296
|
+
},
|
|
60297
|
+
lineId
|
|
60298
|
+
);
|
|
60299
|
+
}) }),
|
|
60300
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "pt-3 pb-1 mt-1 border-t border-slate-100 flex justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
60301
|
+
"button",
|
|
60302
|
+
{
|
|
60303
|
+
type: "button",
|
|
60304
|
+
onClick: () => {
|
|
60305
|
+
if (pendingSelectedLineIds.length > 0) {
|
|
60306
|
+
updateSelectedLineIds(pendingSelectedLineIds);
|
|
60307
|
+
}
|
|
60308
|
+
setIsLineSelectorOpen(false);
|
|
60309
|
+
},
|
|
60310
|
+
disabled: pendingSelectedLineIds.length === 0,
|
|
60311
|
+
className: "bg-blue-600 text-white px-4 py-1.5 rounded-md text-sm font-medium hover:bg-blue-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors w-full",
|
|
60312
|
+
children: "Apply"
|
|
60313
|
+
}
|
|
60314
|
+
) })
|
|
60315
|
+
] }) : null
|
|
60080
60316
|
] });
|
|
60081
|
-
}, [
|
|
60317
|
+
}, [
|
|
60318
|
+
getLineSelectionLabel,
|
|
60319
|
+
isLineSelectorOpen,
|
|
60320
|
+
mergedLineNames,
|
|
60321
|
+
selectedLineIds,
|
|
60322
|
+
pendingSelectedLineIds,
|
|
60323
|
+
visibleLineIds,
|
|
60324
|
+
updateSelectedLineIds,
|
|
60325
|
+
isAllLinesSelection
|
|
60326
|
+
]);
|
|
60082
60327
|
const useSmoothLoading = (isLoading, minDuration = 400) => {
|
|
60083
60328
|
const [showLoading, setShowLoading] = React142.useState(isLoading);
|
|
60084
60329
|
const loadingStartRef2 = React142.useRef(null);
|
|
@@ -60124,11 +60369,11 @@ function HomeView({
|
|
|
60124
60369
|
const isDataLoading = metricsLoading || displayNamesLoading && workspaceMetrics.length === 0;
|
|
60125
60370
|
const hasKpiDataReady = React142.useMemo(() => {
|
|
60126
60371
|
const lineMetricsRows = lineMetrics || [];
|
|
60127
|
-
if (
|
|
60128
|
-
return lineMetricsRows.
|
|
60372
|
+
if (selectedLineIds.length > 1) {
|
|
60373
|
+
return lineMetricsRows.some((row) => selectedLineIdSet.has(row?.line_id));
|
|
60129
60374
|
}
|
|
60130
|
-
return lineMetricsRows.some((row) => row?.line_id ===
|
|
60131
|
-
}, [lineMetrics,
|
|
60375
|
+
return lineMetricsRows.some((row) => row?.line_id === primarySelectedLineId);
|
|
60376
|
+
}, [lineMetrics, primarySelectedLineId, selectedLineIdSet, selectedLineIds.length]);
|
|
60132
60377
|
const isKpiLoading = !hasKpiDataReady;
|
|
60133
60378
|
React142.useEffect(() => {
|
|
60134
60379
|
const minLoadingDurationMs = 250;
|
|
@@ -60190,76 +60435,77 @@ function HomeView({
|
|
|
60190
60435
|
DashboardHeader,
|
|
60191
60436
|
{
|
|
60192
60437
|
lineTitle,
|
|
60193
|
-
lineId:
|
|
60438
|
+
lineId: primarySelectedLineId,
|
|
60194
60439
|
className: "w-full",
|
|
60195
60440
|
headerControls: kpiSectionControl
|
|
60196
60441
|
}
|
|
60197
60442
|
) }) }),
|
|
60198
|
-
/* @__PURE__ */ jsxRuntime.
|
|
60199
|
-
|
|
60200
|
-
|
|
60201
|
-
|
|
60202
|
-
{
|
|
60203
|
-
|
|
60204
|
-
|
|
60205
|
-
|
|
60443
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-y-auto sm:overflow-hidden relative flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-[calc(100vh-100px)] sm:min-h-0", children: workspaceMetricsWithBreakState.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
60444
|
+
motion.div,
|
|
60445
|
+
{
|
|
60446
|
+
initial: { opacity: 0, scale: 0.98 },
|
|
60447
|
+
animate: { opacity: 1, scale: 1 },
|
|
60448
|
+
transition: { duration: 0.3 },
|
|
60449
|
+
className: "h-full",
|
|
60450
|
+
children: React142__namespace.default.createElement(WorkspaceGrid, {
|
|
60451
|
+
workspaces: workspaceMetricsWithBreakState,
|
|
60452
|
+
lineNames: mergedLineNames,
|
|
60453
|
+
lineOrder: selectedLineIds,
|
|
60454
|
+
factoryView: factoryViewId,
|
|
60455
|
+
legend: efficiencyLegend,
|
|
60456
|
+
videoSources,
|
|
60457
|
+
videoStreamsByWorkspaceId,
|
|
60458
|
+
videoStreamsLoading,
|
|
60459
|
+
displayNames: workspaceDisplayNames,
|
|
60460
|
+
hasFlowBuffers,
|
|
60206
60461
|
className: "h-full",
|
|
60207
|
-
|
|
60208
|
-
|
|
60209
|
-
|
|
60210
|
-
|
|
60211
|
-
|
|
60212
|
-
|
|
60213
|
-
|
|
60214
|
-
|
|
60215
|
-
|
|
60216
|
-
|
|
60217
|
-
|
|
60218
|
-
|
|
60219
|
-
|
|
60220
|
-
|
|
60221
|
-
|
|
60222
|
-
|
|
60223
|
-
|
|
60224
|
-
|
|
60225
|
-
{
|
|
60226
|
-
|
|
60227
|
-
|
|
60228
|
-
|
|
60229
|
-
|
|
60230
|
-
|
|
60231
|
-
|
|
60232
|
-
|
|
60233
|
-
|
|
60234
|
-
|
|
60235
|
-
|
|
60236
|
-
|
|
60462
|
+
toolbarRightContent: lineSelectorComponent,
|
|
60463
|
+
onWorkspaceHover: handleWorkspaceHover,
|
|
60464
|
+
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
60465
|
+
})
|
|
60466
|
+
},
|
|
60467
|
+
selectedLineIdsKey
|
|
60468
|
+
) : !shouldShowDataLoading && hasInitialDataLoaded ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
60469
|
+
motion.div,
|
|
60470
|
+
{
|
|
60471
|
+
initial: { opacity: 0 },
|
|
60472
|
+
animate: { opacity: 1 },
|
|
60473
|
+
transition: { duration: 0.3 },
|
|
60474
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(NoWorkspaceData, { message: "No workspace data available. Adjust the selected lines or check configurations." })
|
|
60475
|
+
}
|
|
60476
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
60477
|
+
motion.div,
|
|
60478
|
+
{
|
|
60479
|
+
initial: { opacity: 0, scale: 0.98 },
|
|
60480
|
+
animate: { opacity: 1, scale: 1 },
|
|
60481
|
+
transition: { duration: 0.3 },
|
|
60482
|
+
className: "h-full",
|
|
60483
|
+
children: React142__namespace.default.createElement(WorkspaceGrid, {
|
|
60484
|
+
workspaces: [],
|
|
60485
|
+
// Show empty grid while loading
|
|
60486
|
+
lineNames: mergedLineNames,
|
|
60487
|
+
lineOrder: selectedLineIds,
|
|
60488
|
+
factoryView: factoryViewId,
|
|
60489
|
+
legend: efficiencyLegend,
|
|
60490
|
+
videoSources,
|
|
60491
|
+
videoStreamsByWorkspaceId,
|
|
60492
|
+
videoStreamsLoading,
|
|
60493
|
+
displayNames: workspaceDisplayNames,
|
|
60494
|
+
hasFlowBuffers,
|
|
60237
60495
|
className: "h-full",
|
|
60238
|
-
|
|
60239
|
-
|
|
60240
|
-
|
|
60241
|
-
|
|
60242
|
-
|
|
60243
|
-
|
|
60244
|
-
|
|
60245
|
-
videoStreamsByWorkspaceId,
|
|
60246
|
-
videoStreamsLoading,
|
|
60247
|
-
displayNames: workspaceDisplayNames,
|
|
60248
|
-
hasFlowBuffers,
|
|
60249
|
-
className: "h-full",
|
|
60250
|
-
onWorkspaceHover: handleWorkspaceHover,
|
|
60251
|
-
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
60252
|
-
})
|
|
60253
|
-
},
|
|
60254
|
-
selectedLineId
|
|
60255
|
-
) })
|
|
60256
|
-
] })
|
|
60496
|
+
toolbarRightContent: lineSelectorComponent,
|
|
60497
|
+
onWorkspaceHover: handleWorkspaceHover,
|
|
60498
|
+
onWorkspaceHoverEnd: handleWorkspaceHoverEnd
|
|
60499
|
+
})
|
|
60500
|
+
},
|
|
60501
|
+
selectedLineIdsKey
|
|
60502
|
+
) }) })
|
|
60257
60503
|
] }),
|
|
60258
60504
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
60259
60505
|
BreakNotificationPopup,
|
|
60260
60506
|
{
|
|
60261
60507
|
activeBreaks,
|
|
60262
|
-
lineNames,
|
|
60508
|
+
lineNames: mergedLineNames,
|
|
60263
60509
|
isVisible: !breaksLoading && !breaksError && !breakNotificationsDismissed,
|
|
60264
60510
|
onDismiss: () => setBreakNotificationsDismissed(true)
|
|
60265
60511
|
}
|
|
@@ -61408,9 +61654,9 @@ var MetricCards = React142.memo(({
|
|
|
61408
61654
|
animate: "animate",
|
|
61409
61655
|
className: `grid grid-cols-1 sm:grid-cols-2 ${largeGridColumns} gap-3 sm:gap-4 mb-2 h-auto lg:flex-[2] lg:min-h-[250px]`,
|
|
61410
61656
|
children: [
|
|
61411
|
-
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61412
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700
|
|
61413
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-
|
|
61657
|
+
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61658
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Line Output" }) }),
|
|
61659
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
61414
61660
|
OutputProgressChart,
|
|
61415
61661
|
{
|
|
61416
61662
|
currentOutput: lineInfo?.metrics.current_output || 0,
|
|
@@ -61418,19 +61664,19 @@ var MetricCards = React142.memo(({
|
|
|
61418
61664
|
}
|
|
61419
61665
|
) }) })
|
|
61420
61666
|
] }),
|
|
61421
|
-
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61422
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center
|
|
61423
|
-
/* @__PURE__ */ jsxRuntime.
|
|
61424
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-4xl sm:text-5xl md:text-
|
|
61425
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xl sm:text-2xl md:text-2xl lg:text-3xl text-gray-500 ml-1 sm:ml-2", children: [
|
|
61667
|
+
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61668
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Underperforming Workspaces" }) }),
|
|
61669
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-baseline", children: [
|
|
61670
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap tracking-tight text-4xl sm:text-5xl md:text-5xl lg:text-4xl xl:text-5xl 2xl:text-6xl font-bold text-red-600", children: lineInfo?.metrics.underperforming_workspaces }),
|
|
61671
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xl sm:text-2xl md:text-2xl lg:text-xl xl:text-2xl 2xl:text-3xl text-gray-500 ml-1 sm:ml-2", children: [
|
|
61426
61672
|
"/ ",
|
|
61427
61673
|
lineInfo?.metrics.total_workspaces
|
|
61428
61674
|
] })
|
|
61429
|
-
] })
|
|
61675
|
+
] }) })
|
|
61430
61676
|
] }),
|
|
61431
|
-
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61432
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center
|
|
61433
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-
|
|
61677
|
+
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61678
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Average Efficiency" }) }),
|
|
61679
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `whitespace-nowrap tracking-tight text-4xl sm:text-5xl md:text-5xl lg:text-4xl xl:text-5xl 2xl:text-6xl font-bold ${efficiencyColorClass}`, children: [
|
|
61434
61680
|
efficiency.toFixed(1),
|
|
61435
61681
|
"%"
|
|
61436
61682
|
] }) })
|
|
@@ -61439,11 +61685,11 @@ var MetricCards = React142.memo(({
|
|
|
61439
61685
|
motion.div,
|
|
61440
61686
|
{
|
|
61441
61687
|
variants: itemVariants,
|
|
61442
|
-
className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 h-[240px] sm:h-[260px] md:h-auto",
|
|
61688
|
+
className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto",
|
|
61443
61689
|
children: [
|
|
61444
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-
|
|
61445
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700", children: "
|
|
61446
|
-
/* @__PURE__ */ jsxRuntime.jsx(outline.InformationCircleIcon, { className: "w-4 h-4 text-gray-400 cursor-help" }),
|
|
61690
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-10 sm:h-12 flex items-start justify-center gap-1.5 mb-2 mt-1 relative group z-10", children: [
|
|
61691
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Issue Resolution Time" }),
|
|
61692
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.InformationCircleIcon, { className: "w-4 h-4 text-gray-400 cursor-help flex-shrink-0" }),
|
|
61447
61693
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-full left-1/2 transform -translate-x-1/2 mt-2.5 w-[260px] p-3 bg-white rounded-lg shadow-xl border border-gray-200 opacity-0 invisible group-hover:opacity-100 group-hover:visible transition-all duration-200 pointer-events-none z-50", children: [
|
|
61448
61694
|
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-center text-xs text-gray-600 leading-relaxed mb-2.5 px-1", children: "The average time a supervisor takes to resolve a workstation in red." }),
|
|
61449
61695
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-gray-50 rounded-md py-1.5 border border-gray-100/80", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-center font-medium text-[11px] text-gray-500", children: [
|
|
@@ -61453,13 +61699,13 @@ var MetricCards = React142.memo(({
|
|
|
61453
61699
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -top-1.5 left-1/2 transform -translate-x-1/2 w-3 h-3 bg-white border-l border-t border-gray-200 rotate-45" })
|
|
61454
61700
|
] })
|
|
61455
61701
|
] }),
|
|
61456
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "
|
|
61702
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `whitespace-nowrap tracking-tight text-3xl sm:text-4xl md:text-4xl lg:text-3xl xl:text-4xl 2xl:text-5xl font-bold ${shouldMaskIssueResolution ? "text-gray-400" : "text-gray-900"}`, children: issueResolutionValue }) })
|
|
61457
61703
|
]
|
|
61458
61704
|
}
|
|
61459
61705
|
),
|
|
61460
|
-
showIdleTime && /* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61461
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center
|
|
61462
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-
|
|
61706
|
+
showIdleTime && /* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61707
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Idle Time Breakdown" }) }),
|
|
61708
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
61463
61709
|
IdleTimeReasonChart,
|
|
61464
61710
|
{
|
|
61465
61711
|
data: idleTimeData?.chartData,
|
|
@@ -61519,9 +61765,9 @@ var LineUptimeMetricCards = React142.memo(({
|
|
|
61519
61765
|
animate: "animate",
|
|
61520
61766
|
className: `grid grid-cols-1 sm:grid-cols-2 ${showIdleTime ? "lg:grid-cols-4" : "lg:grid-cols-3"} gap-3 sm:gap-4 mb-2 h-auto lg:flex-[2] lg:min-h-[250px]`,
|
|
61521
61767
|
children: [
|
|
61522
|
-
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61523
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700
|
|
61524
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-
|
|
61768
|
+
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61769
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Utilization" }) }),
|
|
61770
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
61525
61771
|
OutputProgressChart,
|
|
61526
61772
|
{
|
|
61527
61773
|
currentOutput: Number(utilizationText),
|
|
@@ -61529,17 +61775,17 @@ var LineUptimeMetricCards = React142.memo(({
|
|
|
61529
61775
|
}
|
|
61530
61776
|
) }) })
|
|
61531
61777
|
] }),
|
|
61532
|
-
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61533
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center
|
|
61534
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-
|
|
61778
|
+
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61779
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Stoppages" }) }),
|
|
61780
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap tracking-tight text-4xl sm:text-5xl md:text-5xl lg:text-4xl xl:text-5xl 2xl:text-6xl font-bold text-red-600", children: stoppages }) })
|
|
61535
61781
|
] }),
|
|
61536
|
-
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61537
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center
|
|
61538
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-
|
|
61782
|
+
/* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61783
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Average Idle Time" }) }),
|
|
61784
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: `whitespace-nowrap tracking-tight text-3xl sm:text-4xl md:text-5xl lg:text-4xl xl:text-5xl 2xl:text-6xl font-bold ${idleTimeSeconds <= 0 ? "text-green-500" : idleTimeSeconds <= 300 ? "text-yellow-500" : "text-red-500"}`, children: formatIdleTime(idleTimeSeconds) }) })
|
|
61539
61785
|
] }),
|
|
61540
|
-
showIdleTime && /* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61541
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center
|
|
61542
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-
|
|
61786
|
+
showIdleTime && /* @__PURE__ */ jsxRuntime.jsxs(motion.div, { variants: itemVariants, className: "bg-white rounded-xl shadow-sm p-3 sm:p-4 flex flex-col overflow-hidden h-[240px] sm:h-[260px] md:h-auto", children: [
|
|
61787
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-10 sm:h-12 flex items-start justify-center mb-2 mt-1", children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-sm sm:text-base font-bold text-gray-700 text-center", children: "Idle Time Breakdown" }) }),
|
|
61788
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
61543
61789
|
IdleTimeReasonChart,
|
|
61544
61790
|
{
|
|
61545
61791
|
data: idleTimeData?.chartData,
|