@optifye/dashboard-core 6.6.10 → 6.6.11
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 +3 -0
- package/dist/index.js +205 -66
- package/dist/index.mjs +205 -66
- package/package.json +1 -1
package/dist/index.css
CHANGED
|
@@ -2148,6 +2148,9 @@ body {
|
|
|
2148
2148
|
.bg-black\/80 {
|
|
2149
2149
|
background-color: rgb(0 0 0 / 0.8);
|
|
2150
2150
|
}
|
|
2151
|
+
.bg-black\/90 {
|
|
2152
|
+
background-color: rgb(0 0 0 / 0.9);
|
|
2153
|
+
}
|
|
2151
2154
|
.bg-blue-100 {
|
|
2152
2155
|
--tw-bg-opacity: 1;
|
|
2153
2156
|
background-color: rgb(219 234 254 / var(--tw-bg-opacity, 1));
|
package/dist/index.js
CHANGED
|
@@ -22279,7 +22279,7 @@ var WorkspaceMetricCardsImpl = ({
|
|
|
22279
22279
|
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { className: "flex flex-col bg-white shadow-sm h-full min-h-[150px] sm:min-h-0", children: [
|
|
22280
22280
|
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
22281
22281
|
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6 sm:py-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
22282
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
22282
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
22283
22283
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
22284
22284
|
"Standard: ",
|
|
22285
22285
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -25959,8 +25959,19 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25959
25959
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
25960
25960
|
const dailyData = [];
|
|
25961
25961
|
let maxOutput = 0;
|
|
25962
|
-
let
|
|
25963
|
-
let
|
|
25962
|
+
let lastSetTarget = 0;
|
|
25963
|
+
for (let day = daysInMonth; day >= 1; day--) {
|
|
25964
|
+
const dayData = data.find((d) => {
|
|
25965
|
+
const date = new Date(d.date);
|
|
25966
|
+
return date.getDate() === day;
|
|
25967
|
+
});
|
|
25968
|
+
const shiftData = dayData ? selectedShift === "day" ? dayData.dayShift : dayData.nightShift : null;
|
|
25969
|
+
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
25970
|
+
if (idealOutput > 0) {
|
|
25971
|
+
lastSetTarget = idealOutput;
|
|
25972
|
+
break;
|
|
25973
|
+
}
|
|
25974
|
+
}
|
|
25964
25975
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
25965
25976
|
const dayData = data.find((d) => {
|
|
25966
25977
|
const date = new Date(d.date);
|
|
@@ -25970,11 +25981,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25970
25981
|
const output = shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
25971
25982
|
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
25972
25983
|
if (output > maxOutput) maxOutput = output;
|
|
25973
|
-
|
|
25974
|
-
totalIdealOutput += idealOutput;
|
|
25975
|
-
validDaysCount++;
|
|
25976
|
-
}
|
|
25977
|
-
const color2 = output >= idealOutput ? "#00AB45" : "#E34329";
|
|
25984
|
+
const color2 = output >= lastSetTarget ? "#00AB45" : "#E34329";
|
|
25978
25985
|
dailyData.push({
|
|
25979
25986
|
hour: getOrdinal(day),
|
|
25980
25987
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -25989,14 +25996,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25989
25996
|
// Not used but keeps structure consistent
|
|
25990
25997
|
});
|
|
25991
25998
|
}
|
|
25992
|
-
const
|
|
25993
|
-
const calculatedMax = Math.max(maxOutput, avgIdealOutput);
|
|
25999
|
+
const calculatedMax = Math.max(maxOutput, lastSetTarget);
|
|
25994
26000
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
25995
|
-
return { data: dailyData, maxOutput,
|
|
26001
|
+
return { data: dailyData, maxOutput, lastSetTarget, yAxisMax };
|
|
25996
26002
|
}, [data, month, year, selectedShift]);
|
|
25997
26003
|
const yAxisTicks = React21.useMemo(() => {
|
|
25998
26004
|
const max = chartData.yAxisMax;
|
|
25999
|
-
const target = chartData.
|
|
26005
|
+
const target = chartData.lastSetTarget;
|
|
26000
26006
|
if (!max || max <= 0) return void 0;
|
|
26001
26007
|
const desiredIntervals = 4;
|
|
26002
26008
|
const roughStep = max / desiredIntervals;
|
|
@@ -26014,7 +26020,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26014
26020
|
ticks.push(Math.round(target));
|
|
26015
26021
|
}
|
|
26016
26022
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
26017
|
-
}, [chartData.yAxisMax, chartData.
|
|
26023
|
+
}, [chartData.yAxisMax, chartData.lastSetTarget]);
|
|
26018
26024
|
const pieChartData = React21.useMemo(() => {
|
|
26019
26025
|
const validShifts = data.map((d) => selectedShift === "day" ? d.dayShift : d.nightShift).filter(hasRealData);
|
|
26020
26026
|
if (validShifts.length === 0) return [];
|
|
@@ -26326,7 +26332,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26326
26332
|
tick: (props) => {
|
|
26327
26333
|
const { x, y, payload } = props;
|
|
26328
26334
|
const value = Math.round(payload.value);
|
|
26329
|
-
const targetValue = Math.round(chartData.
|
|
26335
|
+
const targetValue = Math.round(chartData.lastSetTarget);
|
|
26330
26336
|
const isTarget = Math.abs(value - targetValue) < 1 && targetValue > 0;
|
|
26331
26337
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
26332
26338
|
"text",
|
|
@@ -26350,10 +26356,10 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26350
26356
|
content: CustomTooltip
|
|
26351
26357
|
}
|
|
26352
26358
|
),
|
|
26353
|
-
chartData.
|
|
26359
|
+
chartData.lastSetTarget > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
26354
26360
|
recharts.ReferenceLine,
|
|
26355
26361
|
{
|
|
26356
|
-
y: chartData.
|
|
26362
|
+
y: chartData.lastSetTarget,
|
|
26357
26363
|
stroke: "#E34329",
|
|
26358
26364
|
strokeDasharray: "5 5",
|
|
26359
26365
|
strokeWidth: 2
|
|
@@ -26411,11 +26417,11 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26411
26417
|
]
|
|
26412
26418
|
}
|
|
26413
26419
|
) }) }),
|
|
26414
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.
|
|
26420
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.lastSetTarget > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26415
26421
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-0.5 border-t-2 border-dashed", style: { borderColor: "#E34329" } }),
|
|
26416
26422
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-gray-600", children: [
|
|
26417
26423
|
"Target: ",
|
|
26418
|
-
Math.round(chartData.
|
|
26424
|
+
Math.round(chartData.lastSetTarget),
|
|
26419
26425
|
" units/day"
|
|
26420
26426
|
] })
|
|
26421
26427
|
] }) })
|
|
@@ -27261,6 +27267,36 @@ var TimePickerDropdown = ({
|
|
|
27261
27267
|
] })
|
|
27262
27268
|
] });
|
|
27263
27269
|
};
|
|
27270
|
+
var ERROR_MAPPING = {
|
|
27271
|
+
1: {
|
|
27272
|
+
// MEDIA_ERR_ABORTED
|
|
27273
|
+
code: 1,
|
|
27274
|
+
type: "recoverable" /* RECOVERABLE */,
|
|
27275
|
+
message: "Video loading was interrupted",
|
|
27276
|
+
canRetry: true
|
|
27277
|
+
},
|
|
27278
|
+
2: {
|
|
27279
|
+
// MEDIA_ERR_NETWORK
|
|
27280
|
+
code: 2,
|
|
27281
|
+
type: "recoverable" /* RECOVERABLE */,
|
|
27282
|
+
message: "Network error - please check your internet connection",
|
|
27283
|
+
canRetry: true
|
|
27284
|
+
},
|
|
27285
|
+
3: {
|
|
27286
|
+
// MEDIA_ERR_DECODE
|
|
27287
|
+
code: 3,
|
|
27288
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27289
|
+
message: "Stream corrupted due to internet connection",
|
|
27290
|
+
canRetry: false
|
|
27291
|
+
},
|
|
27292
|
+
4: {
|
|
27293
|
+
// MEDIA_ERR_SRC_NOT_SUPPORTED
|
|
27294
|
+
code: 4,
|
|
27295
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27296
|
+
message: "Video format not supported by your browser. Please use Google Chrome.",
|
|
27297
|
+
canRetry: false
|
|
27298
|
+
}
|
|
27299
|
+
};
|
|
27264
27300
|
var videoPlayerStyles = `
|
|
27265
27301
|
.video-player-container {
|
|
27266
27302
|
width: 100%;
|
|
@@ -27491,8 +27527,21 @@ var VideoPlayer = React21__namespace.default.forwardRef(({
|
|
|
27491
27527
|
player.on("seeked", () => onSeeked?.(player));
|
|
27492
27528
|
player.on("error", () => {
|
|
27493
27529
|
const error = player.error();
|
|
27494
|
-
|
|
27495
|
-
|
|
27530
|
+
const errorCode = error?.code ?? 0;
|
|
27531
|
+
const errorInfo = ERROR_MAPPING[errorCode] || {
|
|
27532
|
+
code: errorCode || 0,
|
|
27533
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27534
|
+
message: "Unknown playback error occurred",
|
|
27535
|
+
canRetry: false
|
|
27536
|
+
};
|
|
27537
|
+
console.error("[VideoPlayer] Video.js error:", {
|
|
27538
|
+
code: errorCode,
|
|
27539
|
+
type: errorInfo.type,
|
|
27540
|
+
message: errorInfo.message,
|
|
27541
|
+
canRetry: errorInfo.canRetry,
|
|
27542
|
+
originalError: error
|
|
27543
|
+
});
|
|
27544
|
+
onError?.(player, errorInfo);
|
|
27496
27545
|
});
|
|
27497
27546
|
if (src) {
|
|
27498
27547
|
const isHLS = src.endsWith(".m3u8") || src.startsWith("#EXTM3U");
|
|
@@ -28670,7 +28719,7 @@ var FileManagerFilters = ({
|
|
|
28670
28719
|
];
|
|
28671
28720
|
percentileCategories.forEach((category) => {
|
|
28672
28721
|
if (category.count > 0 && shouldShowCategory(category.id)) {
|
|
28673
|
-
tree.
|
|
28722
|
+
tree.push(category);
|
|
28674
28723
|
}
|
|
28675
28724
|
});
|
|
28676
28725
|
return tree;
|
|
@@ -29387,7 +29436,12 @@ var BottlenecksContent = ({
|
|
|
29387
29436
|
} catch (err) {
|
|
29388
29437
|
console.error("[BottlenecksContent] Error fetching clip counts:", err);
|
|
29389
29438
|
if (isMountedRef.current) {
|
|
29390
|
-
setError(
|
|
29439
|
+
setError({
|
|
29440
|
+
type: "fatal",
|
|
29441
|
+
message: "Failed to load clip counts. Please try again.",
|
|
29442
|
+
canSkip: false,
|
|
29443
|
+
canRetry: true
|
|
29444
|
+
});
|
|
29391
29445
|
setIsLoading(false);
|
|
29392
29446
|
}
|
|
29393
29447
|
} finally {
|
|
@@ -29471,7 +29525,12 @@ var BottlenecksContent = ({
|
|
|
29471
29525
|
} catch (err) {
|
|
29472
29526
|
console.error("Error loading first video for category:", err);
|
|
29473
29527
|
if (isMountedRef.current) {
|
|
29474
|
-
setError(
|
|
29528
|
+
setError({
|
|
29529
|
+
type: "fatal",
|
|
29530
|
+
message: "Failed to load clips. Please try again.",
|
|
29531
|
+
canSkip: false,
|
|
29532
|
+
canRetry: true
|
|
29533
|
+
});
|
|
29475
29534
|
setIsCategoryLoading(false);
|
|
29476
29535
|
}
|
|
29477
29536
|
} finally {
|
|
@@ -29753,7 +29812,12 @@ var BottlenecksContent = ({
|
|
|
29753
29812
|
} catch (error2) {
|
|
29754
29813
|
console.error(`[BottlenecksContent] Error loading clip by ID (${clipId}):`, error2);
|
|
29755
29814
|
if (isMountedRef.current) {
|
|
29756
|
-
setError(
|
|
29815
|
+
setError({
|
|
29816
|
+
type: "fatal",
|
|
29817
|
+
message: "Failed to load selected clip. Please try again.",
|
|
29818
|
+
canSkip: true,
|
|
29819
|
+
canRetry: true
|
|
29820
|
+
});
|
|
29757
29821
|
clearLoadingState();
|
|
29758
29822
|
}
|
|
29759
29823
|
}
|
|
@@ -29776,7 +29840,12 @@ var BottlenecksContent = ({
|
|
|
29776
29840
|
}
|
|
29777
29841
|
} catch (error2) {
|
|
29778
29842
|
console.error(`[BottlenecksContent] Error in legacy loadAndPlayClip:`, error2);
|
|
29779
|
-
setError(
|
|
29843
|
+
setError({
|
|
29844
|
+
type: "fatal",
|
|
29845
|
+
message: "Failed to load selected clip. Please try again.",
|
|
29846
|
+
canSkip: true,
|
|
29847
|
+
canRetry: true
|
|
29848
|
+
});
|
|
29780
29849
|
setIsNavigating(false);
|
|
29781
29850
|
}
|
|
29782
29851
|
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById]);
|
|
@@ -29816,7 +29885,12 @@ var BottlenecksContent = ({
|
|
|
29816
29885
|
}
|
|
29817
29886
|
} catch (error2) {
|
|
29818
29887
|
console.error(`[handleNext] Error navigating:`, error2);
|
|
29819
|
-
setError(
|
|
29888
|
+
setError({
|
|
29889
|
+
type: "fatal",
|
|
29890
|
+
message: "Failed to navigate to next clip",
|
|
29891
|
+
canSkip: true,
|
|
29892
|
+
canRetry: true
|
|
29893
|
+
});
|
|
29820
29894
|
clearLoadingState();
|
|
29821
29895
|
}
|
|
29822
29896
|
}, [clearLoadingState, s3ClipsService]);
|
|
@@ -29852,7 +29926,12 @@ var BottlenecksContent = ({
|
|
|
29852
29926
|
}
|
|
29853
29927
|
} catch (error2) {
|
|
29854
29928
|
console.error(`[handlePrevious] Error navigating:`, error2);
|
|
29855
|
-
setError(
|
|
29929
|
+
setError({
|
|
29930
|
+
type: "fatal",
|
|
29931
|
+
message: "Failed to navigate to previous clip",
|
|
29932
|
+
canSkip: true,
|
|
29933
|
+
canRetry: true
|
|
29934
|
+
});
|
|
29856
29935
|
clearLoadingState();
|
|
29857
29936
|
}
|
|
29858
29937
|
}, [clearLoadingState, s3ClipsService]);
|
|
@@ -29865,7 +29944,7 @@ var BottlenecksContent = ({
|
|
|
29865
29944
|
const handleVideoReady = React21.useCallback((player) => {
|
|
29866
29945
|
console.log("Video.js player ready - NOT clearing loading (wait for playing event)");
|
|
29867
29946
|
videoRetryCountRef.current = 0;
|
|
29868
|
-
if (error?.
|
|
29947
|
+
if (error?.isRetrying) {
|
|
29869
29948
|
setError(null);
|
|
29870
29949
|
}
|
|
29871
29950
|
}, [error]);
|
|
@@ -29910,20 +29989,53 @@ var BottlenecksContent = ({
|
|
|
29910
29989
|
}, [clearLoadingState]);
|
|
29911
29990
|
const handleVideoLoadingChange = React21.useCallback((isLoading2) => {
|
|
29912
29991
|
console.log(`[BottlenecksContent] Video loading state changed: ${isLoading2}`);
|
|
29992
|
+
if (error && error.type === "fatal") {
|
|
29993
|
+
console.log(`[BottlenecksContent] Ignoring loading state change - fatal error is showing`);
|
|
29994
|
+
return;
|
|
29995
|
+
}
|
|
29913
29996
|
setIsVideoBuffering(isLoading2);
|
|
29914
|
-
}, []);
|
|
29997
|
+
}, [error]);
|
|
29915
29998
|
const handleVideoEnded = React21.useCallback((player) => {
|
|
29916
29999
|
handleNext();
|
|
29917
30000
|
}, [handleNext]);
|
|
29918
30001
|
const videoRetryCountRef = React21.useRef(0);
|
|
29919
|
-
const handleVideoError = React21.useCallback((player,
|
|
29920
|
-
console.error("Video.js error:",
|
|
30002
|
+
const handleVideoError = React21.useCallback((player, errorInfo) => {
|
|
30003
|
+
console.error("[BottlenecksContent] Video.js error:", errorInfo);
|
|
29921
30004
|
setIsPlaying(false);
|
|
30005
|
+
setIsVideoBuffering(false);
|
|
30006
|
+
const errorCode = errorInfo?.code || 0;
|
|
30007
|
+
const canRetry = errorInfo?.canRetry ?? false;
|
|
30008
|
+
const errorMessage = errorInfo?.message || "Unknown error";
|
|
30009
|
+
console.log(`[Video Error] Code: ${errorCode}, Can Retry: ${canRetry}, Message: ${errorMessage}`);
|
|
30010
|
+
if (!canRetry) {
|
|
30011
|
+
console.log("[Video Error] Non-recoverable error - showing error overlay immediately");
|
|
30012
|
+
setError({
|
|
30013
|
+
type: "fatal",
|
|
30014
|
+
code: errorCode,
|
|
30015
|
+
message: errorMessage,
|
|
30016
|
+
canSkip: true,
|
|
30017
|
+
canRetry: false
|
|
30018
|
+
});
|
|
30019
|
+
clearLoadingState();
|
|
30020
|
+
videoRetryCountRef.current = 0;
|
|
30021
|
+
trackCoreEvent("clips_video_error_non_recoverable", {
|
|
30022
|
+
workspaceId,
|
|
30023
|
+
category: activeFilterRef.current,
|
|
30024
|
+
videoId: currentVideo?.id,
|
|
30025
|
+
errorCode,
|
|
30026
|
+
errorMessage
|
|
30027
|
+
});
|
|
30028
|
+
return;
|
|
30029
|
+
}
|
|
29922
30030
|
if (videoRetryCountRef.current < 3 && currentVideo) {
|
|
29923
30031
|
videoRetryCountRef.current++;
|
|
29924
30032
|
const retryDelay = 1e3 * videoRetryCountRef.current;
|
|
29925
|
-
console.log(`[Video Error] Retrying... Attempt ${videoRetryCountRef.current}/3 in ${retryDelay}ms`);
|
|
29926
|
-
setError(
|
|
30033
|
+
console.log(`[Video Error] Recoverable error - Retrying... Attempt ${videoRetryCountRef.current}/3 in ${retryDelay}ms`);
|
|
30034
|
+
setError({
|
|
30035
|
+
type: "retrying",
|
|
30036
|
+
message: `Retrying... (${videoRetryCountRef.current}/3)`,
|
|
30037
|
+
isRetrying: true
|
|
30038
|
+
});
|
|
29927
30039
|
setTimeout(() => {
|
|
29928
30040
|
if (videoRef.current && currentVideo && isMountedRef.current) {
|
|
29929
30041
|
setError(null);
|
|
@@ -29931,16 +30043,26 @@ var BottlenecksContent = ({
|
|
|
29931
30043
|
}
|
|
29932
30044
|
}, retryDelay);
|
|
29933
30045
|
} else {
|
|
29934
|
-
|
|
30046
|
+
console.log("[Video Error] Retries exhausted - showing final error overlay");
|
|
30047
|
+
setError({
|
|
30048
|
+
type: "fatal",
|
|
30049
|
+
code: errorCode,
|
|
30050
|
+
message: errorMessage,
|
|
30051
|
+
canSkip: true,
|
|
30052
|
+
canRetry: true
|
|
30053
|
+
// Allow manual retry for network errors
|
|
30054
|
+
});
|
|
29935
30055
|
videoRetryCountRef.current = 0;
|
|
29936
30056
|
trackCoreEvent("clips_video_error_final", {
|
|
29937
30057
|
workspaceId,
|
|
29938
30058
|
category: activeFilterRef.current,
|
|
29939
30059
|
videoId: currentVideo?.id,
|
|
29940
|
-
|
|
30060
|
+
errorCode,
|
|
30061
|
+
errorMessage,
|
|
30062
|
+
attempts: 3
|
|
29941
30063
|
});
|
|
29942
30064
|
}
|
|
29943
|
-
}, [currentVideo, workspaceId]);
|
|
30065
|
+
}, [currentVideo, workspaceId, clearLoadingState]);
|
|
29944
30066
|
React21.useEffect(() => {
|
|
29945
30067
|
isMountedRef.current = true;
|
|
29946
30068
|
return () => {
|
|
@@ -29958,9 +30080,13 @@ var BottlenecksContent = ({
|
|
|
29958
30080
|
}, [s3ClipsService]);
|
|
29959
30081
|
React21.useEffect(() => {
|
|
29960
30082
|
if (filteredVideos.length > 0 && currentIndex < filteredVideos.length) {
|
|
30083
|
+
if (error && error.type === "fatal") {
|
|
30084
|
+
console.log("[BottlenecksContent] Not clearing fatal error on video change - let user handle it");
|
|
30085
|
+
return;
|
|
30086
|
+
}
|
|
29961
30087
|
setError(null);
|
|
29962
30088
|
}
|
|
29963
|
-
}, [currentIndex, filteredVideos]);
|
|
30089
|
+
}, [currentIndex, filteredVideos, error]);
|
|
29964
30090
|
React21.useEffect(() => {
|
|
29965
30091
|
if (!isTransitioning && pendingVideo) {
|
|
29966
30092
|
const timer = setTimeout(() => {
|
|
@@ -30035,11 +30161,11 @@ var BottlenecksContent = ({
|
|
|
30035
30161
|
if ((isLoading || clipTypesLoading) && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
30036
30162
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-grow p-4 flex items-center justify-center h-[calc(100vh-12rem)]", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading clips..." }) });
|
|
30037
30163
|
}
|
|
30038
|
-
if (error || clipTypesError) {
|
|
30164
|
+
if (error && error.type === "fatal" && !hasInitialLoad || clipTypesError) {
|
|
30039
30165
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-grow p-4 flex flex-col items-center justify-center h-[calc(100vh-12rem)] text-center", children: [
|
|
30040
30166
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "w-12 h-12 text-red-400 mb-3" }),
|
|
30041
30167
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-red-700 mb-1", children: "Error Loading Clips" }),
|
|
30042
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 max-w-md", children: error || clipTypesError })
|
|
30168
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 max-w-md", children: error?.message || clipTypesError })
|
|
30043
30169
|
] });
|
|
30044
30170
|
}
|
|
30045
30171
|
const categoriesToShow = clipTypes.length > 0 ? clipTypes : [];
|
|
@@ -30086,7 +30212,7 @@ var BottlenecksContent = ({
|
|
|
30086
30212
|
),
|
|
30087
30213
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
30088
30214
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm px-2 py-1 bg-blue-50 text-blue-700 rounded-full font-medium tabular-nums", children: categoryMetadata.length > 0 ? `${currentMetadataIndex + 1} / ${categoryMetadata.length}` : "0 / 0" }),
|
|
30089
|
-
error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-
|
|
30215
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-orange-600 font-medium", children: error.message })
|
|
30090
30216
|
] }),
|
|
30091
30217
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30092
30218
|
"button",
|
|
@@ -30100,7 +30226,6 @@ var BottlenecksContent = ({
|
|
|
30100
30226
|
)
|
|
30101
30227
|
] })
|
|
30102
30228
|
] }) }),
|
|
30103
|
-
/* Show video if we have filtered videos and current video, or show loading */
|
|
30104
30229
|
filteredVideos.length > 0 && currentVideo ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
|
|
30105
30230
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30106
30231
|
CroppedVideoPlayer,
|
|
@@ -30132,30 +30257,44 @@ var BottlenecksContent = ({
|
|
|
30132
30257
|
}
|
|
30133
30258
|
}
|
|
30134
30259
|
),
|
|
30135
|
-
(isTransitioning || isVideoBuffering && isInitialLoading) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30136
|
-
!isTransitioning && isVideoBuffering && !isInitialLoading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30137
|
-
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black/
|
|
30260
|
+
(isTransitioning || isVideoBuffering && isInitialLoading) && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30261
|
+
!isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30262
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-40 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
30263
|
+
/* @__PURE__ */ jsxRuntime.jsx(OptifyeLogoLoader_default, { size: "md" }),
|
|
30264
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-white text-sm mt-4 font-medium", children: error.message })
|
|
30265
|
+
] }) }),
|
|
30266
|
+
error && error.type === "fatal" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/90 text-white p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center max-w-md", children: [
|
|
30138
30267
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-16 h-16 mx-auto mb-4 text-red-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 16.5c-.77.833.192 2.5 1.732 2.5z" }) }),
|
|
30139
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: "
|
|
30140
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-300 mb-
|
|
30141
|
-
/* @__PURE__ */ jsxRuntime.jsxs("
|
|
30142
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
30143
|
-
|
|
30144
|
-
|
|
30145
|
-
|
|
30146
|
-
|
|
30147
|
-
|
|
30148
|
-
|
|
30149
|
-
|
|
30150
|
-
|
|
30151
|
-
|
|
30152
|
-
|
|
30153
|
-
|
|
30154
|
-
|
|
30155
|
-
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30268
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mb-2", children: error.code === 3 ? "Stream Corrupted" : error.code === 4 ? "Format Not Supported" : error.code === 2 ? "Network Error" : error.code === 1 ? "Loading Interrupted" : "Playback Error" }),
|
|
30269
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-300 mb-6", children: error.message }),
|
|
30270
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
30271
|
+
error.canSkip && /* @__PURE__ */ jsxRuntime.jsx(
|
|
30272
|
+
"button",
|
|
30273
|
+
{
|
|
30274
|
+
onClick: () => {
|
|
30275
|
+
setError(null);
|
|
30276
|
+
videoRetryCountRef.current = 0;
|
|
30277
|
+
handleNext();
|
|
30278
|
+
},
|
|
30279
|
+
className: "px-5 py-2.5 bg-blue-600 hover:bg-blue-700 rounded-md text-sm font-medium transition-colors",
|
|
30280
|
+
children: "Skip to Next Clip"
|
|
30281
|
+
}
|
|
30282
|
+
),
|
|
30283
|
+
error.canRetry && /* @__PURE__ */ jsxRuntime.jsx(
|
|
30284
|
+
"button",
|
|
30285
|
+
{
|
|
30286
|
+
onClick: () => {
|
|
30287
|
+
setError(null);
|
|
30288
|
+
videoRetryCountRef.current = 0;
|
|
30289
|
+
if (videoRef.current) {
|
|
30290
|
+
videoRef.current.dispose();
|
|
30291
|
+
}
|
|
30292
|
+
},
|
|
30293
|
+
className: "px-5 py-2.5 bg-gray-600 hover:bg-gray-700 rounded-md text-sm font-medium transition-colors",
|
|
30294
|
+
children: "Retry"
|
|
30295
|
+
}
|
|
30296
|
+
)
|
|
30297
|
+
] })
|
|
30159
30298
|
] }) }),
|
|
30160
30299
|
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
|
|
30161
30300
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" || currentVideo.type === "idle_time" ? "bg-purple-400" : isPercentileCategory(activeFilterRef.current) ? activeFilterRef.current === "fast-cycles" ? "bg-green-600" : activeFilterRef.current === "slow-cycles" ? "bg-red-700" : "bg-orange-500" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-gray-500"} mr-2 animate-pulse` }),
|
|
@@ -42664,7 +42803,7 @@ var WorkspaceDetailView = ({
|
|
|
42664
42803
|
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
42665
42804
|
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
42666
42805
|
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
42667
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42806
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42668
42807
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
42669
42808
|
"Standard: ",
|
|
42670
42809
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -42784,7 +42923,7 @@ var WorkspaceDetailView = ({
|
|
|
42784
42923
|
/* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
|
|
42785
42924
|
/* @__PURE__ */ jsxRuntime.jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsxRuntime.jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
42786
42925
|
/* @__PURE__ */ jsxRuntime.jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
42787
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42926
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42788
42927
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
42789
42928
|
"Standard: ",
|
|
42790
42929
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
package/dist/index.mjs
CHANGED
|
@@ -22249,7 +22249,7 @@ var WorkspaceMetricCardsImpl = ({
|
|
|
22249
22249
|
/* @__PURE__ */ jsxs(Card2, { className: "flex flex-col bg-white shadow-sm h-full min-h-[150px] sm:min-h-0", children: [
|
|
22250
22250
|
/* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
22251
22251
|
/* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6 sm:py-3", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
22252
|
-
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
22252
|
+
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
22253
22253
|
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
22254
22254
|
"Standard: ",
|
|
22255
22255
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -25929,8 +25929,19 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25929
25929
|
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
25930
25930
|
const dailyData = [];
|
|
25931
25931
|
let maxOutput = 0;
|
|
25932
|
-
let
|
|
25933
|
-
let
|
|
25932
|
+
let lastSetTarget = 0;
|
|
25933
|
+
for (let day = daysInMonth; day >= 1; day--) {
|
|
25934
|
+
const dayData = data.find((d) => {
|
|
25935
|
+
const date = new Date(d.date);
|
|
25936
|
+
return date.getDate() === day;
|
|
25937
|
+
});
|
|
25938
|
+
const shiftData = dayData ? selectedShift === "day" ? dayData.dayShift : dayData.nightShift : null;
|
|
25939
|
+
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
25940
|
+
if (idealOutput > 0) {
|
|
25941
|
+
lastSetTarget = idealOutput;
|
|
25942
|
+
break;
|
|
25943
|
+
}
|
|
25944
|
+
}
|
|
25934
25945
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
25935
25946
|
const dayData = data.find((d) => {
|
|
25936
25947
|
const date = new Date(d.date);
|
|
@@ -25940,11 +25951,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25940
25951
|
const output = shiftData && hasRealData(shiftData) ? shiftData.output : 0;
|
|
25941
25952
|
const idealOutput = shiftData ? shiftData.idealOutput : 0;
|
|
25942
25953
|
if (output > maxOutput) maxOutput = output;
|
|
25943
|
-
|
|
25944
|
-
totalIdealOutput += idealOutput;
|
|
25945
|
-
validDaysCount++;
|
|
25946
|
-
}
|
|
25947
|
-
const color2 = output >= idealOutput ? "#00AB45" : "#E34329";
|
|
25954
|
+
const color2 = output >= lastSetTarget ? "#00AB45" : "#E34329";
|
|
25948
25955
|
dailyData.push({
|
|
25949
25956
|
hour: getOrdinal(day),
|
|
25950
25957
|
// Using ordinal format (1st, 2nd, 3rd, etc.)
|
|
@@ -25959,14 +25966,13 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25959
25966
|
// Not used but keeps structure consistent
|
|
25960
25967
|
});
|
|
25961
25968
|
}
|
|
25962
|
-
const
|
|
25963
|
-
const calculatedMax = Math.max(maxOutput, avgIdealOutput);
|
|
25969
|
+
const calculatedMax = Math.max(maxOutput, lastSetTarget);
|
|
25964
25970
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
25965
|
-
return { data: dailyData, maxOutput,
|
|
25971
|
+
return { data: dailyData, maxOutput, lastSetTarget, yAxisMax };
|
|
25966
25972
|
}, [data, month, year, selectedShift]);
|
|
25967
25973
|
const yAxisTicks = useMemo(() => {
|
|
25968
25974
|
const max = chartData.yAxisMax;
|
|
25969
|
-
const target = chartData.
|
|
25975
|
+
const target = chartData.lastSetTarget;
|
|
25970
25976
|
if (!max || max <= 0) return void 0;
|
|
25971
25977
|
const desiredIntervals = 4;
|
|
25972
25978
|
const roughStep = max / desiredIntervals;
|
|
@@ -25984,7 +25990,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
25984
25990
|
ticks.push(Math.round(target));
|
|
25985
25991
|
}
|
|
25986
25992
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
25987
|
-
}, [chartData.yAxisMax, chartData.
|
|
25993
|
+
}, [chartData.yAxisMax, chartData.lastSetTarget]);
|
|
25988
25994
|
const pieChartData = useMemo(() => {
|
|
25989
25995
|
const validShifts = data.map((d) => selectedShift === "day" ? d.dayShift : d.nightShift).filter(hasRealData);
|
|
25990
25996
|
if (validShifts.length === 0) return [];
|
|
@@ -26296,7 +26302,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26296
26302
|
tick: (props) => {
|
|
26297
26303
|
const { x, y, payload } = props;
|
|
26298
26304
|
const value = Math.round(payload.value);
|
|
26299
|
-
const targetValue = Math.round(chartData.
|
|
26305
|
+
const targetValue = Math.round(chartData.lastSetTarget);
|
|
26300
26306
|
const isTarget = Math.abs(value - targetValue) < 1 && targetValue > 0;
|
|
26301
26307
|
return /* @__PURE__ */ jsx(
|
|
26302
26308
|
"text",
|
|
@@ -26320,10 +26326,10 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26320
26326
|
content: CustomTooltip
|
|
26321
26327
|
}
|
|
26322
26328
|
),
|
|
26323
|
-
chartData.
|
|
26329
|
+
chartData.lastSetTarget > 0 && /* @__PURE__ */ jsx(
|
|
26324
26330
|
ReferenceLine,
|
|
26325
26331
|
{
|
|
26326
|
-
y: chartData.
|
|
26332
|
+
y: chartData.lastSetTarget,
|
|
26327
26333
|
stroke: "#E34329",
|
|
26328
26334
|
strokeDasharray: "5 5",
|
|
26329
26335
|
strokeWidth: 2
|
|
@@ -26381,11 +26387,11 @@ var WorkspaceMonthlyHistory = ({
|
|
|
26381
26387
|
]
|
|
26382
26388
|
}
|
|
26383
26389
|
) }) }),
|
|
26384
|
-
/* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.
|
|
26390
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-center items-center gap-6 mt-3", children: chartData.lastSetTarget > 0 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
26385
26391
|
/* @__PURE__ */ jsx("div", { className: "w-12 h-0.5 border-t-2 border-dashed", style: { borderColor: "#E34329" } }),
|
|
26386
26392
|
/* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-600", children: [
|
|
26387
26393
|
"Target: ",
|
|
26388
|
-
Math.round(chartData.
|
|
26394
|
+
Math.round(chartData.lastSetTarget),
|
|
26389
26395
|
" units/day"
|
|
26390
26396
|
] })
|
|
26391
26397
|
] }) })
|
|
@@ -27231,6 +27237,36 @@ var TimePickerDropdown = ({
|
|
|
27231
27237
|
] })
|
|
27232
27238
|
] });
|
|
27233
27239
|
};
|
|
27240
|
+
var ERROR_MAPPING = {
|
|
27241
|
+
1: {
|
|
27242
|
+
// MEDIA_ERR_ABORTED
|
|
27243
|
+
code: 1,
|
|
27244
|
+
type: "recoverable" /* RECOVERABLE */,
|
|
27245
|
+
message: "Video loading was interrupted",
|
|
27246
|
+
canRetry: true
|
|
27247
|
+
},
|
|
27248
|
+
2: {
|
|
27249
|
+
// MEDIA_ERR_NETWORK
|
|
27250
|
+
code: 2,
|
|
27251
|
+
type: "recoverable" /* RECOVERABLE */,
|
|
27252
|
+
message: "Network error - please check your internet connection",
|
|
27253
|
+
canRetry: true
|
|
27254
|
+
},
|
|
27255
|
+
3: {
|
|
27256
|
+
// MEDIA_ERR_DECODE
|
|
27257
|
+
code: 3,
|
|
27258
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27259
|
+
message: "Stream corrupted due to internet connection",
|
|
27260
|
+
canRetry: false
|
|
27261
|
+
},
|
|
27262
|
+
4: {
|
|
27263
|
+
// MEDIA_ERR_SRC_NOT_SUPPORTED
|
|
27264
|
+
code: 4,
|
|
27265
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27266
|
+
message: "Video format not supported by your browser. Please use Google Chrome.",
|
|
27267
|
+
canRetry: false
|
|
27268
|
+
}
|
|
27269
|
+
};
|
|
27234
27270
|
var videoPlayerStyles = `
|
|
27235
27271
|
.video-player-container {
|
|
27236
27272
|
width: 100%;
|
|
@@ -27461,8 +27497,21 @@ var VideoPlayer = React21__default.forwardRef(({
|
|
|
27461
27497
|
player.on("seeked", () => onSeeked?.(player));
|
|
27462
27498
|
player.on("error", () => {
|
|
27463
27499
|
const error = player.error();
|
|
27464
|
-
|
|
27465
|
-
|
|
27500
|
+
const errorCode = error?.code ?? 0;
|
|
27501
|
+
const errorInfo = ERROR_MAPPING[errorCode] || {
|
|
27502
|
+
code: errorCode || 0,
|
|
27503
|
+
type: "non_recoverable" /* NON_RECOVERABLE */,
|
|
27504
|
+
message: "Unknown playback error occurred",
|
|
27505
|
+
canRetry: false
|
|
27506
|
+
};
|
|
27507
|
+
console.error("[VideoPlayer] Video.js error:", {
|
|
27508
|
+
code: errorCode,
|
|
27509
|
+
type: errorInfo.type,
|
|
27510
|
+
message: errorInfo.message,
|
|
27511
|
+
canRetry: errorInfo.canRetry,
|
|
27512
|
+
originalError: error
|
|
27513
|
+
});
|
|
27514
|
+
onError?.(player, errorInfo);
|
|
27466
27515
|
});
|
|
27467
27516
|
if (src) {
|
|
27468
27517
|
const isHLS = src.endsWith(".m3u8") || src.startsWith("#EXTM3U");
|
|
@@ -28640,7 +28689,7 @@ var FileManagerFilters = ({
|
|
|
28640
28689
|
];
|
|
28641
28690
|
percentileCategories.forEach((category) => {
|
|
28642
28691
|
if (category.count > 0 && shouldShowCategory(category.id)) {
|
|
28643
|
-
tree.
|
|
28692
|
+
tree.push(category);
|
|
28644
28693
|
}
|
|
28645
28694
|
});
|
|
28646
28695
|
return tree;
|
|
@@ -29357,7 +29406,12 @@ var BottlenecksContent = ({
|
|
|
29357
29406
|
} catch (err) {
|
|
29358
29407
|
console.error("[BottlenecksContent] Error fetching clip counts:", err);
|
|
29359
29408
|
if (isMountedRef.current) {
|
|
29360
|
-
setError(
|
|
29409
|
+
setError({
|
|
29410
|
+
type: "fatal",
|
|
29411
|
+
message: "Failed to load clip counts. Please try again.",
|
|
29412
|
+
canSkip: false,
|
|
29413
|
+
canRetry: true
|
|
29414
|
+
});
|
|
29361
29415
|
setIsLoading(false);
|
|
29362
29416
|
}
|
|
29363
29417
|
} finally {
|
|
@@ -29441,7 +29495,12 @@ var BottlenecksContent = ({
|
|
|
29441
29495
|
} catch (err) {
|
|
29442
29496
|
console.error("Error loading first video for category:", err);
|
|
29443
29497
|
if (isMountedRef.current) {
|
|
29444
|
-
setError(
|
|
29498
|
+
setError({
|
|
29499
|
+
type: "fatal",
|
|
29500
|
+
message: "Failed to load clips. Please try again.",
|
|
29501
|
+
canSkip: false,
|
|
29502
|
+
canRetry: true
|
|
29503
|
+
});
|
|
29445
29504
|
setIsCategoryLoading(false);
|
|
29446
29505
|
}
|
|
29447
29506
|
} finally {
|
|
@@ -29723,7 +29782,12 @@ var BottlenecksContent = ({
|
|
|
29723
29782
|
} catch (error2) {
|
|
29724
29783
|
console.error(`[BottlenecksContent] Error loading clip by ID (${clipId}):`, error2);
|
|
29725
29784
|
if (isMountedRef.current) {
|
|
29726
|
-
setError(
|
|
29785
|
+
setError({
|
|
29786
|
+
type: "fatal",
|
|
29787
|
+
message: "Failed to load selected clip. Please try again.",
|
|
29788
|
+
canSkip: true,
|
|
29789
|
+
canRetry: true
|
|
29790
|
+
});
|
|
29727
29791
|
clearLoadingState();
|
|
29728
29792
|
}
|
|
29729
29793
|
}
|
|
@@ -29746,7 +29810,12 @@ var BottlenecksContent = ({
|
|
|
29746
29810
|
}
|
|
29747
29811
|
} catch (error2) {
|
|
29748
29812
|
console.error(`[BottlenecksContent] Error in legacy loadAndPlayClip:`, error2);
|
|
29749
|
-
setError(
|
|
29813
|
+
setError({
|
|
29814
|
+
type: "fatal",
|
|
29815
|
+
message: "Failed to load selected clip. Please try again.",
|
|
29816
|
+
canSkip: true,
|
|
29817
|
+
canRetry: true
|
|
29818
|
+
});
|
|
29750
29819
|
setIsNavigating(false);
|
|
29751
29820
|
}
|
|
29752
29821
|
}, [workspaceId, s3ClipsService, date, effectiveShift, loadAndPlayClipById]);
|
|
@@ -29786,7 +29855,12 @@ var BottlenecksContent = ({
|
|
|
29786
29855
|
}
|
|
29787
29856
|
} catch (error2) {
|
|
29788
29857
|
console.error(`[handleNext] Error navigating:`, error2);
|
|
29789
|
-
setError(
|
|
29858
|
+
setError({
|
|
29859
|
+
type: "fatal",
|
|
29860
|
+
message: "Failed to navigate to next clip",
|
|
29861
|
+
canSkip: true,
|
|
29862
|
+
canRetry: true
|
|
29863
|
+
});
|
|
29790
29864
|
clearLoadingState();
|
|
29791
29865
|
}
|
|
29792
29866
|
}, [clearLoadingState, s3ClipsService]);
|
|
@@ -29822,7 +29896,12 @@ var BottlenecksContent = ({
|
|
|
29822
29896
|
}
|
|
29823
29897
|
} catch (error2) {
|
|
29824
29898
|
console.error(`[handlePrevious] Error navigating:`, error2);
|
|
29825
|
-
setError(
|
|
29899
|
+
setError({
|
|
29900
|
+
type: "fatal",
|
|
29901
|
+
message: "Failed to navigate to previous clip",
|
|
29902
|
+
canSkip: true,
|
|
29903
|
+
canRetry: true
|
|
29904
|
+
});
|
|
29826
29905
|
clearLoadingState();
|
|
29827
29906
|
}
|
|
29828
29907
|
}, [clearLoadingState, s3ClipsService]);
|
|
@@ -29835,7 +29914,7 @@ var BottlenecksContent = ({
|
|
|
29835
29914
|
const handleVideoReady = useCallback((player) => {
|
|
29836
29915
|
console.log("Video.js player ready - NOT clearing loading (wait for playing event)");
|
|
29837
29916
|
videoRetryCountRef.current = 0;
|
|
29838
|
-
if (error?.
|
|
29917
|
+
if (error?.isRetrying) {
|
|
29839
29918
|
setError(null);
|
|
29840
29919
|
}
|
|
29841
29920
|
}, [error]);
|
|
@@ -29880,20 +29959,53 @@ var BottlenecksContent = ({
|
|
|
29880
29959
|
}, [clearLoadingState]);
|
|
29881
29960
|
const handleVideoLoadingChange = useCallback((isLoading2) => {
|
|
29882
29961
|
console.log(`[BottlenecksContent] Video loading state changed: ${isLoading2}`);
|
|
29962
|
+
if (error && error.type === "fatal") {
|
|
29963
|
+
console.log(`[BottlenecksContent] Ignoring loading state change - fatal error is showing`);
|
|
29964
|
+
return;
|
|
29965
|
+
}
|
|
29883
29966
|
setIsVideoBuffering(isLoading2);
|
|
29884
|
-
}, []);
|
|
29967
|
+
}, [error]);
|
|
29885
29968
|
const handleVideoEnded = useCallback((player) => {
|
|
29886
29969
|
handleNext();
|
|
29887
29970
|
}, [handleNext]);
|
|
29888
29971
|
const videoRetryCountRef = useRef(0);
|
|
29889
|
-
const handleVideoError = useCallback((player,
|
|
29890
|
-
console.error("Video.js error:",
|
|
29972
|
+
const handleVideoError = useCallback((player, errorInfo) => {
|
|
29973
|
+
console.error("[BottlenecksContent] Video.js error:", errorInfo);
|
|
29891
29974
|
setIsPlaying(false);
|
|
29975
|
+
setIsVideoBuffering(false);
|
|
29976
|
+
const errorCode = errorInfo?.code || 0;
|
|
29977
|
+
const canRetry = errorInfo?.canRetry ?? false;
|
|
29978
|
+
const errorMessage = errorInfo?.message || "Unknown error";
|
|
29979
|
+
console.log(`[Video Error] Code: ${errorCode}, Can Retry: ${canRetry}, Message: ${errorMessage}`);
|
|
29980
|
+
if (!canRetry) {
|
|
29981
|
+
console.log("[Video Error] Non-recoverable error - showing error overlay immediately");
|
|
29982
|
+
setError({
|
|
29983
|
+
type: "fatal",
|
|
29984
|
+
code: errorCode,
|
|
29985
|
+
message: errorMessage,
|
|
29986
|
+
canSkip: true,
|
|
29987
|
+
canRetry: false
|
|
29988
|
+
});
|
|
29989
|
+
clearLoadingState();
|
|
29990
|
+
videoRetryCountRef.current = 0;
|
|
29991
|
+
trackCoreEvent("clips_video_error_non_recoverable", {
|
|
29992
|
+
workspaceId,
|
|
29993
|
+
category: activeFilterRef.current,
|
|
29994
|
+
videoId: currentVideo?.id,
|
|
29995
|
+
errorCode,
|
|
29996
|
+
errorMessage
|
|
29997
|
+
});
|
|
29998
|
+
return;
|
|
29999
|
+
}
|
|
29892
30000
|
if (videoRetryCountRef.current < 3 && currentVideo) {
|
|
29893
30001
|
videoRetryCountRef.current++;
|
|
29894
30002
|
const retryDelay = 1e3 * videoRetryCountRef.current;
|
|
29895
|
-
console.log(`[Video Error] Retrying... Attempt ${videoRetryCountRef.current}/3 in ${retryDelay}ms`);
|
|
29896
|
-
setError(
|
|
30003
|
+
console.log(`[Video Error] Recoverable error - Retrying... Attempt ${videoRetryCountRef.current}/3 in ${retryDelay}ms`);
|
|
30004
|
+
setError({
|
|
30005
|
+
type: "retrying",
|
|
30006
|
+
message: `Retrying... (${videoRetryCountRef.current}/3)`,
|
|
30007
|
+
isRetrying: true
|
|
30008
|
+
});
|
|
29897
30009
|
setTimeout(() => {
|
|
29898
30010
|
if (videoRef.current && currentVideo && isMountedRef.current) {
|
|
29899
30011
|
setError(null);
|
|
@@ -29901,16 +30013,26 @@ var BottlenecksContent = ({
|
|
|
29901
30013
|
}
|
|
29902
30014
|
}, retryDelay);
|
|
29903
30015
|
} else {
|
|
29904
|
-
|
|
30016
|
+
console.log("[Video Error] Retries exhausted - showing final error overlay");
|
|
30017
|
+
setError({
|
|
30018
|
+
type: "fatal",
|
|
30019
|
+
code: errorCode,
|
|
30020
|
+
message: errorMessage,
|
|
30021
|
+
canSkip: true,
|
|
30022
|
+
canRetry: true
|
|
30023
|
+
// Allow manual retry for network errors
|
|
30024
|
+
});
|
|
29905
30025
|
videoRetryCountRef.current = 0;
|
|
29906
30026
|
trackCoreEvent("clips_video_error_final", {
|
|
29907
30027
|
workspaceId,
|
|
29908
30028
|
category: activeFilterRef.current,
|
|
29909
30029
|
videoId: currentVideo?.id,
|
|
29910
|
-
|
|
30030
|
+
errorCode,
|
|
30031
|
+
errorMessage,
|
|
30032
|
+
attempts: 3
|
|
29911
30033
|
});
|
|
29912
30034
|
}
|
|
29913
|
-
}, [currentVideo, workspaceId]);
|
|
30035
|
+
}, [currentVideo, workspaceId, clearLoadingState]);
|
|
29914
30036
|
useEffect(() => {
|
|
29915
30037
|
isMountedRef.current = true;
|
|
29916
30038
|
return () => {
|
|
@@ -29928,9 +30050,13 @@ var BottlenecksContent = ({
|
|
|
29928
30050
|
}, [s3ClipsService]);
|
|
29929
30051
|
useEffect(() => {
|
|
29930
30052
|
if (filteredVideos.length > 0 && currentIndex < filteredVideos.length) {
|
|
30053
|
+
if (error && error.type === "fatal") {
|
|
30054
|
+
console.log("[BottlenecksContent] Not clearing fatal error on video change - let user handle it");
|
|
30055
|
+
return;
|
|
30056
|
+
}
|
|
29931
30057
|
setError(null);
|
|
29932
30058
|
}
|
|
29933
|
-
}, [currentIndex, filteredVideos]);
|
|
30059
|
+
}, [currentIndex, filteredVideos, error]);
|
|
29934
30060
|
useEffect(() => {
|
|
29935
30061
|
if (!isTransitioning && pendingVideo) {
|
|
29936
30062
|
const timer = setTimeout(() => {
|
|
@@ -30005,11 +30131,11 @@ var BottlenecksContent = ({
|
|
|
30005
30131
|
if ((isLoading || clipTypesLoading) && allVideos.length === 0 && Object.keys(mergedCounts).length === 0) {
|
|
30006
30132
|
return /* @__PURE__ */ jsx("div", { className: "flex-grow p-4 flex items-center justify-center h-[calc(100vh-12rem)]", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "lg", message: "Loading clips..." }) });
|
|
30007
30133
|
}
|
|
30008
|
-
if (error || clipTypesError) {
|
|
30134
|
+
if (error && error.type === "fatal" && !hasInitialLoad || clipTypesError) {
|
|
30009
30135
|
return /* @__PURE__ */ jsxs("div", { className: "flex-grow p-4 flex flex-col items-center justify-center h-[calc(100vh-12rem)] text-center", children: [
|
|
30010
30136
|
/* @__PURE__ */ jsx(XCircle, { className: "w-12 h-12 text-red-400 mb-3" }),
|
|
30011
30137
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-red-700 mb-1", children: "Error Loading Clips" }),
|
|
30012
|
-
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: error || clipTypesError })
|
|
30138
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-600 max-w-md", children: error?.message || clipTypesError })
|
|
30013
30139
|
] });
|
|
30014
30140
|
}
|
|
30015
30141
|
const categoriesToShow = clipTypes.length > 0 ? clipTypes : [];
|
|
@@ -30056,7 +30182,7 @@ var BottlenecksContent = ({
|
|
|
30056
30182
|
),
|
|
30057
30183
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1", children: [
|
|
30058
30184
|
/* @__PURE__ */ jsx("span", { className: "text-sm px-2 py-1 bg-blue-50 text-blue-700 rounded-full font-medium tabular-nums", children: categoryMetadata.length > 0 ? `${currentMetadataIndex + 1} / ${categoryMetadata.length}` : "0 / 0" }),
|
|
30059
|
-
error && /* @__PURE__ */ jsx("span", { className: "text-xs text-
|
|
30185
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsx("span", { className: "text-xs text-orange-600 font-medium", children: error.message })
|
|
30060
30186
|
] }),
|
|
30061
30187
|
/* @__PURE__ */ jsx(
|
|
30062
30188
|
"button",
|
|
@@ -30070,7 +30196,6 @@ var BottlenecksContent = ({
|
|
|
30070
30196
|
)
|
|
30071
30197
|
] })
|
|
30072
30198
|
] }) }),
|
|
30073
|
-
/* Show video if we have filtered videos and current video, or show loading */
|
|
30074
30199
|
filteredVideos.length > 0 && currentVideo ? /* @__PURE__ */ jsx("div", { className: "p-4 h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx("div", { className: "relative h-full group", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full overflow-hidden rounded-md shadow-inner bg-gray-900", children: [
|
|
30075
30200
|
/* @__PURE__ */ jsx(
|
|
30076
30201
|
CroppedVideoPlayer,
|
|
@@ -30102,30 +30227,44 @@ var BottlenecksContent = ({
|
|
|
30102
30227
|
}
|
|
30103
30228
|
}
|
|
30104
30229
|
),
|
|
30105
|
-
(isTransitioning || isVideoBuffering && isInitialLoading) && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30106
|
-
!isTransitioning && isVideoBuffering && !isInitialLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30107
|
-
error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-black/
|
|
30230
|
+
(isTransitioning || isVideoBuffering && isInitialLoading) && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30231
|
+
!isTransitioning && isVideoBuffering && !isInitialLoading && !error && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-30 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading video..." }) }),
|
|
30232
|
+
error && error.type === "retrying" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-40 flex items-center justify-center bg-black/60", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
30233
|
+
/* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md" }),
|
|
30234
|
+
/* @__PURE__ */ jsx("p", { className: "text-white text-sm mt-4 font-medium", children: error.message })
|
|
30235
|
+
] }) }),
|
|
30236
|
+
error && error.type === "fatal" && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-50 flex items-center justify-center bg-black/90 text-white p-4", children: /* @__PURE__ */ jsxs("div", { className: "text-center max-w-md", children: [
|
|
30108
30237
|
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 mx-auto mb-4 text-red-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.732-.833-2.5 0L4.268 16.5c-.77.833.192 2.5 1.732 2.5z" }) }),
|
|
30109
|
-
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "
|
|
30110
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-
|
|
30111
|
-
/* @__PURE__ */ jsxs("
|
|
30112
|
-
/* @__PURE__ */ jsx(
|
|
30113
|
-
|
|
30114
|
-
|
|
30115
|
-
|
|
30116
|
-
|
|
30117
|
-
|
|
30118
|
-
|
|
30119
|
-
|
|
30120
|
-
|
|
30121
|
-
|
|
30122
|
-
|
|
30123
|
-
|
|
30124
|
-
|
|
30125
|
-
|
|
30126
|
-
|
|
30127
|
-
|
|
30128
|
-
|
|
30238
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: error.code === 3 ? "Stream Corrupted" : error.code === 4 ? "Format Not Supported" : error.code === 2 ? "Network Error" : error.code === 1 ? "Loading Interrupted" : "Playback Error" }),
|
|
30239
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-300 mb-6", children: error.message }),
|
|
30240
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
30241
|
+
error.canSkip && /* @__PURE__ */ jsx(
|
|
30242
|
+
"button",
|
|
30243
|
+
{
|
|
30244
|
+
onClick: () => {
|
|
30245
|
+
setError(null);
|
|
30246
|
+
videoRetryCountRef.current = 0;
|
|
30247
|
+
handleNext();
|
|
30248
|
+
},
|
|
30249
|
+
className: "px-5 py-2.5 bg-blue-600 hover:bg-blue-700 rounded-md text-sm font-medium transition-colors",
|
|
30250
|
+
children: "Skip to Next Clip"
|
|
30251
|
+
}
|
|
30252
|
+
),
|
|
30253
|
+
error.canRetry && /* @__PURE__ */ jsx(
|
|
30254
|
+
"button",
|
|
30255
|
+
{
|
|
30256
|
+
onClick: () => {
|
|
30257
|
+
setError(null);
|
|
30258
|
+
videoRetryCountRef.current = 0;
|
|
30259
|
+
if (videoRef.current) {
|
|
30260
|
+
videoRef.current.dispose();
|
|
30261
|
+
}
|
|
30262
|
+
},
|
|
30263
|
+
className: "px-5 py-2.5 bg-gray-600 hover:bg-gray-700 rounded-md text-sm font-medium transition-colors",
|
|
30264
|
+
children: "Retry"
|
|
30265
|
+
}
|
|
30266
|
+
)
|
|
30267
|
+
] })
|
|
30129
30268
|
] }) }),
|
|
30130
30269
|
(currentVideo.type === "cycle_completion" || currentVideo.type === "bottleneck" && currentVideo.description.toLowerCase().includes("cycle time")) && currentVideo.cycle_time_seconds || currentVideo.type === "idle_time" || currentVideo.type === "low_value" ? /* @__PURE__ */ jsx("div", { className: "absolute top-3 left-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
30131
30270
|
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${currentVideo.type === "low_value" || currentVideo.type === "idle_time" ? "bg-purple-400" : isPercentileCategory(activeFilterRef.current) ? activeFilterRef.current === "fast-cycles" ? "bg-green-600" : activeFilterRef.current === "slow-cycles" ? "bg-red-700" : "bg-orange-500" : currentVideo.type === "cycle_completion" ? "bg-blue-600" : "bg-gray-500"} mr-2 animate-pulse` }),
|
|
@@ -42634,7 +42773,7 @@ var WorkspaceDetailView = ({
|
|
|
42634
42773
|
/* @__PURE__ */ jsxs(Card2, { children: [
|
|
42635
42774
|
/* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
42636
42775
|
/* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center py-6", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
42637
|
-
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42776
|
+
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42638
42777
|
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
42639
42778
|
"Standard: ",
|
|
42640
42779
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|
|
@@ -42754,7 +42893,7 @@ var WorkspaceDetailView = ({
|
|
|
42754
42893
|
/* @__PURE__ */ jsxs(Card2, { children: [
|
|
42755
42894
|
/* @__PURE__ */ jsx(CardHeader2, { className: "pb-2 flex-none", children: /* @__PURE__ */ jsx(CardTitle2, { className: "text-lg text-center", children: "Cycle Time (s)" }) }),
|
|
42756
42895
|
/* @__PURE__ */ jsx(CardContent2, { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
42757
|
-
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold text-green-500`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42896
|
+
/* @__PURE__ */ jsx("p", { className: `text-5xl font-bold ${workspace.avg_cycle_time > (workspace.ideal_cycle_time || 0) ? "text-red-500" : "text-green-500"}`, children: workspace.avg_cycle_time.toFixed(1) }),
|
|
42758
42897
|
/* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-500 mt-2", children: [
|
|
42759
42898
|
"Standard: ",
|
|
42760
42899
|
workspace.ideal_cycle_time?.toFixed(1) || 0,
|