@optifye/dashboard-core 6.12.44 → 6.12.46
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 +64 -6
- package/dist/index.d.mts +150 -2
- package/dist/index.d.ts +150 -2
- package/dist/index.js +3660 -2804
- package/dist/index.mjs +1338 -482
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { format, addDays, subMonths, endOfMonth, startOfMonth, endOfDay, eachDayOfInterval, getDay, isSameDay, isWithinInterval, startOfDay, parseISO, subDays, differenceInMinutes, addMinutes, addMonths, isValid, formatDistanceToNow, isToday, isFuture, isBefore } from 'date-fns';
|
|
2
2
|
import { formatInTimeZone, fromZonedTime, toZonedTime } from 'date-fns-tz';
|
|
3
|
-
import * as
|
|
4
|
-
import
|
|
3
|
+
import * as React148 from 'react';
|
|
4
|
+
import React148__default, { createContext, useRef, useId, useCallback, useState, useMemo, useEffect, forwardRef, useImperativeHandle, useLayoutEffect, memo as memo$1, useContext, useSyncExternalStore, Children, isValidElement, useInsertionEffect, startTransition, Fragment as Fragment$1, createElement, Component } from 'react';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
import { useRouter } from 'next/router';
|
|
7
7
|
import { toast } from 'sonner';
|
|
@@ -2091,14 +2091,14 @@ var useIdleTimeVlmConfig = () => {
|
|
|
2091
2091
|
}
|
|
2092
2092
|
return context;
|
|
2093
2093
|
};
|
|
2094
|
-
var DashboardConfigContext =
|
|
2094
|
+
var DashboardConfigContext = React148.createContext(void 0);
|
|
2095
2095
|
var DashboardProvider = ({ config: userProvidedConfig, children }) => {
|
|
2096
|
-
const fullConfig =
|
|
2096
|
+
const fullConfig = React148.useMemo(() => mergeWithDefaultConfig(userProvidedConfig), [userProvidedConfig]);
|
|
2097
2097
|
_setDashboardConfigInstance(fullConfig);
|
|
2098
|
-
|
|
2098
|
+
React148.useEffect(() => {
|
|
2099
2099
|
_setDashboardConfigInstance(fullConfig);
|
|
2100
2100
|
}, [fullConfig]);
|
|
2101
|
-
|
|
2101
|
+
React148.useEffect(() => {
|
|
2102
2102
|
if (!fullConfig.theme) return;
|
|
2103
2103
|
const styleId = "dashboard-core-theme-vars";
|
|
2104
2104
|
let styleEl = document.getElementById(styleId);
|
|
@@ -2124,7 +2124,7 @@ var DashboardProvider = ({ config: userProvidedConfig, children }) => {
|
|
|
2124
2124
|
return /* @__PURE__ */ jsx(DashboardConfigContext.Provider, { value: fullConfig, children: /* @__PURE__ */ jsx(IdleTimeVlmConfigProvider, { children }) });
|
|
2125
2125
|
};
|
|
2126
2126
|
var useDashboardConfig = () => {
|
|
2127
|
-
const ctx =
|
|
2127
|
+
const ctx = React148.useContext(DashboardConfigContext);
|
|
2128
2128
|
if (!ctx) throw new Error("useDashboardConfig must be used within a DashboardProvider");
|
|
2129
2129
|
return ctx;
|
|
2130
2130
|
};
|
|
@@ -9290,6 +9290,7 @@ var CLIP_COUNTS_CACHE_TTL = 30 * 1e3;
|
|
|
9290
9290
|
var CLIP_BY_ID_CACHE_TTL = 2 * 60 * 1e3;
|
|
9291
9291
|
var CLIP_BY_ID_CACHE_MAX = 200;
|
|
9292
9292
|
var CLIPS_INIT_CACHE_TTL = 30 * 1e3;
|
|
9293
|
+
var RECENT_FLOW_RED_STREAK_CLIP_TYPE = "recent_flow_red_streak";
|
|
9293
9294
|
var parseFiniteNumber = (value) => {
|
|
9294
9295
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
9295
9296
|
return value;
|
|
@@ -9885,6 +9886,7 @@ var S3ClipsSupabaseService = class {
|
|
|
9885
9886
|
case "long_cycle_time":
|
|
9886
9887
|
case "worst_cycle_time":
|
|
9887
9888
|
case "sop_deviations":
|
|
9889
|
+
case RECENT_FLOW_RED_STREAK_CLIP_TYPE:
|
|
9888
9890
|
return "high";
|
|
9889
9891
|
case "idle_time":
|
|
9890
9892
|
return "medium";
|
|
@@ -9905,7 +9907,8 @@ var S3ClipsSupabaseService = class {
|
|
|
9905
9907
|
"best_cycle_time": "Best Cycle Time Performance",
|
|
9906
9908
|
"worst_cycle_time": "Worst Cycle Time Performance",
|
|
9907
9909
|
"sop_deviations": "SOP Deviations",
|
|
9908
|
-
"cycle_completion": "Cycle Completion"
|
|
9910
|
+
"cycle_completion": "Cycle Completion",
|
|
9911
|
+
[RECENT_FLOW_RED_STREAK_CLIP_TYPE]: "Moments with low efficiency"
|
|
9909
9912
|
};
|
|
9910
9913
|
return clipType ? descriptions[clipType] || "Analysis Clip" : "Analysis Clip";
|
|
9911
9914
|
}
|
|
@@ -12827,7 +12830,7 @@ var useMobileMenu = () => {
|
|
|
12827
12830
|
};
|
|
12828
12831
|
var useHideMobileHeader = (shouldHide = true) => {
|
|
12829
12832
|
const context = useMobileMenu();
|
|
12830
|
-
|
|
12833
|
+
React148__default.useEffect(() => {
|
|
12831
12834
|
if (context && shouldHide) {
|
|
12832
12835
|
context.setHideMobileHeader(true);
|
|
12833
12836
|
return () => {
|
|
@@ -25910,7 +25913,7 @@ var MotionConfigContext = createContext({
|
|
|
25910
25913
|
});
|
|
25911
25914
|
|
|
25912
25915
|
// ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PopChild.mjs
|
|
25913
|
-
var PopChildMeasure = class extends
|
|
25916
|
+
var PopChildMeasure = class extends React148.Component {
|
|
25914
25917
|
getSnapshotBeforeUpdate(prevProps) {
|
|
25915
25918
|
const element = this.props.childRef.current;
|
|
25916
25919
|
if (element && prevProps.isPresent && !this.props.isPresent) {
|
|
@@ -25965,7 +25968,7 @@ function PopChild({ children, isPresent }) {
|
|
|
25965
25968
|
document.head.removeChild(style);
|
|
25966
25969
|
};
|
|
25967
25970
|
}, [isPresent]);
|
|
25968
|
-
return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children:
|
|
25971
|
+
return jsx(PopChildMeasure, { isPresent, childRef: ref, sizeRef: size, children: React148.cloneElement(children, { ref }) });
|
|
25969
25972
|
}
|
|
25970
25973
|
|
|
25971
25974
|
// ../../node_modules/framer-motion/dist/es/components/AnimatePresence/PresenceChild.mjs
|
|
@@ -26002,7 +26005,7 @@ var PresenceChild = ({ children, initial, isPresent, onExitComplete, custom, pre
|
|
|
26002
26005
|
useMemo(() => {
|
|
26003
26006
|
presenceChildren.forEach((_, key) => presenceChildren.set(key, false));
|
|
26004
26007
|
}, [isPresent]);
|
|
26005
|
-
|
|
26008
|
+
React148.useEffect(() => {
|
|
26006
26009
|
!isPresent && !presenceChildren.size && onExitComplete && onExitComplete();
|
|
26007
26010
|
}, [isPresent]);
|
|
26008
26011
|
if (mode === "popLayout") {
|
|
@@ -33787,7 +33790,7 @@ var withAuth = (WrappedComponent2, options) => {
|
|
|
33787
33790
|
requireAuth: true,
|
|
33788
33791
|
...options
|
|
33789
33792
|
};
|
|
33790
|
-
const WithAuthComponent =
|
|
33793
|
+
const WithAuthComponent = React148.memo(function WithAuthComponent2(props) {
|
|
33791
33794
|
const {
|
|
33792
33795
|
session,
|
|
33793
33796
|
user,
|
|
@@ -33798,9 +33801,9 @@ var withAuth = (WrappedComponent2, options) => {
|
|
|
33798
33801
|
retrySessionHydration
|
|
33799
33802
|
} = useAuth();
|
|
33800
33803
|
const router = useRouter();
|
|
33801
|
-
const [localLoading, setLocalLoading] =
|
|
33802
|
-
const [loadingTimeoutReached, setLoadingTimeoutReached] =
|
|
33803
|
-
|
|
33804
|
+
const [localLoading, setLocalLoading] = React148.useState(loading);
|
|
33805
|
+
const [loadingTimeoutReached, setLoadingTimeoutReached] = React148.useState(false);
|
|
33806
|
+
React148.useEffect(() => {
|
|
33804
33807
|
if (process.env.NODE_ENV === "development" && process.env.DEBUG_AUTH === "true") {
|
|
33805
33808
|
console.log("withAuth state:", {
|
|
33806
33809
|
loading,
|
|
@@ -33812,7 +33815,7 @@ var withAuth = (WrappedComponent2, options) => {
|
|
|
33812
33815
|
});
|
|
33813
33816
|
}
|
|
33814
33817
|
}, [authStatus, error, loading, session, user]);
|
|
33815
|
-
const handleLoadingTimeout =
|
|
33818
|
+
const handleLoadingTimeout = React148.useCallback(() => {
|
|
33816
33819
|
console.warn("[withAuth] Loading timeout reached");
|
|
33817
33820
|
setLoadingTimeoutReached(true);
|
|
33818
33821
|
if (hasStoredSupabaseSession()) {
|
|
@@ -33824,13 +33827,13 @@ var withAuth = (WrappedComponent2, options) => {
|
|
|
33824
33827
|
router.replace(defaultOptions.redirectTo);
|
|
33825
33828
|
}
|
|
33826
33829
|
}, [retrySessionHydration, router]);
|
|
33827
|
-
|
|
33830
|
+
React148.useEffect(() => {
|
|
33828
33831
|
if (!loading && authStatus !== "recovering" && defaultOptions.requireAuth && !session && !error) {
|
|
33829
33832
|
console.log("[withAuth] No session found, redirecting to login");
|
|
33830
33833
|
router.replace(defaultOptions.redirectTo);
|
|
33831
33834
|
}
|
|
33832
33835
|
}, [authStatus, defaultOptions.requireAuth, error, loading, router, session]);
|
|
33833
|
-
|
|
33836
|
+
React148.useEffect(() => {
|
|
33834
33837
|
setLocalLoading(loading);
|
|
33835
33838
|
}, [loading]);
|
|
33836
33839
|
if (loading || localLoading) {
|
|
@@ -34829,11 +34832,11 @@ var BarChartComponent = ({
|
|
|
34829
34832
|
aspect = 2,
|
|
34830
34833
|
...restOfChartProps
|
|
34831
34834
|
}) => {
|
|
34832
|
-
const containerRef =
|
|
34833
|
-
const [containerReady, setContainerReady] =
|
|
34835
|
+
const containerRef = React148__default.useRef(null);
|
|
34836
|
+
const [containerReady, setContainerReady] = React148__default.useState(false);
|
|
34834
34837
|
const themeConfig = useThemeConfig();
|
|
34835
34838
|
const { formatNumber } = useFormatNumber();
|
|
34836
|
-
|
|
34839
|
+
React148__default.useEffect(() => {
|
|
34837
34840
|
const checkContainerDimensions = () => {
|
|
34838
34841
|
if (containerRef.current) {
|
|
34839
34842
|
const rect = containerRef.current.getBoundingClientRect();
|
|
@@ -34947,7 +34950,7 @@ var BarChartComponent = ({
|
|
|
34947
34950
|
}
|
|
34948
34951
|
return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: chartContent });
|
|
34949
34952
|
};
|
|
34950
|
-
var BarChart =
|
|
34953
|
+
var BarChart = React148__default.memo(BarChartComponent, (prevProps, nextProps) => {
|
|
34951
34954
|
if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || JSON.stringify(prevProps.referenceLines || []) !== JSON.stringify(nextProps.referenceLines || []) || prevProps.layout !== nextProps.layout || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect) {
|
|
34952
34955
|
return false;
|
|
34953
34956
|
}
|
|
@@ -34998,10 +35001,10 @@ var LineChartComponent = ({
|
|
|
34998
35001
|
fillContainer = false,
|
|
34999
35002
|
...restOfChartProps
|
|
35000
35003
|
}) => {
|
|
35001
|
-
const containerRef =
|
|
35002
|
-
const [dimensions, setDimensions] =
|
|
35003
|
-
const [hasValidData, setHasValidData] =
|
|
35004
|
-
|
|
35004
|
+
const containerRef = React148__default.useRef(null);
|
|
35005
|
+
const [dimensions, setDimensions] = React148__default.useState({ width: 0, height: 0 });
|
|
35006
|
+
const [hasValidData, setHasValidData] = React148__default.useState(false);
|
|
35007
|
+
React148__default.useEffect(() => {
|
|
35005
35008
|
const currentHasValidData = data && lines && lines.length > 0 && data.some(
|
|
35006
35009
|
(item) => lines.some((line) => {
|
|
35007
35010
|
const val = item[line.dataKey];
|
|
@@ -35012,7 +35015,7 @@ var LineChartComponent = ({
|
|
|
35012
35015
|
setHasValidData(true);
|
|
35013
35016
|
}
|
|
35014
35017
|
}, [data, lines, hasValidData]);
|
|
35015
|
-
|
|
35018
|
+
React148__default.useEffect(() => {
|
|
35016
35019
|
if (!containerRef.current) return;
|
|
35017
35020
|
const observer = new ResizeObserver((entries) => {
|
|
35018
35021
|
const entry = entries[0];
|
|
@@ -35137,7 +35140,7 @@ var LineChartComponent = ({
|
|
|
35137
35140
|
}
|
|
35138
35141
|
return /* @__PURE__ */ jsx("div", { className: clsx("w-full", className), children: renderChartContent(restOfChartProps.width, restOfChartProps.height) });
|
|
35139
35142
|
};
|
|
35140
|
-
var LineChart =
|
|
35143
|
+
var LineChart = React148__default.memo(LineChartComponent, (prevProps, nextProps) => {
|
|
35141
35144
|
if (prevProps.xAxisDataKey !== nextProps.xAxisDataKey || prevProps.xAxisLabel !== nextProps.xAxisLabel || prevProps.yAxisLabel !== nextProps.yAxisLabel || prevProps.yAxisUnit !== nextProps.yAxisUnit || prevProps.className !== nextProps.className || prevProps.showGrid !== nextProps.showGrid || prevProps.showLegend !== nextProps.showLegend || prevProps.showTooltip !== nextProps.showTooltip || prevProps.responsive !== nextProps.responsive || prevProps.aspect !== nextProps.aspect || JSON.stringify(prevProps.yAxisDomain) !== JSON.stringify(nextProps.yAxisDomain)) {
|
|
35142
35145
|
return false;
|
|
35143
35146
|
}
|
|
@@ -35304,7 +35307,7 @@ var SkuRow = ({ sku, isSelected, isLive, onSelect }) => {
|
|
|
35304
35307
|
);
|
|
35305
35308
|
};
|
|
35306
35309
|
var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku }) => {
|
|
35307
|
-
const ordered =
|
|
35310
|
+
const ordered = React148__default.useMemo(
|
|
35308
35311
|
() => [...rows].sort((a, b) => {
|
|
35309
35312
|
const am = (b.active_minutes ?? 0) - (a.active_minutes ?? 0);
|
|
35310
35313
|
if (am !== 0) return am;
|
|
@@ -35312,9 +35315,9 @@ var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku
|
|
|
35312
35315
|
}),
|
|
35313
35316
|
[rows]
|
|
35314
35317
|
);
|
|
35315
|
-
const scrollContainerRef =
|
|
35316
|
-
const [showScrollIndicatorBottom, setShowScrollIndicatorBottom] =
|
|
35317
|
-
const [showScrollIndicatorTop, setShowScrollIndicatorTop] =
|
|
35318
|
+
const scrollContainerRef = React148__default.useRef(null);
|
|
35319
|
+
const [showScrollIndicatorBottom, setShowScrollIndicatorBottom] = React148__default.useState(ordered.length > 4);
|
|
35320
|
+
const [showScrollIndicatorTop, setShowScrollIndicatorTop] = React148__default.useState(false);
|
|
35318
35321
|
const handleScroll = (e) => {
|
|
35319
35322
|
const target = e.currentTarget;
|
|
35320
35323
|
if (target.scrollHeight - target.scrollTop <= target.clientHeight + 10) {
|
|
@@ -35338,7 +35341,7 @@ var PerSkuView = ({ rows, className = "", selectedSkuId, liveSkuId, onSelectSku
|
|
|
35338
35341
|
scrollContainerRef.current.scrollBy({ top: -80, behavior: "smooth" });
|
|
35339
35342
|
}
|
|
35340
35343
|
};
|
|
35341
|
-
|
|
35344
|
+
React148__default.useEffect(() => {
|
|
35342
35345
|
if (scrollContainerRef.current) {
|
|
35343
35346
|
const target = scrollContainerRef.current;
|
|
35344
35347
|
setShowScrollIndicatorBottom(target.scrollHeight > target.clientHeight && target.scrollHeight - target.scrollTop > target.clientHeight + 10);
|
|
@@ -35411,7 +35414,7 @@ var OutputProgressChartComponent = ({
|
|
|
35411
35414
|
liveSkuId,
|
|
35412
35415
|
onSelectSku
|
|
35413
35416
|
}) => {
|
|
35414
|
-
const realSkuRows =
|
|
35417
|
+
const realSkuRows = React148__default.useMemo(
|
|
35415
35418
|
() => filterRealSkuBreakdown(skuBreakdown),
|
|
35416
35419
|
[skuBreakdown]
|
|
35417
35420
|
);
|
|
@@ -35436,7 +35439,7 @@ var OutputProgressChartComponent = ({
|
|
|
35436
35439
|
}
|
|
35437
35440
|
);
|
|
35438
35441
|
};
|
|
35439
|
-
var OutputProgressChart =
|
|
35442
|
+
var OutputProgressChart = React148__default.memo(OutputProgressChartComponent);
|
|
35440
35443
|
OutputProgressChart.displayName = "OutputProgressChart";
|
|
35441
35444
|
var LargeOutputProgressChart = ({
|
|
35442
35445
|
currentOutput,
|
|
@@ -35576,7 +35579,7 @@ var CycleTimeChartComponent = ({
|
|
|
35576
35579
|
}
|
|
35577
35580
|
) }) });
|
|
35578
35581
|
};
|
|
35579
|
-
var CycleTimeChart =
|
|
35582
|
+
var CycleTimeChart = React148__default.memo(CycleTimeChartComponent, (prevProps, nextProps) => {
|
|
35580
35583
|
if (prevProps.className !== nextProps.className) {
|
|
35581
35584
|
return false;
|
|
35582
35585
|
}
|
|
@@ -35816,16 +35819,16 @@ var CycleTimeOverTimeChart = ({
|
|
|
35816
35819
|
onHourClick
|
|
35817
35820
|
}) => {
|
|
35818
35821
|
const MAX_DATA_POINTS = 40;
|
|
35819
|
-
const containerRef =
|
|
35820
|
-
const [dimensions, setDimensions] =
|
|
35821
|
-
const [hasValidData, setHasValidData] =
|
|
35822
|
-
|
|
35822
|
+
const containerRef = React148__default.useRef(null);
|
|
35823
|
+
const [dimensions, setDimensions] = React148__default.useState({ width: 0, height: 0 });
|
|
35824
|
+
const [hasValidData, setHasValidData] = React148__default.useState(false);
|
|
35825
|
+
React148__default.useEffect(() => {
|
|
35823
35826
|
const currentHasValidData = data && data.some((val) => val !== null && val > 0);
|
|
35824
35827
|
if (currentHasValidData && !hasValidData) {
|
|
35825
35828
|
setHasValidData(true);
|
|
35826
35829
|
}
|
|
35827
35830
|
}, [data, hasValidData]);
|
|
35828
|
-
|
|
35831
|
+
React148__default.useEffect(() => {
|
|
35829
35832
|
if (!containerRef.current) return;
|
|
35830
35833
|
const observer = new ResizeObserver((entries) => {
|
|
35831
35834
|
const entry = entries[0];
|
|
@@ -35863,7 +35866,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
35863
35866
|
const endLabel = shiftEnd && slotIndex === DURATION - 1 ? formatHourLabel(slotIndex + 1) : formatHourLabel(slotIndex + 1);
|
|
35864
35867
|
return `${startLabel} - ${endLabel}`;
|
|
35865
35868
|
};
|
|
35866
|
-
const getDisplayData =
|
|
35869
|
+
const getDisplayData = React148__default.useCallback((rawData) => {
|
|
35867
35870
|
if (xAxisMode === "hourly") return rawData;
|
|
35868
35871
|
return rawData.slice(Math.max(0, rawData.length - MAX_DATA_POINTS));
|
|
35869
35872
|
}, [xAxisMode]);
|
|
@@ -35871,7 +35874,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
35871
35874
|
const DURATION = displayData.length;
|
|
35872
35875
|
const effectiveDatasetKey = datasetKey || `cycle-time:${xAxisMode}`;
|
|
35873
35876
|
const finalData = displayData;
|
|
35874
|
-
const labelInterval =
|
|
35877
|
+
const labelInterval = React148__default.useMemo(() => {
|
|
35875
35878
|
if (xAxisMode === "hourly") {
|
|
35876
35879
|
return Math.max(1, Math.ceil(DURATION / 8));
|
|
35877
35880
|
}
|
|
@@ -35912,8 +35915,8 @@ var CycleTimeOverTimeChart = ({
|
|
|
35912
35915
|
return `${minutes} minutes ${seconds} seconds ago`;
|
|
35913
35916
|
}
|
|
35914
35917
|
};
|
|
35915
|
-
const getNumericValue =
|
|
35916
|
-
const buildHourClickPayload =
|
|
35918
|
+
const getNumericValue = React148__default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
|
|
35919
|
+
const buildHourClickPayload = React148__default.useCallback((dataPoint) => {
|
|
35917
35920
|
if (!onHourClick || xAxisMode !== "hourly") {
|
|
35918
35921
|
return null;
|
|
35919
35922
|
}
|
|
@@ -35932,7 +35935,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
35932
35935
|
status: cycleTime !== null && cycleTime <= idealCycleTime ? "within_standard" : "above_standard"
|
|
35933
35936
|
};
|
|
35934
35937
|
}, [DURATION, getNumericValue, idealCycleTime, onHourClick, shiftEnd, shiftStart, xAxisMode]);
|
|
35935
|
-
const renderChartTooltip =
|
|
35938
|
+
const renderChartTooltip = React148__default.useCallback((tooltipProps) => {
|
|
35936
35939
|
const { active, payload } = tooltipProps;
|
|
35937
35940
|
if (!active || !Array.isArray(payload) || payload.length === 0) {
|
|
35938
35941
|
return null;
|
|
@@ -35996,7 +35999,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
35996
35999
|
] })
|
|
35997
36000
|
] });
|
|
35998
36001
|
}, [getNumericValue, onHourClick, shiftStart, showIdleTime, xAxisMode]);
|
|
35999
|
-
const renderCycleDot =
|
|
36002
|
+
const renderCycleDot = React148__default.useCallback((props) => {
|
|
36000
36003
|
const { cx: cx2, cy, payload } = props;
|
|
36001
36004
|
const cycleTime = getNumericValue(payload?.cycleTime);
|
|
36002
36005
|
if (cycleTime === null) {
|
|
@@ -36036,7 +36039,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
36036
36039
|
}
|
|
36037
36040
|
);
|
|
36038
36041
|
}, [buildHourClickPayload, getNumericValue, idealCycleTime, onHourClick, selectedHourIndex]);
|
|
36039
|
-
const renderCycleActiveDot =
|
|
36042
|
+
const renderCycleActiveDot = React148__default.useCallback((props) => {
|
|
36040
36043
|
const { cx: cx2, cy, payload } = props;
|
|
36041
36044
|
const cycleTime = getNumericValue(payload?.cycleTime);
|
|
36042
36045
|
if (cycleTime === null) {
|
|
@@ -36065,7 +36068,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
36065
36068
|
}
|
|
36066
36069
|
);
|
|
36067
36070
|
}, [buildHourClickPayload, getNumericValue, idealCycleTime, onHourClick, selectedHourIndex]);
|
|
36068
|
-
const renderIdleDot =
|
|
36071
|
+
const renderIdleDot = React148__default.useCallback((props) => {
|
|
36069
36072
|
const { cx: cx2, cy, payload } = props;
|
|
36070
36073
|
const idleMinutes = getNumericValue(payload?.idleMinutes);
|
|
36071
36074
|
if (idleMinutes === null) {
|
|
@@ -36087,7 +36090,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
36087
36090
|
}
|
|
36088
36091
|
);
|
|
36089
36092
|
}, [getNumericValue, showIdleTime]);
|
|
36090
|
-
const renderIdleActiveDot =
|
|
36093
|
+
const renderIdleActiveDot = React148__default.useCallback((props) => {
|
|
36091
36094
|
const { cx: cx2, cy, payload } = props;
|
|
36092
36095
|
const idleMinutes = getNumericValue(payload?.idleMinutes);
|
|
36093
36096
|
if (idleMinutes === null || !showIdleTime) {
|
|
@@ -36105,7 +36108,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
36105
36108
|
}
|
|
36106
36109
|
);
|
|
36107
36110
|
}, [getNumericValue, showIdleTime]);
|
|
36108
|
-
const chartData =
|
|
36111
|
+
const chartData = React148__default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
|
|
36109
36112
|
const cycleTime = getNumericValue(finalData[i]);
|
|
36110
36113
|
const useIdleSlots = idleTimeSlots.length > 0;
|
|
36111
36114
|
const idleSlot = useIdleSlots ? idleTimeSlots[i] ?? null : null;
|
|
@@ -36302,7 +36305,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
36302
36305
|
}
|
|
36303
36306
|
);
|
|
36304
36307
|
};
|
|
36305
|
-
var Card =
|
|
36308
|
+
var Card = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
36306
36309
|
"div",
|
|
36307
36310
|
{
|
|
36308
36311
|
ref,
|
|
@@ -36314,7 +36317,7 @@ var Card = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
36314
36317
|
}
|
|
36315
36318
|
));
|
|
36316
36319
|
Card.displayName = "Card";
|
|
36317
|
-
var CardHeader =
|
|
36320
|
+
var CardHeader = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
36318
36321
|
"div",
|
|
36319
36322
|
{
|
|
36320
36323
|
ref,
|
|
@@ -36323,7 +36326,7 @@ var CardHeader = React147.forwardRef(({ className, ...props }, ref) => /* @__PUR
|
|
|
36323
36326
|
}
|
|
36324
36327
|
));
|
|
36325
36328
|
CardHeader.displayName = "CardHeader";
|
|
36326
|
-
var CardTitle =
|
|
36329
|
+
var CardTitle = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
36327
36330
|
"h3",
|
|
36328
36331
|
{
|
|
36329
36332
|
ref,
|
|
@@ -36335,7 +36338,7 @@ var CardTitle = React147.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
36335
36338
|
}
|
|
36336
36339
|
));
|
|
36337
36340
|
CardTitle.displayName = "CardTitle";
|
|
36338
|
-
var CardDescription =
|
|
36341
|
+
var CardDescription = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
36339
36342
|
"p",
|
|
36340
36343
|
{
|
|
36341
36344
|
ref,
|
|
@@ -36344,9 +36347,9 @@ var CardDescription = React147.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
36344
36347
|
}
|
|
36345
36348
|
));
|
|
36346
36349
|
CardDescription.displayName = "CardDescription";
|
|
36347
|
-
var CardContent =
|
|
36350
|
+
var CardContent = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx("div", { ref, className: cn("p-6 pt-0", className), ...props }));
|
|
36348
36351
|
CardContent.displayName = "CardContent";
|
|
36349
|
-
var CardFooter =
|
|
36352
|
+
var CardFooter = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
36350
36353
|
"div",
|
|
36351
36354
|
{
|
|
36352
36355
|
ref,
|
|
@@ -36422,7 +36425,7 @@ var buttonVariants = cva(
|
|
|
36422
36425
|
}
|
|
36423
36426
|
}
|
|
36424
36427
|
);
|
|
36425
|
-
var Button =
|
|
36428
|
+
var Button = React148.forwardRef(
|
|
36426
36429
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
36427
36430
|
const Comp = asChild ? Slot : "button";
|
|
36428
36431
|
return /* @__PURE__ */ jsx(
|
|
@@ -37180,14 +37183,14 @@ var HourlyOutputChartComponent = ({
|
|
|
37180
37183
|
onAiSummaryClick,
|
|
37181
37184
|
className = ""
|
|
37182
37185
|
}) => {
|
|
37183
|
-
const containerRef =
|
|
37184
|
-
const [containerReady, setContainerReady] =
|
|
37185
|
-
const [containerWidth, setContainerWidth] =
|
|
37186
|
-
const [hoveredSkuRailLabel, setHoveredSkuRailLabel] =
|
|
37187
|
-
const [isTooltipHovered, setIsTooltipHovered] =
|
|
37188
|
-
const lastTooltipDataRef =
|
|
37189
|
-
const tooltipHoverTimeoutRef =
|
|
37190
|
-
const idleSlots =
|
|
37186
|
+
const containerRef = React148__default.useRef(null);
|
|
37187
|
+
const [containerReady, setContainerReady] = React148__default.useState(false);
|
|
37188
|
+
const [containerWidth, setContainerWidth] = React148__default.useState(0);
|
|
37189
|
+
const [hoveredSkuRailLabel, setHoveredSkuRailLabel] = React148__default.useState(null);
|
|
37190
|
+
const [isTooltipHovered, setIsTooltipHovered] = React148__default.useState(false);
|
|
37191
|
+
const lastTooltipDataRef = React148__default.useRef(null);
|
|
37192
|
+
const tooltipHoverTimeoutRef = React148__default.useRef(null);
|
|
37193
|
+
const idleSlots = React148__default.useMemo(
|
|
37191
37194
|
() => buildHourlyIdleSlots({
|
|
37192
37195
|
idleTimeHourly,
|
|
37193
37196
|
shiftStart,
|
|
@@ -37196,12 +37199,12 @@ var HourlyOutputChartComponent = ({
|
|
|
37196
37199
|
[idleTimeHourly, shiftStart, shiftEnd]
|
|
37197
37200
|
);
|
|
37198
37201
|
const SHIFT_DURATION = idleSlots.length;
|
|
37199
|
-
const [animatedData, setAnimatedData] =
|
|
37202
|
+
const [animatedData, setAnimatedData] = React148__default.useState(
|
|
37200
37203
|
() => Array(SHIFT_DURATION).fill(0)
|
|
37201
37204
|
);
|
|
37202
|
-
const prevDataRef =
|
|
37203
|
-
const animationFrameRef =
|
|
37204
|
-
|
|
37205
|
+
const prevDataRef = React148__default.useRef(Array(SHIFT_DURATION).fill(0));
|
|
37206
|
+
const animationFrameRef = React148__default.useRef(null);
|
|
37207
|
+
React148__default.useEffect(() => {
|
|
37205
37208
|
setAnimatedData((prev) => {
|
|
37206
37209
|
if (prev.length !== SHIFT_DURATION) {
|
|
37207
37210
|
return Array(SHIFT_DURATION).fill(0);
|
|
@@ -37210,14 +37213,14 @@ var HourlyOutputChartComponent = ({
|
|
|
37210
37213
|
});
|
|
37211
37214
|
prevDataRef.current = Array(SHIFT_DURATION).fill(0);
|
|
37212
37215
|
}, [SHIFT_DURATION]);
|
|
37213
|
-
const [idleBarState, setIdleBarState] =
|
|
37216
|
+
const [idleBarState, setIdleBarState] = React148__default.useState({
|
|
37214
37217
|
visible: showIdleTime,
|
|
37215
37218
|
key: 0,
|
|
37216
37219
|
shouldAnimate: false
|
|
37217
37220
|
});
|
|
37218
|
-
const prevShowIdleTimeRef =
|
|
37219
|
-
const stateUpdateTimeoutRef =
|
|
37220
|
-
|
|
37221
|
+
const prevShowIdleTimeRef = React148__default.useRef(showIdleTime);
|
|
37222
|
+
const stateUpdateTimeoutRef = React148__default.useRef(null);
|
|
37223
|
+
React148__default.useEffect(() => {
|
|
37221
37224
|
if (stateUpdateTimeoutRef.current) {
|
|
37222
37225
|
clearTimeout(stateUpdateTimeoutRef.current);
|
|
37223
37226
|
}
|
|
@@ -37242,7 +37245,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37242
37245
|
}
|
|
37243
37246
|
};
|
|
37244
37247
|
}, [showIdleTime]);
|
|
37245
|
-
const animateToNewData =
|
|
37248
|
+
const animateToNewData = React148__default.useCallback((targetData) => {
|
|
37246
37249
|
const startData = [...prevDataRef.current];
|
|
37247
37250
|
const startTime = performance.now();
|
|
37248
37251
|
const duration = 1200;
|
|
@@ -37272,7 +37275,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37272
37275
|
}
|
|
37273
37276
|
animationFrameRef.current = requestAnimationFrame(animate);
|
|
37274
37277
|
}, []);
|
|
37275
|
-
|
|
37278
|
+
React148__default.useEffect(() => {
|
|
37276
37279
|
if (JSON.stringify(data) !== JSON.stringify(prevDataRef.current)) {
|
|
37277
37280
|
const shiftData = data.slice(0, SHIFT_DURATION);
|
|
37278
37281
|
animateToNewData(shiftData);
|
|
@@ -37283,14 +37286,14 @@ var HourlyOutputChartComponent = ({
|
|
|
37283
37286
|
}
|
|
37284
37287
|
};
|
|
37285
37288
|
}, [data, animateToNewData]);
|
|
37286
|
-
|
|
37289
|
+
React148__default.useEffect(() => {
|
|
37287
37290
|
return () => {
|
|
37288
37291
|
if (tooltipHoverTimeoutRef.current) {
|
|
37289
37292
|
clearTimeout(tooltipHoverTimeoutRef.current);
|
|
37290
37293
|
}
|
|
37291
37294
|
};
|
|
37292
37295
|
}, []);
|
|
37293
|
-
|
|
37296
|
+
React148__default.useEffect(() => {
|
|
37294
37297
|
const checkContainerDimensions = () => {
|
|
37295
37298
|
if (containerRef.current) {
|
|
37296
37299
|
const rect = containerRef.current.getBoundingClientRect();
|
|
@@ -37316,7 +37319,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37316
37319
|
clearTimeout(fallbackTimeout);
|
|
37317
37320
|
};
|
|
37318
37321
|
}, []);
|
|
37319
|
-
const xAxisConfig =
|
|
37322
|
+
const xAxisConfig = React148__default.useMemo(() => {
|
|
37320
37323
|
if (containerWidth >= 960) {
|
|
37321
37324
|
return {
|
|
37322
37325
|
interval: 0,
|
|
@@ -37337,13 +37340,13 @@ var HourlyOutputChartComponent = ({
|
|
|
37337
37340
|
}
|
|
37338
37341
|
return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6 };
|
|
37339
37342
|
}, [containerWidth]);
|
|
37340
|
-
const shiftWindow =
|
|
37343
|
+
const shiftWindow = React148__default.useMemo(() => resolveShiftWindow2({
|
|
37341
37344
|
shiftStart,
|
|
37342
37345
|
slotCount: SHIFT_DURATION,
|
|
37343
37346
|
shiftDate,
|
|
37344
37347
|
timezone
|
|
37345
37348
|
}), [shiftStart, shiftEnd, SHIFT_DURATION, shiftDate, timezone]);
|
|
37346
|
-
const fallbackTimelineEndOffset =
|
|
37349
|
+
const fallbackTimelineEndOffset = React148__default.useMemo(
|
|
37347
37350
|
() => resolveTimelineEndOffset({
|
|
37348
37351
|
shiftStart,
|
|
37349
37352
|
shiftEnd,
|
|
@@ -37353,7 +37356,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37353
37356
|
}),
|
|
37354
37357
|
[shiftStart, shiftEnd, SHIFT_DURATION, shiftDate, timezone]
|
|
37355
37358
|
);
|
|
37356
|
-
const observedTimelineEndOffset =
|
|
37359
|
+
const observedTimelineEndOffset = React148__default.useMemo(() => {
|
|
37357
37360
|
let lastObservedMinute = -1;
|
|
37358
37361
|
idleSlots.forEach((slot) => {
|
|
37359
37362
|
slot.idleArray.forEach((value, minuteIndex) => {
|
|
@@ -37369,7 +37372,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37369
37372
|
return Math.min((lastObservedMinute + 1) / 60, SHIFT_DURATION);
|
|
37370
37373
|
}, [idleSlots, SHIFT_DURATION]);
|
|
37371
37374
|
const timelineEndOffset = observedTimelineEndOffset ?? fallbackTimelineEndOffset;
|
|
37372
|
-
const targetLineEndOffset =
|
|
37375
|
+
const targetLineEndOffset = React148__default.useMemo(() => {
|
|
37373
37376
|
if (timelineEndOffset >= SHIFT_DURATION) {
|
|
37374
37377
|
return SHIFT_DURATION;
|
|
37375
37378
|
}
|
|
@@ -37378,7 +37381,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37378
37381
|
}
|
|
37379
37382
|
return Math.min(Math.floor(timelineEndOffset) + 1, SHIFT_DURATION);
|
|
37380
37383
|
}, [timelineEndOffset, SHIFT_DURATION]);
|
|
37381
|
-
const skuTimelineSegments =
|
|
37384
|
+
const skuTimelineSegments = React148__default.useMemo(() => {
|
|
37382
37385
|
if (!skuSegments || skuSegments.length === 0 || !shiftWindow || timelineEndOffset <= 0) {
|
|
37383
37386
|
return [];
|
|
37384
37387
|
}
|
|
@@ -37412,18 +37415,18 @@ var HourlyOutputChartComponent = ({
|
|
|
37412
37415
|
};
|
|
37413
37416
|
}).filter((segment) => segment.end > segment.start);
|
|
37414
37417
|
}, [skuSegments, shiftWindow, timelineEndOffset, pphThreshold]);
|
|
37415
|
-
const targetTimelineSegments =
|
|
37418
|
+
const targetTimelineSegments = React148__default.useMemo(() => {
|
|
37416
37419
|
if (skuTimelineSegments.length === 0) return [];
|
|
37417
37420
|
return skuTimelineSegments.map((segment, index) => ({
|
|
37418
37421
|
...segment,
|
|
37419
37422
|
end: index === skuTimelineSegments.length - 1 ? Math.max(segment.start, targetLineEndOffset) : segment.end
|
|
37420
37423
|
})).filter((segment) => segment.end > segment.start);
|
|
37421
37424
|
}, [skuTimelineSegments, targetLineEndOffset]);
|
|
37422
|
-
const hasExplicitHourlyTargetOutputProp =
|
|
37425
|
+
const hasExplicitHourlyTargetOutputProp = React148__default.useMemo(
|
|
37423
37426
|
() => hourlyTargetOutput !== void 0,
|
|
37424
37427
|
[hourlyTargetOutput]
|
|
37425
37428
|
);
|
|
37426
|
-
const fallbackHourlyTargetOutput =
|
|
37429
|
+
const fallbackHourlyTargetOutput = React148__default.useMemo(() => {
|
|
37427
37430
|
if (hasExplicitHourlyTargetOutputProp) return void 0;
|
|
37428
37431
|
if (skuTimelineSegments.length > 0) return void 0;
|
|
37429
37432
|
const plan = buildHourlyTargetPlan({
|
|
@@ -37443,19 +37446,19 @@ var HourlyOutputChartComponent = ({
|
|
|
37443
37446
|
shiftBreaks,
|
|
37444
37447
|
pphThreshold
|
|
37445
37448
|
]);
|
|
37446
|
-
const effectiveHourlyTargetOutput =
|
|
37449
|
+
const effectiveHourlyTargetOutput = React148__default.useMemo(
|
|
37447
37450
|
() => hasExplicitHourlyTargetOutputProp ? hourlyTargetOutput : fallbackHourlyTargetOutput,
|
|
37448
37451
|
[hasExplicitHourlyTargetOutputProp, hourlyTargetOutput, fallbackHourlyTargetOutput]
|
|
37449
37452
|
);
|
|
37450
|
-
const hasHourlyTargetOutputProp =
|
|
37453
|
+
const hasHourlyTargetOutputProp = React148__default.useMemo(
|
|
37451
37454
|
() => effectiveHourlyTargetOutput !== void 0,
|
|
37452
37455
|
[effectiveHourlyTargetOutput]
|
|
37453
37456
|
);
|
|
37454
|
-
const hasExplicitHourlyTargets =
|
|
37457
|
+
const hasExplicitHourlyTargets = React148__default.useMemo(
|
|
37455
37458
|
() => Array.isArray(effectiveHourlyTargetOutput) && effectiveHourlyTargetOutput.some((value) => value !== null && value !== void 0),
|
|
37456
37459
|
[effectiveHourlyTargetOutput]
|
|
37457
37460
|
);
|
|
37458
|
-
const hourlyTargetSegments =
|
|
37461
|
+
const hourlyTargetSegments = React148__default.useMemo(() => {
|
|
37459
37462
|
if (!hasExplicitHourlyTargets) return [];
|
|
37460
37463
|
const segments = [];
|
|
37461
37464
|
let runStart = null;
|
|
@@ -37487,7 +37490,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37487
37490
|
flush(SHIFT_DURATION);
|
|
37488
37491
|
return segments.filter((segment) => segment.end > segment.start);
|
|
37489
37492
|
}, [SHIFT_DURATION, hasExplicitHourlyTargets, effectiveHourlyTargetOutput]);
|
|
37490
|
-
const activeSkuHourIndices =
|
|
37493
|
+
const activeSkuHourIndices = React148__default.useMemo(() => {
|
|
37491
37494
|
const indices = /* @__PURE__ */ new Set();
|
|
37492
37495
|
const targets = Array(SHIFT_DURATION).fill(pphThreshold);
|
|
37493
37496
|
if (!skuSegments || !shiftWindow) return { indices, targets, hasTimeline: false };
|
|
@@ -37520,7 +37523,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37520
37523
|
}
|
|
37521
37524
|
return { indices, targets, hasTimeline: true };
|
|
37522
37525
|
}, [skuSegments, activeSkuId, shiftWindow, SHIFT_DURATION, pphThreshold]);
|
|
37523
|
-
const chartData =
|
|
37526
|
+
const chartData = React148__default.useMemo(() => {
|
|
37524
37527
|
const { indices, targets, hasTimeline } = activeSkuHourIndices;
|
|
37525
37528
|
return Array.from({ length: SHIFT_DURATION }, (_, i) => {
|
|
37526
37529
|
const idleSlot = idleSlots[i];
|
|
@@ -37549,7 +37552,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37549
37552
|
};
|
|
37550
37553
|
});
|
|
37551
37554
|
}, [animatedData, data, pphThreshold, idleSlots, SHIFT_DURATION, activeSkuHourIndices, activeSkuId, effectiveHourlyTargetOutput, hasHourlyTargetOutputProp, selectedHourIndex]);
|
|
37552
|
-
const renderSkuTimelineRail =
|
|
37555
|
+
const renderSkuTimelineRail = React148__default.useCallback((props) => {
|
|
37553
37556
|
if (!skuTimelineSegments.length || SHIFT_DURATION <= 0) return null;
|
|
37554
37557
|
const offset = props?.offset;
|
|
37555
37558
|
if (!offset) return null;
|
|
@@ -37698,7 +37701,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37698
37701
|
})
|
|
37699
37702
|
] });
|
|
37700
37703
|
}, [skuTimelineSegments, SHIFT_DURATION, activeSkuId]);
|
|
37701
|
-
const IdleBar =
|
|
37704
|
+
const IdleBar = React148__default.useMemo(() => {
|
|
37702
37705
|
if (!idleBarState.visible) return null;
|
|
37703
37706
|
return /* @__PURE__ */ jsx(
|
|
37704
37707
|
Bar,
|
|
@@ -37792,7 +37795,7 @@ var HourlyOutputChartComponent = ({
|
|
|
37792
37795
|
}
|
|
37793
37796
|
return filteredTicks;
|
|
37794
37797
|
};
|
|
37795
|
-
const renderTargetLine =
|
|
37798
|
+
const renderTargetLine = React148__default.useCallback((props) => {
|
|
37796
37799
|
const { offset, yAxisMap } = props;
|
|
37797
37800
|
if (!offset || !yAxisMap || SHIFT_DURATION <= 0 || targetLineEndOffset <= 0) return null;
|
|
37798
37801
|
const { left, width } = offset;
|
|
@@ -38293,7 +38296,7 @@ var HourlyOutputChartComponent = ({
|
|
|
38293
38296
|
}
|
|
38294
38297
|
);
|
|
38295
38298
|
};
|
|
38296
|
-
var HourlyOutputChart =
|
|
38299
|
+
var HourlyOutputChart = React148__default.memo(
|
|
38297
38300
|
HourlyOutputChartComponent,
|
|
38298
38301
|
(prevProps, nextProps) => {
|
|
38299
38302
|
if (prevProps.pphThreshold !== nextProps.pphThreshold || prevProps.shiftStart !== nextProps.shiftStart || prevProps.shiftEnd !== nextProps.shiftEnd || prevProps.shiftDate !== nextProps.shiftDate || prevProps.timezone !== nextProps.timezone || prevProps.showIdleTime !== nextProps.showIdleTime || prevProps.activeSkuId !== nextProps.activeSkuId || prevProps.selectedHourIndex !== nextProps.selectedHourIndex || prevProps.onHourClick !== nextProps.onHourClick || prevProps.className !== nextProps.className) {
|
|
@@ -38747,7 +38750,7 @@ function getTrendArrowAndColor(trend) {
|
|
|
38747
38750
|
return { arrow: "\u2192", color: "text-gray-400" };
|
|
38748
38751
|
}
|
|
38749
38752
|
}
|
|
38750
|
-
var VideoCard =
|
|
38753
|
+
var VideoCard = React148__default.memo(({
|
|
38751
38754
|
workspace,
|
|
38752
38755
|
hlsUrl,
|
|
38753
38756
|
shouldPlay,
|
|
@@ -39017,7 +39020,7 @@ var hasRecentHealthSignal = (lastHeartbeat) => {
|
|
|
39017
39020
|
if (!Number.isFinite(heartbeatMs)) return false;
|
|
39018
39021
|
return Date.now() - heartbeatMs <= RECENT_HEALTH_SIGNAL_MS;
|
|
39019
39022
|
};
|
|
39020
|
-
var VideoGridView =
|
|
39023
|
+
var VideoGridView = React148__default.memo(({
|
|
39021
39024
|
workspaces,
|
|
39022
39025
|
blueComparisonWorkspaces,
|
|
39023
39026
|
selectedLine,
|
|
@@ -39456,7 +39459,7 @@ var VideoGridView = React147__default.memo(({
|
|
|
39456
39459
|
) });
|
|
39457
39460
|
});
|
|
39458
39461
|
VideoGridView.displayName = "VideoGridView";
|
|
39459
|
-
var MapGridView =
|
|
39462
|
+
var MapGridView = React148__default.memo(({
|
|
39460
39463
|
workspaces,
|
|
39461
39464
|
className = "",
|
|
39462
39465
|
displayNames = {},
|
|
@@ -39677,13 +39680,13 @@ var WorkspaceMetricCardsImpl = ({
|
|
|
39677
39680
|
liveSkuId
|
|
39678
39681
|
}) => {
|
|
39679
39682
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
39680
|
-
const activeSku =
|
|
39683
|
+
const activeSku = React148__default.useMemo(() => {
|
|
39681
39684
|
if (skuAware && activeSkuId && skuBreakdown) {
|
|
39682
39685
|
return skuBreakdown.find((s) => s.sku_id === activeSkuId);
|
|
39683
39686
|
}
|
|
39684
39687
|
return null;
|
|
39685
39688
|
}, [skuAware, activeSkuId, skuBreakdown]);
|
|
39686
|
-
const displaySku =
|
|
39689
|
+
const displaySku = React148__default.useMemo(() => {
|
|
39687
39690
|
if (activeSku) return activeSku;
|
|
39688
39691
|
if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
|
|
39689
39692
|
return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
|
|
@@ -40337,7 +40340,7 @@ var UptimeLineChartComponent = ({ points, className = "" }) => {
|
|
|
40337
40340
|
)
|
|
40338
40341
|
] }) }) });
|
|
40339
40342
|
};
|
|
40340
|
-
var UptimeLineChart =
|
|
40343
|
+
var UptimeLineChart = React148__default.memo(UptimeLineChartComponent);
|
|
40341
40344
|
var getTimeFromTimeString = (timeStr) => {
|
|
40342
40345
|
if (!timeStr) {
|
|
40343
40346
|
return { hour: 0, minute: 0, decimalHour: 0 };
|
|
@@ -40361,10 +40364,10 @@ var HourlyUptimeChartComponent = ({
|
|
|
40361
40364
|
shiftBreaks,
|
|
40362
40365
|
className = ""
|
|
40363
40366
|
}) => {
|
|
40364
|
-
const containerRef =
|
|
40365
|
-
const [containerReady, setContainerReady] =
|
|
40366
|
-
const [containerWidth, setContainerWidth] =
|
|
40367
|
-
const uptimeSeries =
|
|
40367
|
+
const containerRef = React148__default.useRef(null);
|
|
40368
|
+
const [containerReady, setContainerReady] = React148__default.useState(false);
|
|
40369
|
+
const [containerWidth, setContainerWidth] = React148__default.useState(0);
|
|
40370
|
+
const uptimeSeries = React148__default.useMemo(() => buildUptimeSeries({
|
|
40368
40371
|
idleTimeHourly,
|
|
40369
40372
|
shiftStart,
|
|
40370
40373
|
shiftEnd,
|
|
@@ -40374,11 +40377,11 @@ var HourlyUptimeChartComponent = ({
|
|
|
40374
40377
|
shiftBreaks
|
|
40375
40378
|
}), [idleTimeHourly, shiftStart, shiftEnd, shiftDate, timezone, elapsedMinutes, shiftBreaks]);
|
|
40376
40379
|
const hasAggregateData = Boolean(hourlyAggregates && hourlyAggregates.length > 0);
|
|
40377
|
-
const shiftStartTime =
|
|
40380
|
+
const shiftStartTime = React148__default.useMemo(
|
|
40378
40381
|
() => getTimeFromTimeString(shiftStart),
|
|
40379
40382
|
[shiftStart]
|
|
40380
40383
|
);
|
|
40381
|
-
const { shiftDuration, shiftEndTime } =
|
|
40384
|
+
const { shiftDuration, shiftEndTime } = React148__default.useMemo(() => {
|
|
40382
40385
|
if (!shiftEnd) {
|
|
40383
40386
|
const fallbackHours = uptimeSeries.shiftMinutes > 0 ? Math.ceil(uptimeSeries.shiftMinutes / 60) : 0;
|
|
40384
40387
|
return { shiftDuration: fallbackHours, shiftEndTime: null };
|
|
@@ -40392,7 +40395,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40392
40395
|
const hourCount = hasPartial ? Math.ceil(duration) : Math.round(duration);
|
|
40393
40396
|
return { shiftDuration: hourCount, shiftEndTime: endTime };
|
|
40394
40397
|
}, [shiftEnd, shiftStartTime.decimalHour, uptimeSeries.shiftMinutes]);
|
|
40395
|
-
const formatHour =
|
|
40398
|
+
const formatHour = React148__default.useCallback((hourIndex) => {
|
|
40396
40399
|
const isLastHour = hourIndex === shiftDuration - 1;
|
|
40397
40400
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
40398
40401
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
@@ -40417,7 +40420,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40417
40420
|
};
|
|
40418
40421
|
return `${formatTime5(startHour, startMinute)}-${formatTime5(endHour, endMinute)}`;
|
|
40419
40422
|
}, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
|
|
40420
|
-
const formatTimeRange2 =
|
|
40423
|
+
const formatTimeRange2 = React148__default.useCallback((hourIndex) => {
|
|
40421
40424
|
const isLastHour = hourIndex === shiftDuration - 1;
|
|
40422
40425
|
const startDecimalHour = shiftStartTime.decimalHour + hourIndex;
|
|
40423
40426
|
const startHour = Math.floor(startDecimalHour) % 24;
|
|
@@ -40439,7 +40442,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40439
40442
|
};
|
|
40440
40443
|
return `${formatTime5(startHour, startMinute)} - ${formatTime5(endHour, endMinute)}`;
|
|
40441
40444
|
}, [shiftDuration, shiftStartTime.decimalHour, shiftEndTime]);
|
|
40442
|
-
const chartData =
|
|
40445
|
+
const chartData = React148__default.useMemo(() => {
|
|
40443
40446
|
if (shiftDuration <= 0) return [];
|
|
40444
40447
|
if (hasAggregateData) {
|
|
40445
40448
|
return hourlyAggregates.map((entry, hourIndex) => ({
|
|
@@ -40481,7 +40484,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40481
40484
|
}, [hasAggregateData, hourlyAggregates, uptimeSeries.points, uptimeSeries.elapsedMinutes, uptimeSeries.shiftMinutes, shiftDuration, formatHour, formatTimeRange2]);
|
|
40482
40485
|
const maxYValue = 100;
|
|
40483
40486
|
const yAxisTicks = [0, 25, 50, 75, 100];
|
|
40484
|
-
|
|
40487
|
+
React148__default.useEffect(() => {
|
|
40485
40488
|
const checkContainerDimensions = () => {
|
|
40486
40489
|
if (containerRef.current) {
|
|
40487
40490
|
const rect = containerRef.current.getBoundingClientRect();
|
|
@@ -40507,7 +40510,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40507
40510
|
clearTimeout(fallbackTimeout);
|
|
40508
40511
|
};
|
|
40509
40512
|
}, []);
|
|
40510
|
-
const xAxisConfig =
|
|
40513
|
+
const xAxisConfig = React148__default.useMemo(() => {
|
|
40511
40514
|
if (containerWidth >= 960) {
|
|
40512
40515
|
return { interval: 0, angle: -45, height: 92, tickFont: 10, tickMargin: 12, labelMode: "full" };
|
|
40513
40516
|
}
|
|
@@ -40516,7 +40519,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40516
40519
|
}
|
|
40517
40520
|
return { interval: 0, angle: -30, height: 64, tickFont: 9, tickMargin: 6, labelMode: "start" };
|
|
40518
40521
|
}, [containerWidth]);
|
|
40519
|
-
const formatXAxisTick =
|
|
40522
|
+
const formatXAxisTick = React148__default.useCallback((raw) => {
|
|
40520
40523
|
const label = typeof raw === "string" ? raw : String(raw);
|
|
40521
40524
|
if (xAxisConfig.labelMode === "full") return label;
|
|
40522
40525
|
const parts = label.split("-");
|
|
@@ -40722,7 +40725,7 @@ var HourlyUptimeChartComponent = ({
|
|
|
40722
40725
|
}
|
|
40723
40726
|
);
|
|
40724
40727
|
};
|
|
40725
|
-
var HourlyUptimeChart =
|
|
40728
|
+
var HourlyUptimeChart = React148__default.memo(HourlyUptimeChartComponent);
|
|
40726
40729
|
var DEFAULT_COLORS2 = ["#00AB45", "#ef4444"];
|
|
40727
40730
|
var UptimeDonutChartComponent = ({
|
|
40728
40731
|
data,
|
|
@@ -40792,7 +40795,7 @@ var UptimeDonutChartComponent = ({
|
|
|
40792
40795
|
] }) })
|
|
40793
40796
|
] }) });
|
|
40794
40797
|
};
|
|
40795
|
-
var UptimeDonutChart =
|
|
40798
|
+
var UptimeDonutChart = React148__default.memo(UptimeDonutChartComponent);
|
|
40796
40799
|
UptimeDonutChart.displayName = "UptimeDonutChart";
|
|
40797
40800
|
var TrendIcon = ({ trend }) => {
|
|
40798
40801
|
if (trend === "up") {
|
|
@@ -40913,7 +40916,7 @@ var EmptyStateMessage = ({
|
|
|
40913
40916
|
iconClassName
|
|
40914
40917
|
}) => {
|
|
40915
40918
|
let IconContent = null;
|
|
40916
|
-
if (
|
|
40919
|
+
if (React148__default.isValidElement(iconType)) {
|
|
40917
40920
|
IconContent = iconType;
|
|
40918
40921
|
} else if (typeof iconType === "string") {
|
|
40919
40922
|
const MappedIcon = IconMap[iconType];
|
|
@@ -41421,6 +41424,7 @@ var CYCLE_RANGE_CATEGORY_IDS = /* @__PURE__ */ new Set([
|
|
|
41421
41424
|
"fast-cycles",
|
|
41422
41425
|
"slow-cycles"
|
|
41423
41426
|
]);
|
|
41427
|
+
var EXPLICIT_INTERVAL_CATEGORY_IDS = /* @__PURE__ */ new Set(["recent_flow_red_streak"]);
|
|
41424
41428
|
var roundToNearestMinute = (date) => {
|
|
41425
41429
|
const rounded = new Date(date.getTime());
|
|
41426
41430
|
const seconds = rounded.getSeconds();
|
|
@@ -41476,6 +41480,22 @@ var buildPrefetchedExplorerMetadata = (activeFilter, metadataCategoryId, categor
|
|
|
41476
41480
|
};
|
|
41477
41481
|
};
|
|
41478
41482
|
var shouldDeferClipPlayerRender = (cropLoading, workspaceCrop) => cropLoading && workspaceCrop === null;
|
|
41483
|
+
var getCategoryMetadataLoadPlanForFilterChange = ({
|
|
41484
|
+
activeFilter,
|
|
41485
|
+
currentClipId,
|
|
41486
|
+
categoryTotal
|
|
41487
|
+
}) => {
|
|
41488
|
+
if (!activeFilter || activeFilter === "all") {
|
|
41489
|
+
return { shouldLoad: false, autoLoadFirstVideo: false };
|
|
41490
|
+
}
|
|
41491
|
+
if (activeFilter === "recent_flow_red_streak" && categoryTotal > 0) {
|
|
41492
|
+
return { shouldLoad: true, autoLoadFirstVideo: true };
|
|
41493
|
+
}
|
|
41494
|
+
return {
|
|
41495
|
+
shouldLoad: Boolean(currentClipId),
|
|
41496
|
+
autoLoadFirstVideo: false
|
|
41497
|
+
};
|
|
41498
|
+
};
|
|
41479
41499
|
var getSecondsBetweenTimestamps = (startTime, endTime) => {
|
|
41480
41500
|
const startDate = parseTimestamp(startTime);
|
|
41481
41501
|
const endDate = parseTimestamp(endTime);
|
|
@@ -41488,8 +41508,24 @@ var formatClipExplorerTimeLabel = ({
|
|
|
41488
41508
|
timezone,
|
|
41489
41509
|
durationSeconds,
|
|
41490
41510
|
idleStartTime,
|
|
41491
|
-
idleEndTime
|
|
41511
|
+
idleEndTime,
|
|
41512
|
+
clipStartTime,
|
|
41513
|
+
clipEndTime
|
|
41492
41514
|
}) => {
|
|
41515
|
+
if (EXPLICIT_INTERVAL_CATEGORY_IDS.has(categoryId)) {
|
|
41516
|
+
const endTimestamp = clipEndTime || clipTimestamp;
|
|
41517
|
+
if (clipStartTime && endTimestamp) {
|
|
41518
|
+
return formatTimestampRange(clipStartTime, endTimestamp, timezone);
|
|
41519
|
+
}
|
|
41520
|
+
if (typeof durationSeconds === "number" && Number.isFinite(durationSeconds) && durationSeconds > 0) {
|
|
41521
|
+
const endDate = parseTimestamp(endTimestamp);
|
|
41522
|
+
if (endDate) {
|
|
41523
|
+
const startDate = new Date(endDate.getTime() - durationSeconds * 1e3);
|
|
41524
|
+
return formatTimestampRange(startDate.toISOString(), endTimestamp, timezone);
|
|
41525
|
+
}
|
|
41526
|
+
}
|
|
41527
|
+
return formatClipExplorerSingleTime(endTimestamp, timezone);
|
|
41528
|
+
}
|
|
41493
41529
|
if (IDLE_RANGE_CATEGORY_IDS.has(categoryId)) {
|
|
41494
41530
|
const idleDurationSeconds = getSecondsBetweenTimestamps(idleStartTime, idleEndTime);
|
|
41495
41531
|
const idleEndTimestamp = idleEndTime || clipTimestamp;
|
|
@@ -41516,6 +41552,106 @@ var formatClipExplorerTimeLabel = ({
|
|
|
41516
41552
|
return singleTime;
|
|
41517
41553
|
};
|
|
41518
41554
|
var formatIdleTimeRange = (startTime, endTime, timezone) => formatTimestampRange(startTime, endTime, timezone);
|
|
41555
|
+
|
|
41556
|
+
// src/lib/utils/redFlowDisplay.ts
|
|
41557
|
+
var getRedFlowDriverLabel = (driver) => {
|
|
41558
|
+
switch (driver) {
|
|
41559
|
+
case "idle":
|
|
41560
|
+
return "Idle";
|
|
41561
|
+
case "micro_stoppage":
|
|
41562
|
+
return "Gaps";
|
|
41563
|
+
case "slow_cycle":
|
|
41564
|
+
return "Slow Cycles";
|
|
41565
|
+
case "low_output":
|
|
41566
|
+
return "Low Output";
|
|
41567
|
+
default:
|
|
41568
|
+
return "";
|
|
41569
|
+
}
|
|
41570
|
+
};
|
|
41571
|
+
var getRedFlowDriversFromEvidence = (evidence) => {
|
|
41572
|
+
const drivers = /* @__PURE__ */ new Set();
|
|
41573
|
+
(evidence || []).forEach((item) => {
|
|
41574
|
+
const normalized = item.toLowerCase();
|
|
41575
|
+
if (normalized.includes("idle")) {
|
|
41576
|
+
drivers.add("idle");
|
|
41577
|
+
}
|
|
41578
|
+
if (normalized.includes("micro") || normalized.includes("gap")) {
|
|
41579
|
+
drivers.add("micro_stoppage");
|
|
41580
|
+
}
|
|
41581
|
+
if (normalized.includes("slow") || normalized.includes("cycle time") || normalized.includes("shift avg")) {
|
|
41582
|
+
drivers.add("slow_cycle");
|
|
41583
|
+
}
|
|
41584
|
+
if (normalized.includes("output")) {
|
|
41585
|
+
drivers.add("low_output");
|
|
41586
|
+
}
|
|
41587
|
+
});
|
|
41588
|
+
return Array.from(drivers);
|
|
41589
|
+
};
|
|
41590
|
+
var getRedFlowDisplayDriverKeys = (summary) => {
|
|
41591
|
+
if (!summary || summary.confidence !== "medium" && summary.confidence !== "high") {
|
|
41592
|
+
return [];
|
|
41593
|
+
}
|
|
41594
|
+
if (summary.primary_driver === "unknown") {
|
|
41595
|
+
return [];
|
|
41596
|
+
}
|
|
41597
|
+
if (summary.primary_driver === "mixed") {
|
|
41598
|
+
const evidenceDrivers = getRedFlowDriversFromEvidence(summary.evidence).filter((driver) => Boolean(getRedFlowDriverLabel(driver)));
|
|
41599
|
+
return evidenceDrivers.length >= 2 ? evidenceDrivers.slice(0, 3) : [];
|
|
41600
|
+
}
|
|
41601
|
+
return getRedFlowDriverLabel(summary.primary_driver) ? [summary.primary_driver] : [];
|
|
41602
|
+
};
|
|
41603
|
+
var formatRedFlowCompactNumber = (value) => Number.isInteger(value) ? String(value) : value.toFixed(1).replace(/\.0$/, "");
|
|
41604
|
+
var formatRedFlowOutputCount = (value) => Number.isFinite(value) ? String(Math.round(value)) : "";
|
|
41605
|
+
var getRedFlowBinOutputUnits = (bin) => {
|
|
41606
|
+
if (typeof bin.actual_output_units === "number" && Number.isFinite(bin.actual_output_units)) {
|
|
41607
|
+
return bin.actual_output_units;
|
|
41608
|
+
}
|
|
41609
|
+
if (typeof bin.actual_ppm === "number" && Number.isFinite(bin.actual_ppm)) {
|
|
41610
|
+
const durationSeconds = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : 60;
|
|
41611
|
+
return bin.actual_ppm * durationSeconds / 60;
|
|
41612
|
+
}
|
|
41613
|
+
return null;
|
|
41614
|
+
};
|
|
41615
|
+
var summarizeRedFlowOutput = (timeline, summary) => {
|
|
41616
|
+
const actualFromSummary = summary?.totals.actual_output_units;
|
|
41617
|
+
const expectedFromSummary = summary?.totals.baseline_output_units;
|
|
41618
|
+
if (typeof actualFromSummary === "number" && Number.isFinite(actualFromSummary) && typeof expectedFromSummary === "number" && Number.isFinite(expectedFromSummary)) {
|
|
41619
|
+
return { actual: actualFromSummary, expected: expectedFromSummary };
|
|
41620
|
+
}
|
|
41621
|
+
let actual = 0;
|
|
41622
|
+
let expected = 0;
|
|
41623
|
+
let hasActual = false;
|
|
41624
|
+
let hasExpected = false;
|
|
41625
|
+
(timeline?.minute_bins || []).forEach((bin) => {
|
|
41626
|
+
const output = getRedFlowBinOutputUnits(bin);
|
|
41627
|
+
if (output !== null) {
|
|
41628
|
+
actual += output;
|
|
41629
|
+
hasActual = true;
|
|
41630
|
+
}
|
|
41631
|
+
if (typeof bin.target_ppm === "number" && Number.isFinite(bin.target_ppm)) {
|
|
41632
|
+
const durationSeconds = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : 60;
|
|
41633
|
+
expected += bin.target_ppm * durationSeconds / 60;
|
|
41634
|
+
hasExpected = true;
|
|
41635
|
+
}
|
|
41636
|
+
});
|
|
41637
|
+
return hasActual && hasExpected ? { actual, expected } : null;
|
|
41638
|
+
};
|
|
41639
|
+
var getRedFlowOutputShortfallUnits = (timeline) => {
|
|
41640
|
+
let actual = 0;
|
|
41641
|
+
let expected = 0;
|
|
41642
|
+
let hasComparableBin = false;
|
|
41643
|
+
(timeline?.minute_bins || []).forEach((bin) => {
|
|
41644
|
+
const output = getRedFlowBinOutputUnits(bin);
|
|
41645
|
+
const durationSeconds = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : null;
|
|
41646
|
+
if (output === null || durationSeconds === null || typeof bin.target_ppm !== "number" || !Number.isFinite(bin.target_ppm)) {
|
|
41647
|
+
return;
|
|
41648
|
+
}
|
|
41649
|
+
actual += output;
|
|
41650
|
+
expected += bin.target_ppm * durationSeconds / 60;
|
|
41651
|
+
hasComparableBin = true;
|
|
41652
|
+
});
|
|
41653
|
+
return hasComparableBin ? expected - actual : null;
|
|
41654
|
+
};
|
|
41519
41655
|
var formatTime2 = (seconds) => {
|
|
41520
41656
|
if (!seconds || isNaN(seconds)) return "0:00";
|
|
41521
41657
|
const h = Math.floor(seconds / 3600);
|
|
@@ -41526,6 +41662,33 @@ var formatTime2 = (seconds) => {
|
|
|
41526
41662
|
}
|
|
41527
41663
|
return `${m}:${s.toString().padStart(2, "0")}`;
|
|
41528
41664
|
};
|
|
41665
|
+
var formatTimelineClockTime = (isoTime, timezone) => {
|
|
41666
|
+
if (!isoTime) return "";
|
|
41667
|
+
const date = new Date(isoTime);
|
|
41668
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
41669
|
+
return date.toLocaleTimeString("en-US", {
|
|
41670
|
+
hour: "numeric",
|
|
41671
|
+
minute: "2-digit",
|
|
41672
|
+
hour12: true,
|
|
41673
|
+
timeZone: timezone
|
|
41674
|
+
});
|
|
41675
|
+
};
|
|
41676
|
+
var formatCompactNumber = formatRedFlowCompactNumber;
|
|
41677
|
+
var formatTooltipSeconds = (value) => `${Math.round(value)}s`;
|
|
41678
|
+
var formatEfficiencyPercent = (value) => {
|
|
41679
|
+
if (typeof value !== "number" || !Number.isFinite(value)) {
|
|
41680
|
+
return "No output data";
|
|
41681
|
+
}
|
|
41682
|
+
return `${Math.round(value)}% efficient`;
|
|
41683
|
+
};
|
|
41684
|
+
var getBinOutputUnits = getRedFlowBinOutputUnits;
|
|
41685
|
+
var formatOutputLabel = (bin) => {
|
|
41686
|
+
const actualOutput = getBinOutputUnits(bin);
|
|
41687
|
+
if (actualOutput === null) {
|
|
41688
|
+
return "";
|
|
41689
|
+
}
|
|
41690
|
+
return `Output ${formatCompactNumber(actualOutput)}`;
|
|
41691
|
+
};
|
|
41529
41692
|
var VideoControls = ({
|
|
41530
41693
|
isPlaying,
|
|
41531
41694
|
currentTime,
|
|
@@ -41544,15 +41707,20 @@ var VideoControls = ({
|
|
|
41544
41707
|
onShare,
|
|
41545
41708
|
isShareLoading = false,
|
|
41546
41709
|
isShareCopied = false,
|
|
41710
|
+
timelineAnnotations,
|
|
41711
|
+
timelineExplanation,
|
|
41712
|
+
timelineTimezone,
|
|
41547
41713
|
className = ""
|
|
41548
41714
|
}) => {
|
|
41549
41715
|
const [isDragging2, setIsDragging] = useState(false);
|
|
41550
41716
|
const [dragTime, setDragTime] = useState(0);
|
|
41551
41717
|
const [isHoveringProgressBar, setIsHoveringProgressBar] = useState(false);
|
|
41718
|
+
const [hoveredTimelineBin, setHoveredTimelineBin] = useState(null);
|
|
41552
41719
|
const [showSpeedMenu, setShowSpeedMenu] = useState(false);
|
|
41553
41720
|
const speedMenuRef = useRef(null);
|
|
41554
41721
|
const progressTrackRef = useRef(null);
|
|
41555
41722
|
const activePointerIdRef = useRef(null);
|
|
41723
|
+
const markerPointerJumpHandledRef = useRef(false);
|
|
41556
41724
|
const progressColor = "#4b5563";
|
|
41557
41725
|
const controlsVisible = showControls || controlsPinned;
|
|
41558
41726
|
const isDraggingRef = useRef(false);
|
|
@@ -41576,6 +41744,43 @@ var VideoControls = ({
|
|
|
41576
41744
|
isDraggingRef.current = false;
|
|
41577
41745
|
onSeekEnd?.();
|
|
41578
41746
|
};
|
|
41747
|
+
const handleTimelineJump = useCallback((time2) => {
|
|
41748
|
+
const nextTime = Math.min(Math.max(time2, 0), duration || time2);
|
|
41749
|
+
const wasDragging = isDraggingRef.current;
|
|
41750
|
+
activePointerIdRef.current = null;
|
|
41751
|
+
setIsDragging(false);
|
|
41752
|
+
isDraggingRef.current = false;
|
|
41753
|
+
setDragTime(nextTime);
|
|
41754
|
+
if (!wasDragging) {
|
|
41755
|
+
onSeekStart?.();
|
|
41756
|
+
}
|
|
41757
|
+
onSeek(nextTime);
|
|
41758
|
+
onSeekEnd?.();
|
|
41759
|
+
}, [duration, onSeek, onSeekEnd, onSeekStart]);
|
|
41760
|
+
const handleTimelineMarkerPointerDown = useCallback((e, time2) => {
|
|
41761
|
+
e.preventDefault();
|
|
41762
|
+
e.stopPropagation();
|
|
41763
|
+
markerPointerJumpHandledRef.current = true;
|
|
41764
|
+
handleTimelineJump(time2);
|
|
41765
|
+
}, [handleTimelineJump]);
|
|
41766
|
+
const handleTimelineMarkerMouseDown = useCallback((e, time2) => {
|
|
41767
|
+
e.preventDefault();
|
|
41768
|
+
e.stopPropagation();
|
|
41769
|
+
if (markerPointerJumpHandledRef.current) {
|
|
41770
|
+
return;
|
|
41771
|
+
}
|
|
41772
|
+
markerPointerJumpHandledRef.current = true;
|
|
41773
|
+
handleTimelineJump(time2);
|
|
41774
|
+
}, [handleTimelineJump]);
|
|
41775
|
+
const handleTimelineMarkerClick = useCallback((e, time2) => {
|
|
41776
|
+
e.preventDefault();
|
|
41777
|
+
e.stopPropagation();
|
|
41778
|
+
if (markerPointerJumpHandledRef.current) {
|
|
41779
|
+
markerPointerJumpHandledRef.current = false;
|
|
41780
|
+
return;
|
|
41781
|
+
}
|
|
41782
|
+
handleTimelineJump(time2);
|
|
41783
|
+
}, [handleTimelineJump]);
|
|
41579
41784
|
const updateTimeFromClientX = useCallback((clientX) => {
|
|
41580
41785
|
if (!progressTrackRef.current) return;
|
|
41581
41786
|
const rect = progressTrackRef.current.getBoundingClientRect();
|
|
@@ -41636,6 +41841,127 @@ var VideoControls = ({
|
|
|
41636
41841
|
const displayTime = isDragging2 ? dragTime : currentTime;
|
|
41637
41842
|
const progressPercent = getPercentage(displayTime, duration);
|
|
41638
41843
|
const bufferedPercent = getPercentage(buffered, duration);
|
|
41844
|
+
const timelineBins = useMemo(() => {
|
|
41845
|
+
if (!timelineAnnotations?.minute_bins?.length || duration <= 0) {
|
|
41846
|
+
return [];
|
|
41847
|
+
}
|
|
41848
|
+
return timelineAnnotations.minute_bins.map((bin) => {
|
|
41849
|
+
const offset = typeof bin.offset_seconds === "number" && Number.isFinite(bin.offset_seconds) ? Math.max(0, bin.offset_seconds) : 0;
|
|
41850
|
+
const binDuration = typeof bin.duration_seconds === "number" && Number.isFinite(bin.duration_seconds) && bin.duration_seconds > 0 ? bin.duration_seconds : 60;
|
|
41851
|
+
if (offset >= duration) {
|
|
41852
|
+
return null;
|
|
41853
|
+
}
|
|
41854
|
+
const clampedDuration = Math.min(binDuration, Math.max(0, duration - offset));
|
|
41855
|
+
if (clampedDuration <= 0) {
|
|
41856
|
+
return null;
|
|
41857
|
+
}
|
|
41858
|
+
const clockLabel = formatTimelineClockTime(bin.start_time, timelineTimezone);
|
|
41859
|
+
const minuteExplanation = timelineExplanation?.minute_explanations?.find((explanation) => explanation.offset_seconds === offset || Boolean(explanation.start_time) && explanation.start_time === bin.start_time);
|
|
41860
|
+
const explanationLabel = minuteExplanation && minuteExplanation.confidence !== "low" ? minuteExplanation.primary_driver === "idle" ? "High Idle Detected" : minuteExplanation.primary_driver === "micro_stoppage" ? `Gap: ${Math.round(minuteExplanation.micro_stoppage_lost_seconds)}s lost` : minuteExplanation.primary_driver === "slow_cycle" ? typeof minuteExplanation.actual_cycle_time_seconds === "number" && Number.isFinite(minuteExplanation.actual_cycle_time_seconds) && typeof minuteExplanation.median_cycle_time_seconds === "number" && Number.isFinite(minuteExplanation.median_cycle_time_seconds) ? `Avg Cycle Time: ${formatTooltipSeconds(minuteExplanation.actual_cycle_time_seconds)} vs Shift Avg: ${formatTooltipSeconds(minuteExplanation.median_cycle_time_seconds)}` : `Slow cycle: ${Math.round(minuteExplanation.slow_cycle_lost_seconds)}s lost` : minuteExplanation.primary_driver === "low_output" ? "Low Output" : void 0 : void 0;
|
|
41861
|
+
return {
|
|
41862
|
+
...bin,
|
|
41863
|
+
offset_seconds: offset,
|
|
41864
|
+
duration_seconds: clampedDuration,
|
|
41865
|
+
leftPercent: getPercentage(offset, duration),
|
|
41866
|
+
widthPercent: Math.max(getPercentage(clampedDuration, duration), 0.4),
|
|
41867
|
+
clockLabel,
|
|
41868
|
+
efficiencyLabel: formatEfficiencyPercent(bin.efficiency_percent),
|
|
41869
|
+
outputLabel: formatOutputLabel({ ...bin, duration_seconds: clampedDuration }),
|
|
41870
|
+
explanationLabel
|
|
41871
|
+
};
|
|
41872
|
+
}).filter((bin) => Boolean(bin));
|
|
41873
|
+
}, [duration, timelineAnnotations, timelineExplanation, timelineTimezone]);
|
|
41874
|
+
const hasTimelineAnnotations = timelineBins.length > 0;
|
|
41875
|
+
const worstMinuteMarkers = useMemo(() => {
|
|
41876
|
+
const efficiencySource = timelineBins.filter((bin) => typeof bin.efficiency_percent === "number" && Number.isFinite(bin.efficiency_percent)).slice().sort((a, b) => a.efficiency_percent - b.efficiency_percent || a.offset_seconds - b.offset_seconds).slice(0, 3).map((bin, index) => ({
|
|
41877
|
+
start_time: bin.start_time,
|
|
41878
|
+
offset_seconds: bin.offset_seconds,
|
|
41879
|
+
duration_seconds: bin.duration_seconds,
|
|
41880
|
+
avg_flow_percent: bin.avg_flow_percent,
|
|
41881
|
+
rank: index + 1
|
|
41882
|
+
}));
|
|
41883
|
+
const source = efficiencySource.length ? efficiencySource : timelineAnnotations?.worst_minutes?.length ? timelineAnnotations.worst_minutes : timelineBins.filter((bin) => typeof bin.avg_flow_percent === "number" && Number.isFinite(bin.avg_flow_percent)).sort((a, b) => a.avg_flow_percent - b.avg_flow_percent).slice(0, 3);
|
|
41884
|
+
return source.filter((marker) => typeof marker.offset_seconds === "number" && Number.isFinite(marker.offset_seconds)).slice(0, 3).map((marker, index) => {
|
|
41885
|
+
const offset = Math.max(0, Math.min(duration, marker.offset_seconds));
|
|
41886
|
+
const matchingBin = timelineBins.find((bin) => bin.offset_seconds === marker.offset_seconds || Boolean(marker.start_time) && bin.start_time === marker.start_time);
|
|
41887
|
+
const markerDuration = "duration_seconds" in marker ? Number(marker.duration_seconds || 0) : 0;
|
|
41888
|
+
const width = markerDuration > 0 ? markerDuration : Number(matchingBin?.duration_seconds || 0);
|
|
41889
|
+
const centerOffset = Math.min(duration, offset + Math.max(0, width) / 2);
|
|
41890
|
+
return {
|
|
41891
|
+
...marker,
|
|
41892
|
+
rank: "rank" in marker ? marker.rank : index + 1,
|
|
41893
|
+
leftPercent: getPercentage(centerOffset, duration)
|
|
41894
|
+
};
|
|
41895
|
+
});
|
|
41896
|
+
}, [duration, timelineAnnotations, timelineBins]);
|
|
41897
|
+
const transitionMarkers = useMemo(() => {
|
|
41898
|
+
if (timelineBins.length < 2 || duration <= 0) {
|
|
41899
|
+
return [];
|
|
41900
|
+
}
|
|
41901
|
+
const orderedBins = timelineBins.slice().sort((left, right) => left.offset_seconds - right.offset_seconds);
|
|
41902
|
+
return orderedBins.slice(1).map((bin, index) => {
|
|
41903
|
+
const previousBin = orderedBins[index];
|
|
41904
|
+
const fromOutputUnits = getBinOutputUnits(previousBin);
|
|
41905
|
+
const toOutputUnits = getBinOutputUnits(bin);
|
|
41906
|
+
const hasOutputValues = fromOutputUnits !== null && toOutputUnits !== null && fromOutputUnits > 0;
|
|
41907
|
+
const fromEfficiency = previousBin.efficiency_percent;
|
|
41908
|
+
const toEfficiency = bin.efficiency_percent;
|
|
41909
|
+
const hasEfficiencyValues = typeof fromEfficiency === "number" && typeof toEfficiency === "number" && Number.isFinite(fromEfficiency) && Number.isFinite(toEfficiency) && fromEfficiency > 0;
|
|
41910
|
+
if (!hasOutputValues && !hasEfficiencyValues) {
|
|
41911
|
+
return null;
|
|
41912
|
+
}
|
|
41913
|
+
const fromValue = hasOutputValues ? fromOutputUnits : fromEfficiency;
|
|
41914
|
+
const toValue2 = hasOutputValues ? toOutputUnits : toEfficiency;
|
|
41915
|
+
const relativeDrop = (fromValue - toValue2) / fromValue;
|
|
41916
|
+
if (relativeDrop <= 0.5) {
|
|
41917
|
+
return null;
|
|
41918
|
+
}
|
|
41919
|
+
const transitionOffset = Math.min(Math.max(bin.offset_seconds, 0), duration);
|
|
41920
|
+
return {
|
|
41921
|
+
offsetSeconds: transitionOffset,
|
|
41922
|
+
leftPercent: getPercentage(transitionOffset, duration),
|
|
41923
|
+
fromValue,
|
|
41924
|
+
toValue: toValue2,
|
|
41925
|
+
relativeDrop,
|
|
41926
|
+
fromOutputUnits,
|
|
41927
|
+
toOutputUnits,
|
|
41928
|
+
source: hasOutputValues ? "output" : "efficiency",
|
|
41929
|
+
absoluteDrop: fromValue - toValue2
|
|
41930
|
+
};
|
|
41931
|
+
}).filter((marker) => Boolean(marker)).sort((left, right) => {
|
|
41932
|
+
const relativeDiff = right.relativeDrop - left.relativeDrop;
|
|
41933
|
+
if (relativeDiff !== 0) {
|
|
41934
|
+
return relativeDiff;
|
|
41935
|
+
}
|
|
41936
|
+
const outputDiff = right.absoluteDrop - left.absoluteDrop;
|
|
41937
|
+
if (outputDiff !== 0) {
|
|
41938
|
+
return outputDiff;
|
|
41939
|
+
}
|
|
41940
|
+
return left.offsetSeconds - right.offsetSeconds;
|
|
41941
|
+
}).slice(0, 3).map((marker, index) => ({
|
|
41942
|
+
...marker,
|
|
41943
|
+
rank: index + 1
|
|
41944
|
+
}));
|
|
41945
|
+
}, [duration, timelineBins]);
|
|
41946
|
+
worstMinuteMarkers[0] || null;
|
|
41947
|
+
const updateHoveredTimelineBin = useCallback((clientX) => {
|
|
41948
|
+
if (!hasTimelineAnnotations || !progressTrackRef.current || duration <= 0) {
|
|
41949
|
+
setHoveredTimelineBin(null);
|
|
41950
|
+
return;
|
|
41951
|
+
}
|
|
41952
|
+
const rect = progressTrackRef.current.getBoundingClientRect();
|
|
41953
|
+
if (!rect.width) {
|
|
41954
|
+
setHoveredTimelineBin(null);
|
|
41955
|
+
return;
|
|
41956
|
+
}
|
|
41957
|
+
const pct = Math.min(Math.max((clientX - rect.left) / rect.width, 0), 1);
|
|
41958
|
+
const hoverTime = pct * duration;
|
|
41959
|
+
const nextBin = timelineBins.find((bin) => hoverTime >= bin.offset_seconds && hoverTime <= bin.offset_seconds + bin.duration_seconds) || null;
|
|
41960
|
+
setHoveredTimelineBin(nextBin);
|
|
41961
|
+
}, [duration, hasTimelineAnnotations, timelineBins]);
|
|
41962
|
+
const handleProgressMouseMove = useCallback((e) => {
|
|
41963
|
+
updateHoveredTimelineBin(e.clientX);
|
|
41964
|
+
}, [updateHoveredTimelineBin]);
|
|
41639
41965
|
return /* @__PURE__ */ jsxs(
|
|
41640
41966
|
"div",
|
|
41641
41967
|
{
|
|
@@ -41647,12 +41973,16 @@ var VideoControls = ({
|
|
|
41647
41973
|
"div",
|
|
41648
41974
|
{
|
|
41649
41975
|
ref: progressTrackRef,
|
|
41650
|
-
className: "relative h-1 mb-4 group cursor-pointer",
|
|
41976
|
+
className: "relative z-10 h-1 mb-4 group cursor-pointer",
|
|
41651
41977
|
onMouseEnter: () => setIsHoveringProgressBar(true),
|
|
41652
|
-
|
|
41978
|
+
onMouseMove: handleProgressMouseMove,
|
|
41979
|
+
onMouseLeave: () => {
|
|
41980
|
+
setIsHoveringProgressBar(false);
|
|
41981
|
+
setHoveredTimelineBin(null);
|
|
41982
|
+
},
|
|
41653
41983
|
onPointerDown: handlePointerDown,
|
|
41654
41984
|
children: [
|
|
41655
|
-
/* @__PURE__ */ jsx("div", { className: "absolute -top-4
|
|
41985
|
+
/* @__PURE__ */ jsx("div", { className: "absolute -top-4 bottom-0 left-0 right-0 z-20" }),
|
|
41656
41986
|
/* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 bottom-0 bg-white/20 rounded-full overflow-hidden z-0", children: /* @__PURE__ */ jsx(
|
|
41657
41987
|
"div",
|
|
41658
41988
|
{
|
|
@@ -41686,17 +42016,47 @@ var VideoControls = ({
|
|
|
41686
42016
|
onInput: handleSeekChange,
|
|
41687
42017
|
onMouseDown: handleSeekStart,
|
|
41688
42018
|
onMouseUp: handleSeekEnd,
|
|
42019
|
+
onMouseMove: handleProgressMouseMove,
|
|
41689
42020
|
onTouchStart: handleSeekStart,
|
|
41690
42021
|
onTouchEnd: handleSeekEnd,
|
|
41691
42022
|
onPointerDown: handlePointerDown,
|
|
41692
|
-
className: "absolute left-0 right-0 top-[-12px] bottom-
|
|
42023
|
+
className: "absolute left-0 right-0 top-[-12px] bottom-0 w-full h-auto opacity-0 cursor-pointer z-30 margin-0 padding-0"
|
|
42024
|
+
}
|
|
42025
|
+
),
|
|
42026
|
+
hasTimelineAnnotations && transitionMarkers.map((marker) => /* @__PURE__ */ jsx(
|
|
42027
|
+
"button",
|
|
42028
|
+
{
|
|
42029
|
+
type: "button",
|
|
42030
|
+
"aria-label": marker.source === "output" ? `Output drop marker ${marker.rank}: output ${formatCompactNumber(marker.fromValue)} to ${formatCompactNumber(marker.toValue)} (${Math.round(marker.relativeDrop * 100)}% drop)` : `Output drop marker ${marker.rank}: efficiency ${Math.round(marker.fromValue)}% to ${Math.round(marker.toValue)}% (${Math.round(marker.relativeDrop * 100)}% drop)`,
|
|
42031
|
+
title: marker.source === "output" ? `Output drop: ${formatCompactNumber(marker.fromValue)} to ${formatCompactNumber(marker.toValue)}` : `Output drop: ${Math.round(marker.fromValue)}% to ${Math.round(marker.toValue)}%`,
|
|
42032
|
+
onPointerDownCapture: (e) => handleTimelineMarkerPointerDown(e, marker.offsetSeconds),
|
|
42033
|
+
onMouseDownCapture: (e) => handleTimelineMarkerMouseDown(e, marker.offsetSeconds),
|
|
42034
|
+
onClickCapture: (e) => handleTimelineMarkerClick(e, marker.offsetSeconds),
|
|
42035
|
+
className: "absolute top-1/2 -translate-y-1/2 z-[70] flex h-5 w-5 cursor-pointer items-center justify-center rounded-full border border-white bg-sky-500 p-0 text-center text-[9px] font-bold leading-none text-white shadow hover:bg-sky-400 focus:outline-none focus:ring-2 focus:ring-sky-200",
|
|
42036
|
+
style: { left: `calc(${marker.leftPercent}% - 10px)`, zIndex: 70, pointerEvents: "auto" },
|
|
42037
|
+
children: marker.rank
|
|
42038
|
+
},
|
|
42039
|
+
`${marker.rank}-${marker.offsetSeconds}`
|
|
42040
|
+
)),
|
|
42041
|
+
hasTimelineAnnotations && hoveredTimelineBin && /* @__PURE__ */ jsxs(
|
|
42042
|
+
"div",
|
|
42043
|
+
{
|
|
42044
|
+
className: "absolute bottom-full z-50 mb-2 -translate-x-1/2 rounded bg-slate-900 px-2 py-1 text-[11px] font-semibold text-white shadow-lg",
|
|
42045
|
+
style: { left: `${hoveredTimelineBin.leftPercent + hoveredTimelineBin.widthPercent / 2}%` },
|
|
42046
|
+
children: [
|
|
42047
|
+
hoveredTimelineBin.clockLabel || formatTime2(hoveredTimelineBin.offset_seconds),
|
|
42048
|
+
" | ",
|
|
42049
|
+
hoveredTimelineBin.efficiencyLabel,
|
|
42050
|
+
hoveredTimelineBin.outputLabel ? ` | ${hoveredTimelineBin.outputLabel}` : "",
|
|
42051
|
+
hoveredTimelineBin.explanationLabel ? ` | ${hoveredTimelineBin.explanationLabel}` : ""
|
|
42052
|
+
]
|
|
41693
42053
|
}
|
|
41694
42054
|
)
|
|
41695
42055
|
]
|
|
41696
42056
|
}
|
|
41697
42057
|
),
|
|
41698
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
|
|
41699
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
42058
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-40 flex items-center justify-between text-white", children: [
|
|
42059
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-50 flex items-center gap-4", children: [
|
|
41700
42060
|
/* @__PURE__ */ jsx(
|
|
41701
42061
|
"button",
|
|
41702
42062
|
{
|
|
@@ -41977,7 +42337,10 @@ var HlsVideoPlayer = forwardRef(({
|
|
|
41977
42337
|
onClick,
|
|
41978
42338
|
onShare,
|
|
41979
42339
|
isShareLoading,
|
|
41980
|
-
isShareCopied
|
|
42340
|
+
isShareCopied,
|
|
42341
|
+
timelineAnnotations,
|
|
42342
|
+
timelineExplanation,
|
|
42343
|
+
timelineTimezone
|
|
41981
42344
|
}, ref) => {
|
|
41982
42345
|
const supabase = useSupabase();
|
|
41983
42346
|
const videoContainerRef = useRef(null);
|
|
@@ -42639,6 +43002,7 @@ var HlsVideoPlayer = forwardRef(({
|
|
|
42639
43002
|
const handleSeek = useCallback((time2) => {
|
|
42640
43003
|
if (videoRef.current) {
|
|
42641
43004
|
videoRef.current.currentTime = time2;
|
|
43005
|
+
setCurrentTime(time2);
|
|
42642
43006
|
}
|
|
42643
43007
|
}, []);
|
|
42644
43008
|
const handleSeekStart = useCallback(() => {
|
|
@@ -42745,7 +43109,10 @@ var HlsVideoPlayer = forwardRef(({
|
|
|
42745
43109
|
onToggleFullscreen: handleToggleFullscreen,
|
|
42746
43110
|
onShare,
|
|
42747
43111
|
isShareLoading,
|
|
42748
|
-
isShareCopied
|
|
43112
|
+
isShareCopied,
|
|
43113
|
+
timelineAnnotations,
|
|
43114
|
+
timelineExplanation,
|
|
43115
|
+
timelineTimezone
|
|
42749
43116
|
}
|
|
42750
43117
|
)
|
|
42751
43118
|
]
|
|
@@ -43066,6 +43433,7 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
43066
43433
|
const handleSeek = useCallback((time2) => {
|
|
43067
43434
|
if (hiddenVideoRef.current) {
|
|
43068
43435
|
hiddenVideoRef.current.currentTime(time2);
|
|
43436
|
+
setCurrentTime(time2);
|
|
43069
43437
|
setTimeout(() => renderFrameToCanvas(), 50);
|
|
43070
43438
|
userSeekingRef.current = true;
|
|
43071
43439
|
}
|
|
@@ -43211,7 +43579,10 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
43211
43579
|
onToggleFullscreen: handleToggleFullscreen,
|
|
43212
43580
|
onShare: videoProps.onShare,
|
|
43213
43581
|
isShareLoading: videoProps.isShareLoading,
|
|
43214
|
-
isShareCopied: videoProps.isShareCopied
|
|
43582
|
+
isShareCopied: videoProps.isShareCopied,
|
|
43583
|
+
timelineAnnotations: videoProps.timelineAnnotations,
|
|
43584
|
+
timelineExplanation: videoProps.timelineExplanation,
|
|
43585
|
+
timelineTimezone: videoProps.timelineTimezone
|
|
43215
43586
|
}
|
|
43216
43587
|
)
|
|
43217
43588
|
]
|
|
@@ -43220,6 +43591,100 @@ var CroppedHlsVideoPlayer = forwardRef(({
|
|
|
43220
43591
|
});
|
|
43221
43592
|
CroppedHlsVideoPlayer.displayName = "CroppedHlsVideoPlayer";
|
|
43222
43593
|
var CroppedVideoPlayer = CroppedHlsVideoPlayer;
|
|
43594
|
+
var formatSeconds = (value) => {
|
|
43595
|
+
const seconds = Math.max(0, Math.round(value));
|
|
43596
|
+
if (seconds < 60) {
|
|
43597
|
+
return `${seconds}s`;
|
|
43598
|
+
}
|
|
43599
|
+
const minutes = Math.floor(seconds / 60);
|
|
43600
|
+
const remainingSeconds = seconds % 60;
|
|
43601
|
+
return remainingSeconds > 0 ? `${minutes}m ${remainingSeconds}s` : `${minutes}m`;
|
|
43602
|
+
};
|
|
43603
|
+
var buildLostChip = (explanation) => {
|
|
43604
|
+
const totals = explanation.summary.totals;
|
|
43605
|
+
const explicitTotalLostSeconds = Number(totals.total_lost_seconds);
|
|
43606
|
+
const lostSeconds = Number.isFinite(explicitTotalLostSeconds) ? explicitTotalLostSeconds : Math.max(
|
|
43607
|
+
Number(totals.idle_overlap_seconds) || 0,
|
|
43608
|
+
Number(totals.micro_stoppage_lost_seconds) || 0,
|
|
43609
|
+
Number(totals.slow_cycle_lost_seconds) || 0
|
|
43610
|
+
);
|
|
43611
|
+
if (lostSeconds > 0) {
|
|
43612
|
+
return `${formatSeconds(lostSeconds)} lost`;
|
|
43613
|
+
}
|
|
43614
|
+
if (Number(totals.idle_overlap_percent) > 0) {
|
|
43615
|
+
return `${Math.round(totals.idle_overlap_percent)}% idle`;
|
|
43616
|
+
}
|
|
43617
|
+
return null;
|
|
43618
|
+
};
|
|
43619
|
+
var RedFlowDiagnosticOverlay = ({
|
|
43620
|
+
timeline,
|
|
43621
|
+
explanation,
|
|
43622
|
+
aiSummary,
|
|
43623
|
+
aiSummaryLoading = false,
|
|
43624
|
+
aiSummaryError = null,
|
|
43625
|
+
className = ""
|
|
43626
|
+
}) => {
|
|
43627
|
+
const summary = explanation?.summary || null;
|
|
43628
|
+
const driverKeys = useMemo(() => getRedFlowDisplayDriverKeys(summary), [summary]);
|
|
43629
|
+
const outputSummary = useMemo(() => summarizeRedFlowOutput(timeline, summary), [summary, timeline]);
|
|
43630
|
+
const hasOutputIssue = Boolean(
|
|
43631
|
+
outputSummary && Number.isFinite(outputSummary.expected) && Number.isFinite(outputSummary.actual) && outputSummary.expected > outputSummary.actual
|
|
43632
|
+
);
|
|
43633
|
+
if (driverKeys.length === 0 && !hasOutputIssue) {
|
|
43634
|
+
return null;
|
|
43635
|
+
}
|
|
43636
|
+
const driverLabel = driverKeys.length > 0 ? driverKeys.map(getRedFlowDriverLabel).filter(Boolean).join(" + ") : "Low Output";
|
|
43637
|
+
if (!driverLabel) {
|
|
43638
|
+
return null;
|
|
43639
|
+
}
|
|
43640
|
+
const shouldShowLostChip = driverKeys.some((driver) => driver !== "low_output");
|
|
43641
|
+
const chips = explanation && shouldShowLostChip ? [buildLostChip(explanation)].filter((chip) => Boolean(chip)) : [];
|
|
43642
|
+
const shouldShowHeadline = Boolean(summary && driverKeys.length > 0 && summary.primary_driver !== "unknown");
|
|
43643
|
+
const aiSummaryBullets = Array.isArray(aiSummary?.bullets) ? aiSummary.bullets.map((bullet) => String(bullet || "").trim()).filter(Boolean).slice(0, 3) : [];
|
|
43644
|
+
const shouldShowAiSummary = !aiSummaryError && aiSummaryBullets.length === 3;
|
|
43645
|
+
return /* @__PURE__ */ jsxs(
|
|
43646
|
+
"div",
|
|
43647
|
+
{
|
|
43648
|
+
className: `pointer-events-none absolute z-20 w-[240px] max-w-[calc(100%-2rem)] rounded-xl border border-white/10 bg-black/60 p-5 text-white shadow-xl backdrop-blur-md ${className}`,
|
|
43649
|
+
children: [
|
|
43650
|
+
outputSummary ? /* @__PURE__ */ jsxs("div", { className: "mb-5 space-y-4", children: [
|
|
43651
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
43652
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/50", children: "Output:" }),
|
|
43653
|
+
/* @__PURE__ */ jsxs("span", { className: "text-sm font-bold text-white", children: [
|
|
43654
|
+
/* @__PURE__ */ jsx("span", { className: "text-red-400", children: formatRedFlowOutputCount(outputSummary.actual) }),
|
|
43655
|
+
/* @__PURE__ */ jsx("span", { className: "px-1 text-white/30", children: "/" }),
|
|
43656
|
+
formatRedFlowOutputCount(outputSummary.expected)
|
|
43657
|
+
] })
|
|
43658
|
+
] }),
|
|
43659
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
43660
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-white/50", children: "Reason:" }),
|
|
43661
|
+
/* @__PURE__ */ jsx("span", { className: "rounded bg-red-500/10 px-2 py-1 text-[10px] font-semibold tracking-wide text-red-400 ring-1 ring-inset ring-red-500/20", children: "Low output" })
|
|
43662
|
+
] })
|
|
43663
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "mb-4 flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { className: "rounded bg-red-500/10 px-2 py-1 text-[10px] font-semibold tracking-wide text-red-400 ring-1 ring-inset ring-red-500/20", children: driverLabel }) }),
|
|
43664
|
+
(shouldShowAiSummary || aiSummaryLoading || chips.length > 0 || shouldShowHeadline) && /* @__PURE__ */ jsx("div", { className: "mb-4 h-px w-full bg-white/10" }),
|
|
43665
|
+
!shouldShowAiSummary && !aiSummaryLoading && shouldShowHeadline && summary?.headline ? /* @__PURE__ */ jsx("div", { className: "mb-3 text-[13px] font-medium leading-relaxed text-white/90", children: summary.headline }) : null,
|
|
43666
|
+
!shouldShowAiSummary && !aiSummaryLoading && chips.length > 0 ? /* @__PURE__ */ jsx("div", { className: "mb-3 flex flex-wrap gap-2", children: chips.slice(0, 3).map((chip) => /* @__PURE__ */ jsx(
|
|
43667
|
+
"span",
|
|
43668
|
+
{
|
|
43669
|
+
className: "rounded border border-white/10 bg-white/5 px-2 py-0.5 text-[11px] font-medium text-white/70",
|
|
43670
|
+
children: chip
|
|
43671
|
+
},
|
|
43672
|
+
chip
|
|
43673
|
+
)) }) : null,
|
|
43674
|
+
shouldShowAiSummary ? /* @__PURE__ */ jsxs("div", { className: "mt-1", children: [
|
|
43675
|
+
/* @__PURE__ */ jsx("div", { className: "mb-3 text-[10px] font-bold uppercase tracking-[0.15em] text-white/40", children: "AI summary" }),
|
|
43676
|
+
/* @__PURE__ */ jsx("ol", { className: "space-y-3 text-[12px] leading-relaxed text-white/80", children: aiSummaryBullets.map((bullet, index) => /* @__PURE__ */ jsxs("li", { className: "flex gap-2", children: [
|
|
43677
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-white/40", children: [
|
|
43678
|
+
index + 1,
|
|
43679
|
+
"."
|
|
43680
|
+
] }),
|
|
43681
|
+
/* @__PURE__ */ jsx("span", { children: bullet })
|
|
43682
|
+
] }, `${index}-${bullet}`)) })
|
|
43683
|
+
] }) : aiSummaryLoading ? /* @__PURE__ */ jsx("div", { className: "mt-1 text-[13px] font-medium text-white/60", children: "Generating summary..." }) : null
|
|
43684
|
+
]
|
|
43685
|
+
}
|
|
43686
|
+
);
|
|
43687
|
+
};
|
|
43223
43688
|
function useWorkspaceCrop(workspaceId) {
|
|
43224
43689
|
const supabase = useSupabase();
|
|
43225
43690
|
const [crop, setCrop] = useState(null);
|
|
@@ -43269,7 +43734,7 @@ function Skeleton({ className, ...props }) {
|
|
|
43269
43734
|
var Select = SelectPrimitive.Root;
|
|
43270
43735
|
var SelectGroup = SelectPrimitive.Group;
|
|
43271
43736
|
var SelectValue = SelectPrimitive.Value;
|
|
43272
|
-
var SelectTrigger =
|
|
43737
|
+
var SelectTrigger = React148.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
43273
43738
|
SelectPrimitive.Trigger,
|
|
43274
43739
|
{
|
|
43275
43740
|
ref,
|
|
@@ -43285,7 +43750,7 @@ var SelectTrigger = React147.forwardRef(({ className, children, ...props }, ref)
|
|
|
43285
43750
|
}
|
|
43286
43751
|
));
|
|
43287
43752
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
43288
|
-
var SelectScrollUpButton =
|
|
43753
|
+
var SelectScrollUpButton = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
43289
43754
|
SelectPrimitive.ScrollUpButton,
|
|
43290
43755
|
{
|
|
43291
43756
|
ref,
|
|
@@ -43295,7 +43760,7 @@ var SelectScrollUpButton = React147.forwardRef(({ className, ...props }, ref) =>
|
|
|
43295
43760
|
}
|
|
43296
43761
|
));
|
|
43297
43762
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
43298
|
-
var SelectScrollDownButton =
|
|
43763
|
+
var SelectScrollDownButton = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
43299
43764
|
SelectPrimitive.ScrollDownButton,
|
|
43300
43765
|
{
|
|
43301
43766
|
ref,
|
|
@@ -43305,7 +43770,7 @@ var SelectScrollDownButton = React147.forwardRef(({ className, ...props }, ref)
|
|
|
43305
43770
|
}
|
|
43306
43771
|
));
|
|
43307
43772
|
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
43308
|
-
var SelectContent =
|
|
43773
|
+
var SelectContent = React148.forwardRef(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
43309
43774
|
SelectPrimitive.Content,
|
|
43310
43775
|
{
|
|
43311
43776
|
ref,
|
|
@@ -43333,7 +43798,7 @@ var SelectContent = React147.forwardRef(({ className, children, position = "popp
|
|
|
43333
43798
|
}
|
|
43334
43799
|
) }));
|
|
43335
43800
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
43336
|
-
var SelectLabel =
|
|
43801
|
+
var SelectLabel = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
43337
43802
|
SelectPrimitive.Label,
|
|
43338
43803
|
{
|
|
43339
43804
|
ref,
|
|
@@ -43342,7 +43807,7 @@ var SelectLabel = React147.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
43342
43807
|
}
|
|
43343
43808
|
));
|
|
43344
43809
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
43345
|
-
var SelectItem =
|
|
43810
|
+
var SelectItem = React148.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
43346
43811
|
SelectPrimitive.Item,
|
|
43347
43812
|
{
|
|
43348
43813
|
ref,
|
|
@@ -43358,7 +43823,7 @@ var SelectItem = React147.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
43358
43823
|
}
|
|
43359
43824
|
));
|
|
43360
43825
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
43361
|
-
var SelectSeparator =
|
|
43826
|
+
var SelectSeparator = React148.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
43362
43827
|
SelectPrimitive.Separator,
|
|
43363
43828
|
{
|
|
43364
43829
|
ref,
|
|
@@ -43984,7 +44449,7 @@ var TimePickerDropdown = ({
|
|
|
43984
44449
|
)
|
|
43985
44450
|
] });
|
|
43986
44451
|
};
|
|
43987
|
-
var SilentErrorBoundary = class extends
|
|
44452
|
+
var SilentErrorBoundary = class extends React148__default.Component {
|
|
43988
44453
|
constructor(props) {
|
|
43989
44454
|
super(props);
|
|
43990
44455
|
this.handleClearAndReload = () => {
|
|
@@ -44729,6 +45194,9 @@ var AvatarUpload = ({
|
|
|
44729
45194
|
] });
|
|
44730
45195
|
};
|
|
44731
45196
|
var CLIP_METADATA_PAGE_SIZE = 50;
|
|
45197
|
+
var RECENT_FLOW_RED_STREAK_CLIP_TYPE2 = "recent_flow_red_streak";
|
|
45198
|
+
var RECENT_FLOW_RED_STREAK_DISPLAY_LABEL = "Low moments";
|
|
45199
|
+
var RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE = "Moments of low efficiency";
|
|
44732
45200
|
var parseCycleTime = (value) => {
|
|
44733
45201
|
if (typeof value === "number" && Number.isFinite(value)) {
|
|
44734
45202
|
return value;
|
|
@@ -44757,10 +45225,37 @@ var formatDurationLabel = (seconds) => {
|
|
|
44757
45225
|
}
|
|
44758
45226
|
return `${Math.round(roundedSeconds / 60)} min`;
|
|
44759
45227
|
};
|
|
45228
|
+
var sortRedFlowMetadata = (clips) => {
|
|
45229
|
+
return clips.slice().sort((left, right) => {
|
|
45230
|
+
const getOutputShortfall = (clip) => {
|
|
45231
|
+
const directShortfall = parseCycleTime(clip.red_flow_output_shortfall_units);
|
|
45232
|
+
if (directShortfall !== null) {
|
|
45233
|
+
return directShortfall;
|
|
45234
|
+
}
|
|
45235
|
+
return getRedFlowOutputShortfallUnits(clip.red_flow_timeline);
|
|
45236
|
+
};
|
|
45237
|
+
const leftScore = getOutputShortfall(left);
|
|
45238
|
+
const rightScore = getOutputShortfall(right);
|
|
45239
|
+
const leftNull = leftScore === null;
|
|
45240
|
+
const rightNull = rightScore === null;
|
|
45241
|
+
if (leftNull !== rightNull) {
|
|
45242
|
+
return leftNull ? 1 : -1;
|
|
45243
|
+
}
|
|
45244
|
+
if (leftScore !== null && rightScore !== null && leftScore !== rightScore) {
|
|
45245
|
+
return rightScore - leftScore;
|
|
45246
|
+
}
|
|
45247
|
+
const leftTime = new Date(left.clip_timestamp).getTime();
|
|
45248
|
+
const rightTime = new Date(right.clip_timestamp).getTime();
|
|
45249
|
+
return (Number.isFinite(rightTime) ? rightTime : 0) - (Number.isFinite(leftTime) ? leftTime : 0);
|
|
45250
|
+
});
|
|
45251
|
+
};
|
|
44760
45252
|
var getSeverityIcon = (severity, categoryId, cycleTimeSeconds, targetCycleTime, clipId) => {
|
|
44761
45253
|
if (categoryId === "idle_time" || categoryId === "low_value" || categoryId === "longest-idles") {
|
|
44762
45254
|
return null;
|
|
44763
45255
|
}
|
|
45256
|
+
if (categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
45257
|
+
return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3 w-3 text-red-500" });
|
|
45258
|
+
}
|
|
44764
45259
|
if (categoryId === "cycle_completion" && targetCycleTime && targetCycleTime > 0 && cycleTimeSeconds !== null && cycleTimeSeconds !== void 0) {
|
|
44765
45260
|
if (cycleTimeSeconds <= targetCycleTime) {
|
|
44766
45261
|
return /* @__PURE__ */ jsx(CheckCircle, { className: "h-3 w-3 text-green-500" });
|
|
@@ -44832,6 +45327,7 @@ var FileManagerFilters = ({
|
|
|
44832
45327
|
idleTimeVlmEnabled = false,
|
|
44833
45328
|
showPercentileCycleFilters = true,
|
|
44834
45329
|
prefetchedClipMetadata,
|
|
45330
|
+
externallyManagedLoadingCategories,
|
|
44835
45331
|
activeCategoryLoading,
|
|
44836
45332
|
idleClipSort = "latest",
|
|
44837
45333
|
onIdleClipSortChange,
|
|
@@ -44916,11 +45412,11 @@ var FileManagerFilters = ({
|
|
|
44916
45412
|
if (prefetchedClipMetadata && Array.isArray(prefetchedClipMetadata[categoryId]) && prefetchedClipMetadata[categoryId].length > 0) {
|
|
44917
45413
|
return true;
|
|
44918
45414
|
}
|
|
44919
|
-
if (
|
|
45415
|
+
if (externallyManagedLoadingCategories?.[categoryId]) {
|
|
44920
45416
|
return true;
|
|
44921
45417
|
}
|
|
44922
45418
|
return false;
|
|
44923
|
-
}, [prefetchedClipMetadata,
|
|
45419
|
+
}, [prefetchedClipMetadata, externallyManagedLoadingCategories]);
|
|
44924
45420
|
useEffect(() => {
|
|
44925
45421
|
if (!prefetchedClipMetadata) {
|
|
44926
45422
|
return;
|
|
@@ -45041,6 +45537,9 @@ var FileManagerFilters = ({
|
|
|
45041
45537
|
[idleReasonOptions, idleLabelFilter]
|
|
45042
45538
|
);
|
|
45043
45539
|
const getClipBadge = useCallback((node) => {
|
|
45540
|
+
if (node.categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
45541
|
+
return null;
|
|
45542
|
+
}
|
|
45044
45543
|
if (node.categoryId === "idle_time" || node.categoryId === "low_value") {
|
|
45045
45544
|
return { text: "Idle", className: "bg-red-100 text-red-700" };
|
|
45046
45545
|
}
|
|
@@ -45059,6 +45558,23 @@ var FileManagerFilters = ({
|
|
|
45059
45558
|
}
|
|
45060
45559
|
return { text: "Fast", className: "bg-green-100 text-green-700" };
|
|
45061
45560
|
}, [resolvedTargetCycleTime]);
|
|
45561
|
+
const getRedFlowDriverBadges = useCallback((node) => {
|
|
45562
|
+
if (node.categoryId !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
45563
|
+
return [];
|
|
45564
|
+
}
|
|
45565
|
+
const summary = node.redFlowExplanationSummary || null;
|
|
45566
|
+
const drivers = getRedFlowDisplayDriverKeys(summary);
|
|
45567
|
+
if (drivers.length === 0) {
|
|
45568
|
+
return [{
|
|
45569
|
+
text: "Low Output",
|
|
45570
|
+
className: "bg-slate-50 text-slate-600 border border-slate-200"
|
|
45571
|
+
}];
|
|
45572
|
+
}
|
|
45573
|
+
return drivers.slice(0, 3).map((driver) => ({
|
|
45574
|
+
text: getRedFlowDriverLabel(driver),
|
|
45575
|
+
className: "bg-rose-50 text-rose-700 border border-rose-200"
|
|
45576
|
+
}));
|
|
45577
|
+
}, []);
|
|
45062
45578
|
const getAuthToken4 = useCallback(async () => {
|
|
45063
45579
|
try {
|
|
45064
45580
|
return await getAccessTokenOrRedirect(supabase, { redirectReason: "session_expired" });
|
|
@@ -45067,7 +45583,7 @@ var FileManagerFilters = ({
|
|
|
45067
45583
|
return null;
|
|
45068
45584
|
}
|
|
45069
45585
|
}, [supabase]);
|
|
45070
|
-
const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
|
|
45586
|
+
const getMetadataLoadingKey = useCallback((categoryId, page) => `${categoryId}-${page}-${categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"}`, [idleClipSort]);
|
|
45071
45587
|
const fetchClipMetadataPage = useCallback(async (categoryId, page = 1) => {
|
|
45072
45588
|
if (!workspaceId || !date || shift === void 0) {
|
|
45073
45589
|
throw new Error("Missing required params for clip metadata fetch");
|
|
@@ -45088,7 +45604,7 @@ var FileManagerFilters = ({
|
|
|
45088
45604
|
knownTotal: typeof counts?.[categoryId] === "number" ? counts[categoryId] : null,
|
|
45089
45605
|
snapshotDateTime,
|
|
45090
45606
|
snapshotClipId,
|
|
45091
|
-
sort: categoryId === "idle_time" ? idleClipSort : "latest"
|
|
45607
|
+
sort: categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
|
|
45092
45608
|
}),
|
|
45093
45609
|
redirectReason: "session_expired"
|
|
45094
45610
|
});
|
|
@@ -45459,7 +45975,7 @@ var FileManagerFilters = ({
|
|
|
45459
45975
|
fetchClipMetadata(activeFilter, 1);
|
|
45460
45976
|
}
|
|
45461
45977
|
}
|
|
45462
|
-
}, [activeFilter
|
|
45978
|
+
}, [activeFilter]);
|
|
45463
45979
|
useEffect(() => {
|
|
45464
45980
|
const handleEscape = (e) => {
|
|
45465
45981
|
if (e.key === "Escape") {
|
|
@@ -45542,6 +46058,9 @@ var FileManagerFilters = ({
|
|
|
45542
46058
|
const categoryCount = counts?.[category.id] || 0;
|
|
45543
46059
|
const categoryClips = clipMetadata[category.id] || [];
|
|
45544
46060
|
let filteredClips = categoryClips.filter((clip) => isClipInTimeRange(clip.clip_timestamp));
|
|
46061
|
+
if (category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
46062
|
+
filteredClips = sortRedFlowMetadata(filteredClips);
|
|
46063
|
+
}
|
|
45545
46064
|
if (category.id === "idle_time" && idleLabelFilter) {
|
|
45546
46065
|
filteredClips = filteredClips.filter((clip) => {
|
|
45547
46066
|
const classification = getIdleTimeClassification(clip.clipId || clip.id);
|
|
@@ -45556,15 +46075,18 @@ var FileManagerFilters = ({
|
|
|
45556
46075
|
const cycleTime = extractCycleTimeSeconds(clip);
|
|
45557
46076
|
const idleDuration = category.id === "idle_time" ? clip.idle_duration_seconds ?? clip.duration : null;
|
|
45558
46077
|
const idleDurationLabel = formatDurationLabel(idleDuration);
|
|
46078
|
+
const redFlowDurationLabel = category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? formatDurationLabel(clip.duration) : null;
|
|
45559
46079
|
const baseTimeLabel = formatClipExplorerTimeLabel({
|
|
45560
46080
|
categoryId: category.id,
|
|
45561
46081
|
clipTimestamp: clip.clip_timestamp,
|
|
45562
46082
|
timezone,
|
|
45563
46083
|
durationSeconds: idleDuration ?? clip.duration,
|
|
45564
46084
|
idleStartTime: clip.idle_start_time,
|
|
45565
|
-
idleEndTime: clip.idle_end_time
|
|
46085
|
+
idleEndTime: clip.idle_end_time,
|
|
46086
|
+
clipStartTime: clip.clip_start_time,
|
|
46087
|
+
clipEndTime: clip.clip_end_time
|
|
45566
46088
|
});
|
|
45567
|
-
const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
|
|
46089
|
+
const displayLabel = `${baseTimeLabel}${idleDurationLabel && category.id === "idle_time" ? ` - (${idleDurationLabel})` : ""}${redFlowDurationLabel ? ` - (${redFlowDurationLabel})` : ""}${clip.duration && category.id !== "idle_time" && category.id !== "low_value" && category.id !== RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? ` - (${clip.duration.toFixed(1)}s)` : ""}`;
|
|
45568
46090
|
return {
|
|
45569
46091
|
id: clip.id,
|
|
45570
46092
|
label: displayLabel,
|
|
@@ -45580,14 +46102,18 @@ var FileManagerFilters = ({
|
|
|
45580
46102
|
cycleTimeSeconds: cycleTime,
|
|
45581
46103
|
duration: idleDuration ?? clip.duration,
|
|
45582
46104
|
// Store duration for custom badge rendering
|
|
45583
|
-
cycleItemCount: clip.cycle_item_count ?? null
|
|
46105
|
+
cycleItemCount: clip.cycle_item_count ?? null,
|
|
46106
|
+
redFlowSeverityScore: clip.red_flow_severity_score ?? null,
|
|
46107
|
+
redFlowExplanationSummary: clip.red_flow_explanation_summary ?? clip.red_flow_explanation?.summary ?? null
|
|
45584
46108
|
};
|
|
45585
46109
|
});
|
|
46110
|
+
const categoryLabel = category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_LABEL : category.label;
|
|
46111
|
+
const categorySubtitle = category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE : category.subtitle || category.description;
|
|
45586
46112
|
regularCategoryNodes.push({
|
|
45587
46113
|
id: category.id,
|
|
45588
|
-
label:
|
|
45589
|
-
subtitle:
|
|
45590
|
-
description: category.description,
|
|
46114
|
+
label: categoryLabel,
|
|
46115
|
+
subtitle: categorySubtitle,
|
|
46116
|
+
description: category.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2 ? RECENT_FLOW_RED_STREAK_DISPLAY_SUBTITLE : category.description,
|
|
45591
46117
|
type: "category",
|
|
45592
46118
|
count: displayCount,
|
|
45593
46119
|
// Use filtered count when time filter is active
|
|
@@ -45699,7 +46225,7 @@ var FileManagerFilters = ({
|
|
|
45699
46225
|
})
|
|
45700
46226
|
} */
|
|
45701
46227
|
] : [];
|
|
45702
|
-
const orderedIds = ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
46228
|
+
const orderedIds = [RECENT_FLOW_RED_STREAK_CLIP_TYPE2, "cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
45703
46229
|
orderedIds.forEach((orderedId) => {
|
|
45704
46230
|
const percentileCategory = percentileCategories.find((cat) => cat.id === orderedId);
|
|
45705
46231
|
const shouldIncludePercentile = percentileCategory ? typeof percentileCategory.count === "number" && percentileCategory.count > 0 : false;
|
|
@@ -45788,6 +46314,13 @@ var FileManagerFilters = ({
|
|
|
45788
46314
|
shift,
|
|
45789
46315
|
count: node.count || 0
|
|
45790
46316
|
});
|
|
46317
|
+
} else if (node.id === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) {
|
|
46318
|
+
trackCoreEvent("Low Moments Clicked", {
|
|
46319
|
+
workspaceId,
|
|
46320
|
+
date,
|
|
46321
|
+
shift,
|
|
46322
|
+
count: node.count || 0
|
|
46323
|
+
});
|
|
45791
46324
|
}
|
|
45792
46325
|
if (node.id !== "idle_time" && idleLabelFilter) {
|
|
45793
46326
|
setIdleLabelFilter(null);
|
|
@@ -45812,8 +46345,15 @@ var FileManagerFilters = ({
|
|
|
45812
46345
|
const isCurrentVideo = currentVideoId === node.id;
|
|
45813
46346
|
const isCountUnknown = node.type === "percentile-category" && node.count === null;
|
|
45814
46347
|
const hasChildren = isCountUnknown || (node.count || 0) > 0;
|
|
45815
|
-
const
|
|
45816
|
-
|
|
46348
|
+
const hasLoadedChildren = (clipMetadata[node.id]?.length || percentileClips[node.id]?.length || 0) > 0;
|
|
46349
|
+
const loadedPage = categoryPages[node.id] || 0;
|
|
46350
|
+
const pageOneLoadingKey = getMetadataLoadingKey(node.id, 1);
|
|
46351
|
+
const nextMetadataPage = loadedPage + 1;
|
|
46352
|
+
const nextLoadMorePage = (categoryPages[node.id] || 1) + 1;
|
|
46353
|
+
const isPageOneLoading = loadingCategories.has(pageOneLoadingKey);
|
|
46354
|
+
const isLoadMoreLoading = loadedPage > 0 && loadingCategories.has(getMetadataLoadingKey(node.id, nextMetadataPage));
|
|
46355
|
+
const showInitialLoadingState = Boolean(
|
|
46356
|
+
isExpanded && !hasLoadedChildren && (node.type === "category" || node.type === "percentile-category") && (isPageOneLoading || activeCategoryLoading && node.id === activeFilter)
|
|
45817
46357
|
);
|
|
45818
46358
|
const colorClasses = node.color ? getColorClasses(node.color) : null;
|
|
45819
46359
|
return /* @__PURE__ */ jsxs("div", { className: "select-none animate-in", children: [
|
|
@@ -45855,9 +46395,9 @@ var FileManagerFilters = ({
|
|
|
45855
46395
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0 flex items-center justify-between", children: [
|
|
45856
46396
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
45857
46397
|
/* @__PURE__ */ jsx("div", { className: `font-semibold tracking-tight ${node.type === "category" || node.type === "percentile-category" ? "text-slate-800 text-sm" : "text-slate-700 text-xs"} ${isCurrentVideo ? "text-blue-700 font-bold" : ""} group-hover:text-slate-900 transition-colors duration-200`, children: node.label }),
|
|
45858
|
-
node.type === "category" && categories.find((c) => c.id === node.id)?.description && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: categories.find((c) => c.id === node.id)?.description }),
|
|
46398
|
+
node.type === "category" && (node.subtitle || categories.find((c) => c.id === node.id)?.description) && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle || categories.find((c) => c.id === node.id)?.description }),
|
|
45859
46399
|
node.type === "percentile-category" && node.subtitle && /* @__PURE__ */ jsx("div", { className: "text-xs text-slate-500 mt-0.5 font-normal", children: node.subtitle }),
|
|
45860
|
-
node.type === "video" && (node.severity || node.categoryId === "cycle_completion" || node.categoryId === "idle_time" || node.categoryId === "low_value") && /* @__PURE__ */ jsx("div", { className: "text-xs mt-0.5 font-medium", children: node.categoryId === "idle_time" ? (
|
|
46400
|
+
node.type === "video" && (node.severity || node.categoryId === "cycle_completion" || node.categoryId === "idle_time" || node.categoryId === "low_value" || node.categoryId === RECENT_FLOW_RED_STREAK_CLIP_TYPE2) && /* @__PURE__ */ jsx("div", { className: "text-xs mt-0.5 font-medium", children: node.categoryId === "idle_time" ? (
|
|
45861
46401
|
// Show root cause label for idle time clips (text only, icon is on the left)
|
|
45862
46402
|
(() => {
|
|
45863
46403
|
if (!idleTimeVlmEnabled) {
|
|
@@ -45879,8 +46419,10 @@ var FileManagerFilters = ({
|
|
|
45879
46419
|
// Show badge for other clips
|
|
45880
46420
|
(() => {
|
|
45881
46421
|
const badge = getClipBadge(node);
|
|
46422
|
+
const redFlowDriverBadges = getRedFlowDriverBadges(node);
|
|
45882
46423
|
return /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center gap-1.5", children: [
|
|
45883
|
-
/* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${badge.className}`, children: badge.text }),
|
|
46424
|
+
badge ? /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${badge.className}`, children: badge.text }) : null,
|
|
46425
|
+
redFlowDriverBadges.map((redFlowDriverBadge) => /* @__PURE__ */ jsx("span", { className: `inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-medium ${redFlowDriverBadge.className}`, children: redFlowDriverBadge.text }, redFlowDriverBadge.text)),
|
|
45884
46426
|
node.categoryId === "cycle_completion" && node.cycleItemCount && node.cycleItemCount > 1 ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center px-1.5 py-0.5 rounded-md text-xs font-semibold bg-blue-100 text-blue-700 border border-blue-200", children: [
|
|
45885
46427
|
"x",
|
|
45886
46428
|
node.cycleItemCount
|
|
@@ -45896,21 +46438,20 @@ var FileManagerFilters = ({
|
|
|
45896
46438
|
),
|
|
45897
46439
|
hasChildren && isExpanded && (node.type === "category" || node.type === "percentile-category") && /* @__PURE__ */ jsx("div", { className: "mt-2 ml-3 animate-in border-l-2 border-slate-100 pl-3", children: /* @__PURE__ */ jsxs("div", { className: "max-h-64 overflow-y-auto space-y-1 scrollbar-thin scrollbar-track-slate-100 scrollbar-thumb-slate-300", children: [
|
|
45898
46440
|
node.children.map((child) => renderNode(child, depth + 1)),
|
|
45899
|
-
|
|
46441
|
+
showInitialLoadingState && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
|
|
45900
46442
|
/* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
|
|
45901
46443
|
"Loading clips..."
|
|
45902
46444
|
] }) }),
|
|
45903
|
-
|
|
46445
|
+
isLoadMoreLoading && /* @__PURE__ */ jsx("div", { className: "py-2 px-3 text-center", children: /* @__PURE__ */ jsxs("div", { className: "inline-flex items-center text-sm text-slate-500", children: [
|
|
45904
46446
|
/* @__PURE__ */ jsx("div", { className: "animate-spin mr-2 h-4 w-4 border-2 border-slate-300 border-t-blue-500 rounded-full" }),
|
|
45905
46447
|
"Loading more clips..."
|
|
45906
46448
|
] }) }),
|
|
45907
|
-
categoryHasMore[node.id] && !
|
|
46449
|
+
categoryHasMore[node.id] && !isLoadMoreLoading && /* @__PURE__ */ jsxs(
|
|
45908
46450
|
"button",
|
|
45909
46451
|
{
|
|
45910
46452
|
onClick: (e) => {
|
|
45911
46453
|
e.stopPropagation();
|
|
45912
|
-
|
|
45913
|
-
fetchClipMetadata(node.id, nextPage);
|
|
46454
|
+
fetchClipMetadata(node.id, nextLoadMorePage);
|
|
45914
46455
|
},
|
|
45915
46456
|
className: "w-full py-2 px-3 text-sm text-blue-600 hover:bg-blue-50 rounded-lg transition-colors duration-200 text-center",
|
|
45916
46457
|
children: [
|
|
@@ -46673,6 +47214,7 @@ var BottlenecksContent = ({
|
|
|
46673
47214
|
triageMode = false,
|
|
46674
47215
|
ticketId,
|
|
46675
47216
|
prefetchedPercentileCounts,
|
|
47217
|
+
lowMomentsPrefetch,
|
|
46676
47218
|
initialTimeFilter
|
|
46677
47219
|
}) => {
|
|
46678
47220
|
console.log("\u{1F3AB} [BottlenecksContent] Rendered with ticketId:", ticketId || "NONE", "workspaceId:", workspaceId, "date:", date, "shift:", shift);
|
|
@@ -46765,6 +47307,10 @@ var BottlenecksContent = ({
|
|
|
46765
47307
|
const [isShareLoading, setIsShareLoading] = useState(false);
|
|
46766
47308
|
const [isShareCopied, setIsShareCopied] = useState(false);
|
|
46767
47309
|
const shareCopiedTimeoutRef = useRef(null);
|
|
47310
|
+
const [lowEfficiencyAiSummaryByClipId, setLowEfficiencyAiSummaryByClipId] = useState({});
|
|
47311
|
+
const [lowEfficiencyAiSummaryLoadingByClipId, setLowEfficiencyAiSummaryLoadingByClipId] = useState({});
|
|
47312
|
+
const [lowEfficiencyAiSummaryErrorByClipId, setLowEfficiencyAiSummaryErrorByClipId] = useState({});
|
|
47313
|
+
const lowEfficiencyAiSummaryRequestStatusRef = useRef({});
|
|
46768
47314
|
useEffect(() => {
|
|
46769
47315
|
return () => {
|
|
46770
47316
|
if (shareCopiedTimeoutRef.current) {
|
|
@@ -46773,6 +47319,7 @@ var BottlenecksContent = ({
|
|
|
46773
47319
|
};
|
|
46774
47320
|
}, []);
|
|
46775
47321
|
const loadingTimeoutRef = useRef(null);
|
|
47322
|
+
const metadataLoadingKeyRef = useRef(null);
|
|
46776
47323
|
const [activeFilter, setActiveFilter] = useState(initialFilter);
|
|
46777
47324
|
const previousFilterRef = useRef("");
|
|
46778
47325
|
const [allVideos, setAllVideos] = useState([]);
|
|
@@ -46929,60 +47476,33 @@ var BottlenecksContent = ({
|
|
|
46929
47476
|
if (initialFilter) {
|
|
46930
47477
|
return;
|
|
46931
47478
|
}
|
|
47479
|
+
const redStreakType = "recent_flow_red_streak";
|
|
47480
|
+
if (dynamicCounts[redStreakType] > 0) {
|
|
47481
|
+
setInitialFilter(redStreakType);
|
|
47482
|
+
setActiveFilter(redStreakType);
|
|
47483
|
+
activeFilterRef.current = redStreakType;
|
|
47484
|
+
return;
|
|
47485
|
+
}
|
|
46932
47486
|
if (defaultCategory) {
|
|
46933
47487
|
setInitialFilter(defaultCategory);
|
|
46934
47488
|
setActiveFilter(defaultCategory);
|
|
46935
47489
|
activeFilterRef.current = defaultCategory;
|
|
46936
47490
|
return;
|
|
46937
47491
|
}
|
|
46938
|
-
if (clipTypes.length > 0) {
|
|
46939
|
-
let selectedType = null;
|
|
46940
|
-
if (clipTypes.length === 1) {
|
|
46941
|
-
selectedType = clipTypes[0];
|
|
46942
|
-
} else {
|
|
46943
|
-
const priorityOrder = ["cycle_completion", "fast-cycles", "slow-cycles", "idle_time"];
|
|
46944
|
-
for (const priorityType of priorityOrder) {
|
|
46945
|
-
const type = clipTypes.find((t) => t.type === priorityType && (dynamicCounts[t.type] || 0) > 0);
|
|
46946
|
-
if (type) {
|
|
46947
|
-
selectedType = type;
|
|
46948
|
-
break;
|
|
46949
|
-
}
|
|
46950
|
-
}
|
|
46951
|
-
if (!selectedType) {
|
|
46952
|
-
selectedType = clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0);
|
|
46953
|
-
}
|
|
46954
|
-
if (!selectedType) {
|
|
46955
|
-
selectedType = clipTypes[0];
|
|
46956
|
-
}
|
|
46957
|
-
}
|
|
46958
|
-
if (selectedType) {
|
|
46959
|
-
console.log(`[BottlenecksContent] Auto-selecting filter: ${selectedType.type} (count: ${dynamicCounts[selectedType.type] || 0})`);
|
|
46960
|
-
setInitialFilter(selectedType.type);
|
|
46961
|
-
setActiveFilter(selectedType.type);
|
|
46962
|
-
activeFilterRef.current = selectedType.type;
|
|
46963
|
-
}
|
|
46964
|
-
}
|
|
46965
47492
|
}, [clipTypes, dynamicCounts, defaultCategory, initialFilter]);
|
|
46966
47493
|
const mergedCounts = useMemo(() => {
|
|
46967
47494
|
return { ...dynamicCounts };
|
|
46968
47495
|
}, [dynamicCounts]);
|
|
46969
47496
|
useEffect(() => {
|
|
46970
|
-
if (
|
|
47497
|
+
if (allVideos.length > 0 || !isMountedRef.current) {
|
|
46971
47498
|
return;
|
|
46972
47499
|
}
|
|
46973
|
-
if (activeFilterRef.current
|
|
47500
|
+
if (!activeFilterRef.current) {
|
|
47501
|
+
setHasInitialLoad(true);
|
|
47502
|
+
setIsCategoryLoading(false);
|
|
46974
47503
|
return;
|
|
46975
47504
|
}
|
|
46976
|
-
|
|
46977
|
-
setAllVideos([firstClip]);
|
|
46978
|
-
setCurrentPosition(1);
|
|
46979
|
-
currentPositionRef.current = 1;
|
|
46980
|
-
const total = mergedCounts[firstClip.type] || 0;
|
|
46981
|
-
currentTotalRef.current = total;
|
|
46982
|
-
setCurrentTotal(total);
|
|
46983
|
-
setHasInitialLoad(true);
|
|
46984
|
-
setIsCategoryLoading(false);
|
|
46985
|
-
}, [firstClip, allVideos.length, mergedCounts]);
|
|
47505
|
+
}, [firstClips, allVideos.length, mergedCounts]);
|
|
46986
47506
|
useEffect(() => {
|
|
46987
47507
|
if (!firstClips || typeof document === "undefined") {
|
|
46988
47508
|
return;
|
|
@@ -47018,25 +47538,6 @@ var BottlenecksContent = ({
|
|
|
47018
47538
|
const loadFirstVideoForCategory = useCallback(async (category) => {
|
|
47019
47539
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current || !isEffectiveShiftReady) return;
|
|
47020
47540
|
const targetCategory = category || activeFilterRef.current;
|
|
47021
|
-
const initClip = targetCategory ? firstClips?.[targetCategory] : null;
|
|
47022
|
-
if (initClip) {
|
|
47023
|
-
setCurrentClipId(initClip.id || null);
|
|
47024
|
-
setAllVideos((prev) => {
|
|
47025
|
-
const exists = prev.some((v) => v.id === initClip.id);
|
|
47026
|
-
if (!exists) {
|
|
47027
|
-
return [...prev, initClip];
|
|
47028
|
-
}
|
|
47029
|
-
return prev;
|
|
47030
|
-
});
|
|
47031
|
-
setCurrentPosition(1);
|
|
47032
|
-
currentPositionRef.current = 1;
|
|
47033
|
-
const total = mergedCounts[targetCategory] || 0;
|
|
47034
|
-
currentTotalRef.current = total;
|
|
47035
|
-
setCurrentTotal(total);
|
|
47036
|
-
setHasInitialLoad(true);
|
|
47037
|
-
setIsCategoryLoading(false);
|
|
47038
|
-
return;
|
|
47039
|
-
}
|
|
47040
47541
|
const operationKey = `loadFirstVideo:${targetCategory}:${effectiveDateString}:${effectiveShiftId}`;
|
|
47041
47542
|
if (loadingCategoryRef.current === targetCategory || fetchInProgressRef.current.has(operationKey)) {
|
|
47042
47543
|
console.log(`[BottlenecksContent] Load first video already in progress for ${targetCategory}`);
|
|
@@ -47052,12 +47553,25 @@ var BottlenecksContent = ({
|
|
|
47052
47553
|
const shiftStr = effectiveShiftId;
|
|
47053
47554
|
console.log(`[BottlenecksContent] Loading first video for category: ${targetCategory}`);
|
|
47054
47555
|
try {
|
|
47055
|
-
|
|
47056
|
-
|
|
47057
|
-
|
|
47058
|
-
|
|
47059
|
-
|
|
47060
|
-
|
|
47556
|
+
let firstVideo = null;
|
|
47557
|
+
const totalCategoryClips = mergedCounts[targetCategory] || 0;
|
|
47558
|
+
if (totalCategoryClips > 0) {
|
|
47559
|
+
firstVideo = await s3ClipsService.getClipByIndex(
|
|
47560
|
+
workspaceId,
|
|
47561
|
+
operationalDate,
|
|
47562
|
+
shiftStr,
|
|
47563
|
+
targetCategory,
|
|
47564
|
+
0
|
|
47565
|
+
);
|
|
47566
|
+
}
|
|
47567
|
+
if (!firstVideo) {
|
|
47568
|
+
firstVideo = await s3ClipsService.getFirstClipForCategory(
|
|
47569
|
+
workspaceId,
|
|
47570
|
+
operationalDate,
|
|
47571
|
+
shiftStr,
|
|
47572
|
+
targetCategory
|
|
47573
|
+
);
|
|
47574
|
+
}
|
|
47061
47575
|
if (firstVideo) {
|
|
47062
47576
|
console.log(`[BottlenecksContent] Successfully loaded first video, ID: ${firstVideo.id}`);
|
|
47063
47577
|
setCurrentClipId(firstVideo.id || null);
|
|
@@ -47068,8 +47582,8 @@ var BottlenecksContent = ({
|
|
|
47068
47582
|
}
|
|
47069
47583
|
return prev;
|
|
47070
47584
|
});
|
|
47071
|
-
setCurrentPosition(1);
|
|
47072
|
-
currentPositionRef.current = 1;
|
|
47585
|
+
setCurrentPosition(totalCategoryClips > 0 ? 1 : 0);
|
|
47586
|
+
currentPositionRef.current = totalCategoryClips > 0 ? 1 : 0;
|
|
47073
47587
|
const total = mergedCounts[targetCategory] || 0;
|
|
47074
47588
|
currentTotalRef.current = total;
|
|
47075
47589
|
setCurrentTotal(total);
|
|
@@ -47083,13 +47597,13 @@ var BottlenecksContent = ({
|
|
|
47083
47597
|
}
|
|
47084
47598
|
if (mergedCounts[targetCategory] > 0) {
|
|
47085
47599
|
try {
|
|
47600
|
+
const fallbackIndex = 0;
|
|
47086
47601
|
const firstVideo = await s3ClipsService.getClipByIndex(
|
|
47087
47602
|
workspaceId,
|
|
47088
47603
|
operationalDate,
|
|
47089
47604
|
shiftStr,
|
|
47090
47605
|
targetCategory,
|
|
47091
|
-
|
|
47092
|
-
// First video (index 0)
|
|
47606
|
+
fallbackIndex
|
|
47093
47607
|
);
|
|
47094
47608
|
if (firstVideo && isMountedRef.current) {
|
|
47095
47609
|
console.log(`[BottlenecksContent] Successfully loaded first video via index`);
|
|
@@ -47192,11 +47706,12 @@ var BottlenecksContent = ({
|
|
|
47192
47706
|
categoryId
|
|
47193
47707
|
}));
|
|
47194
47708
|
};
|
|
47195
|
-
const [cycleClips, idleClips] = await Promise.all([
|
|
47709
|
+
const [cycleClips, redFlowClips, idleClips] = await Promise.all([
|
|
47196
47710
|
fetchCategoryMetadata("cycle_completion"),
|
|
47711
|
+
fetchCategoryMetadata("recent_flow_red_streak"),
|
|
47197
47712
|
fetchCategoryMetadata("idle_time")
|
|
47198
47713
|
]);
|
|
47199
|
-
const allClips = [...cycleClips, ...idleClips].sort(
|
|
47714
|
+
const allClips = [...cycleClips, ...redFlowClips, ...idleClips].sort(
|
|
47200
47715
|
(a, b) => new Date(b.clip_timestamp).getTime() - new Date(a.clip_timestamp).getTime()
|
|
47201
47716
|
);
|
|
47202
47717
|
setTriageClips(allClips);
|
|
@@ -47245,6 +47760,9 @@ var BottlenecksContent = ({
|
|
|
47245
47760
|
}, [idleTimeVlmEnabled, triageClips, triageMode, getAuthToken4]);
|
|
47246
47761
|
useEffect(() => {
|
|
47247
47762
|
if (s3ClipsService && (mergedCounts[activeFilter] || 0) > 0) {
|
|
47763
|
+
if (activeFilter === "recent_flow_red_streak") {
|
|
47764
|
+
return;
|
|
47765
|
+
}
|
|
47248
47766
|
if (firstClip && firstClip.type === activeFilter) {
|
|
47249
47767
|
return;
|
|
47250
47768
|
}
|
|
@@ -47265,10 +47783,10 @@ var BottlenecksContent = ({
|
|
|
47265
47783
|
return ["fast-cycles", "slow-cycles", "longest-idles"].includes(categoryId);
|
|
47266
47784
|
}, [isFastSlowClipFiltersEnabled]);
|
|
47267
47785
|
const shouldUseMetadataNavigation = useCallback((categoryId) => {
|
|
47268
|
-
return isPercentileCategory(categoryId) || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
|
|
47786
|
+
return isPercentileCategory(categoryId) || categoryId === "recent_flow_red_streak" || categoryId === "idle_time" && idleClipSort === "idle_duration_desc";
|
|
47269
47787
|
}, [idleClipSort, isPercentileCategory]);
|
|
47270
47788
|
const getMetadataCacheKey = useCallback((categoryId) => {
|
|
47271
|
-
const sortKey = categoryId === "idle_time" ? idleClipSort : "latest";
|
|
47789
|
+
const sortKey = categoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest";
|
|
47272
47790
|
return `${categoryId}-${effectiveDateString}-${effectiveShiftId}-${snapshotDateTime ?? "nosnap"}-${snapshotClipId ?? "nosnap"}-${sortKey}`;
|
|
47273
47791
|
}, [effectiveDateString, effectiveShiftId, snapshotDateTime, snapshotClipId, idleClipSort]);
|
|
47274
47792
|
const setVisibleCategoryMetadata = useCallback((categoryId, clips) => {
|
|
@@ -47278,7 +47796,7 @@ var BottlenecksContent = ({
|
|
|
47278
47796
|
categoryMetadataRef.current = clips;
|
|
47279
47797
|
setCategoryMetadata(clips);
|
|
47280
47798
|
setCategoryMetadataCategoryId(clips.length > 0 ? categoryId : null);
|
|
47281
|
-
setCategoryMetadataSort(clips.length > 0 ? categoryId === "idle_time" ? idleClipSort : "latest" : null);
|
|
47799
|
+
setCategoryMetadataSort(clips.length > 0 ? categoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest" : null);
|
|
47282
47800
|
return true;
|
|
47283
47801
|
}, [idleClipSort]);
|
|
47284
47802
|
const applyMetadataSnapshot = useCallback((categoryId, clips, total) => {
|
|
@@ -47296,6 +47814,22 @@ var BottlenecksContent = ({
|
|
|
47296
47814
|
setCurrentTotal(total);
|
|
47297
47815
|
}
|
|
47298
47816
|
}, [getMetadataCacheKey, shouldUseMetadataNavigation, setVisibleCategoryMetadata]);
|
|
47817
|
+
const applyPrefetchedFirstVideo = useCallback((video) => {
|
|
47818
|
+
if (!video || !isMountedRef.current) {
|
|
47819
|
+
return false;
|
|
47820
|
+
}
|
|
47821
|
+
if (currentClipIdRef.current === video.id) {
|
|
47822
|
+
return true;
|
|
47823
|
+
}
|
|
47824
|
+
setCurrentClipId(video.id);
|
|
47825
|
+
setAllVideos([video]);
|
|
47826
|
+
setCurrentIndex(0);
|
|
47827
|
+
setCurrentMetadataIndex(0);
|
|
47828
|
+
currentMetadataIndexRef.current = 0;
|
|
47829
|
+
setCurrentPosition(1);
|
|
47830
|
+
currentPositionRef.current = 1;
|
|
47831
|
+
return true;
|
|
47832
|
+
}, []);
|
|
47299
47833
|
const getClipTypesForPercentileCategory = useCallback((categoryId) => {
|
|
47300
47834
|
switch (categoryId) {
|
|
47301
47835
|
case "fast-cycles":
|
|
@@ -47315,7 +47849,7 @@ var BottlenecksContent = ({
|
|
|
47315
47849
|
if (activeFilter !== "fast-cycles" && activeFilter !== "slow-cycles") {
|
|
47316
47850
|
return;
|
|
47317
47851
|
}
|
|
47318
|
-
const fallbackFilter = ["cycle_completion", "idle_time"].find((type) => (dynamicCounts[type] || 0) > 0) || clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0)?.type || clipTypes[0]?.type;
|
|
47852
|
+
const fallbackFilter = ["cycle_completion", "recent_flow_red_streak", "idle_time"].find((type) => (dynamicCounts[type] || 0) > 0) || clipTypes.find((type) => (dynamicCounts[type.type] || 0) > 0)?.type || clipTypes[0]?.type;
|
|
47319
47853
|
if (!fallbackFilter || fallbackFilter === activeFilter) {
|
|
47320
47854
|
return;
|
|
47321
47855
|
}
|
|
@@ -47371,30 +47905,70 @@ var BottlenecksContent = ({
|
|
|
47371
47905
|
setCategoryMetadataCategoryId(null);
|
|
47372
47906
|
setCategoryMetadataSort(null);
|
|
47373
47907
|
categoryMetadataRef.current = [];
|
|
47908
|
+
if (activeFilterRef.current === categoryId) {
|
|
47909
|
+
setIsCategoryLoading(false);
|
|
47910
|
+
}
|
|
47374
47911
|
return;
|
|
47375
47912
|
}
|
|
47376
47913
|
if (!isEffectiveShiftReady) {
|
|
47377
47914
|
console.log("[BottlenecksContent] Skipping metadata load - shift/date not ready");
|
|
47915
|
+
if (activeFilterRef.current === categoryId) {
|
|
47916
|
+
setIsCategoryLoading(false);
|
|
47917
|
+
}
|
|
47378
47918
|
return;
|
|
47379
47919
|
}
|
|
47380
47920
|
const resolvedDate = effectiveDateString;
|
|
47381
47921
|
const cacheKey = getMetadataCacheKey(categoryId);
|
|
47382
|
-
const
|
|
47922
|
+
const candidateLowMomentsPrefetch = lowMomentsPrefetch ?? null;
|
|
47923
|
+
const lowMomentsPrefetchMatchesScope = Boolean(
|
|
47924
|
+
candidateLowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`)
|
|
47925
|
+
);
|
|
47926
|
+
const matchingLowMomentsPrefetch = !forceRefresh && categoryId === "recent_flow_red_streak" && candidateLowMomentsPrefetch && (candidateLowMomentsPrefetch.key === cacheKey || lowMomentsPrefetchMatchesScope) && !candidateLowMomentsPrefetch.loading && Array.isArray(candidateLowMomentsPrefetch.metadata) && candidateLowMomentsPrefetch.metadata.length > 0 ? candidateLowMomentsPrefetch : null;
|
|
47927
|
+
const lowMomentsPrefetchInFlight = !forceRefresh && categoryId === "recent_flow_red_streak" && candidateLowMomentsPrefetch && (candidateLowMomentsPrefetch.key === cacheKey || lowMomentsPrefetchMatchesScope) && candidateLowMomentsPrefetch.loading;
|
|
47928
|
+
if (lowMomentsPrefetchInFlight) {
|
|
47929
|
+
if (autoLoadFirstVideo && candidateLowMomentsPrefetch?.firstVideo) {
|
|
47930
|
+
applyPrefetchedFirstVideo(candidateLowMomentsPrefetch.firstVideo);
|
|
47931
|
+
}
|
|
47932
|
+
if (Array.isArray(candidateLowMomentsPrefetch?.metadata) && candidateLowMomentsPrefetch.metadata.length > 0) {
|
|
47933
|
+
applyMetadataSnapshot(categoryId, candidateLowMomentsPrefetch.metadata, candidateLowMomentsPrefetch.total);
|
|
47934
|
+
}
|
|
47935
|
+
if (activeFilterRef.current === categoryId) {
|
|
47936
|
+
setIsCategoryLoading(true);
|
|
47937
|
+
}
|
|
47938
|
+
return;
|
|
47939
|
+
}
|
|
47940
|
+
const cachedMetadata = matchingLowMomentsPrefetch?.metadata ?? (!forceRefresh ? metadataCache[cacheKey] : void 0);
|
|
47941
|
+
const requestKey = cacheKey;
|
|
47942
|
+
if (metadataLoadingKeyRef.current === requestKey) {
|
|
47943
|
+
console.log(`[BottlenecksContent] Metadata load already in progress for ${categoryId}`);
|
|
47944
|
+
return;
|
|
47945
|
+
}
|
|
47946
|
+
metadataLoadingKeyRef.current = requestKey;
|
|
47383
47947
|
try {
|
|
47384
47948
|
if (cachedMetadata) {
|
|
47385
47949
|
console.log(`[BottlenecksContent] Using cached metadata for ${categoryId}`);
|
|
47950
|
+
if (matchingLowMomentsPrefetch) {
|
|
47951
|
+
setMetadataCache((prev) => prev[cacheKey] ? prev : {
|
|
47952
|
+
...prev,
|
|
47953
|
+
[cacheKey]: matchingLowMomentsPrefetch.metadata
|
|
47954
|
+
});
|
|
47955
|
+
}
|
|
47386
47956
|
setVisibleCategoryMetadata(categoryId, cachedMetadata);
|
|
47387
47957
|
if (autoLoadFirstVideo && cachedMetadata.length > 0 && s3ClipsService) {
|
|
47388
47958
|
const firstClipMeta = cachedMetadata[0];
|
|
47959
|
+
const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
|
|
47960
|
+
const prefetchedFirstVideo = matchingLowMomentsPrefetch?.firstVideo ?? null;
|
|
47389
47961
|
try {
|
|
47390
|
-
|
|
47391
|
-
if (
|
|
47392
|
-
|
|
47393
|
-
|
|
47394
|
-
|
|
47395
|
-
|
|
47396
|
-
|
|
47397
|
-
|
|
47962
|
+
let loadedVideo = null;
|
|
47963
|
+
if (prefetchedFirstVideo?.id === firstClipId) {
|
|
47964
|
+
loadedVideo = prefetchedFirstVideo;
|
|
47965
|
+
applyPrefetchedFirstVideo(prefetchedFirstVideo);
|
|
47966
|
+
} else {
|
|
47967
|
+
loadedVideo = await s3ClipsService.getClipById(firstClipId);
|
|
47968
|
+
applyPrefetchedFirstVideo(loadedVideo);
|
|
47969
|
+
}
|
|
47970
|
+
if (loadedVideo && isMountedRef.current) {
|
|
47971
|
+
console.log(`[BottlenecksContent] Auto-loaded first video from cache: ${loadedVideo.id} (1/${cachedMetadata.length})`);
|
|
47398
47972
|
}
|
|
47399
47973
|
} catch (error2) {
|
|
47400
47974
|
console.error(`[BottlenecksContent] Error loading first video from cache:`, error2);
|
|
@@ -47441,7 +48015,7 @@ var BottlenecksContent = ({
|
|
|
47441
48015
|
knownTotal: mergedCounts[categoryId] ?? null,
|
|
47442
48016
|
snapshotDateTime,
|
|
47443
48017
|
snapshotClipId,
|
|
47444
|
-
sort: categoryId === "idle_time" ? idleClipSort : "latest"
|
|
48018
|
+
sort: categoryId === "recent_flow_red_streak" ? "red_flow_output_shortfall_desc" : categoryId === "idle_time" ? idleClipSort : "latest"
|
|
47445
48019
|
}),
|
|
47446
48020
|
redirectReason: "session_expired"
|
|
47447
48021
|
});
|
|
@@ -47502,10 +48076,11 @@ var BottlenecksContent = ({
|
|
|
47502
48076
|
console.log(`[BottlenecksContent] Loaded metadata for ${categoryId}: ${metadataClips.length} clips`);
|
|
47503
48077
|
if (autoLoadFirstVideo && metadataClips.length > 0 && s3ClipsService) {
|
|
47504
48078
|
const firstClipMeta = metadataClips[0];
|
|
48079
|
+
const firstClipId = firstClipMeta.clipId || firstClipMeta.id;
|
|
47505
48080
|
try {
|
|
47506
|
-
const video = await s3ClipsService.getClipById(
|
|
48081
|
+
const video = await s3ClipsService.getClipById(firstClipId);
|
|
47507
48082
|
if (video && isMountedRef.current) {
|
|
47508
|
-
setCurrentClipId(
|
|
48083
|
+
setCurrentClipId(firstClipId);
|
|
47509
48084
|
setAllVideos([video]);
|
|
47510
48085
|
setCurrentIndex(0);
|
|
47511
48086
|
setCurrentMetadataIndex(0);
|
|
@@ -47527,9 +48102,43 @@ var BottlenecksContent = ({
|
|
|
47527
48102
|
} catch (error2) {
|
|
47528
48103
|
console.error(`[BottlenecksContent] Error loading category metadata:`, error2);
|
|
47529
48104
|
} finally {
|
|
47530
|
-
|
|
48105
|
+
if (metadataLoadingKeyRef.current === requestKey) {
|
|
48106
|
+
metadataLoadingKeyRef.current = null;
|
|
48107
|
+
}
|
|
48108
|
+
if (activeFilterRef.current === categoryId) {
|
|
48109
|
+
setIsCategoryLoading(false);
|
|
48110
|
+
}
|
|
47531
48111
|
}
|
|
47532
|
-
}, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata]);
|
|
48112
|
+
}, [workspaceId, effectiveDateString, effectiveShiftId, getMetadataCacheKey, isPercentileCategory, isFastSlowClipFiltersEnabled, metadataCache, s3ClipsService, clearLoadingState, isEffectiveShiftReady, snapshotDateTime, snapshotClipId, idleClipSort, supabase, setVisibleCategoryMetadata, lowMomentsPrefetch, applyPrefetchedFirstVideo, applyMetadataSnapshot]);
|
|
48113
|
+
useEffect(() => {
|
|
48114
|
+
if (activeFilter !== "recent_flow_red_streak") {
|
|
48115
|
+
return;
|
|
48116
|
+
}
|
|
48117
|
+
if (!lowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`)) {
|
|
48118
|
+
return;
|
|
48119
|
+
}
|
|
48120
|
+
if (lowMomentsPrefetch.firstVideo && !allVideos.some((video) => video.type === "recent_flow_red_streak")) {
|
|
48121
|
+
applyPrefetchedFirstVideo(lowMomentsPrefetch.firstVideo);
|
|
48122
|
+
}
|
|
48123
|
+
if (lowMomentsPrefetch.metadata.length > 0) {
|
|
48124
|
+
applyMetadataSnapshot("recent_flow_red_streak", lowMomentsPrefetch.metadata, lowMomentsPrefetch.total);
|
|
48125
|
+
if (isMountedRef.current) {
|
|
48126
|
+
setIsCategoryLoading(false);
|
|
48127
|
+
}
|
|
48128
|
+
return;
|
|
48129
|
+
}
|
|
48130
|
+
if (isMountedRef.current) {
|
|
48131
|
+
setIsCategoryLoading(lowMomentsPrefetch.loading);
|
|
48132
|
+
}
|
|
48133
|
+
}, [
|
|
48134
|
+
activeFilter,
|
|
48135
|
+
lowMomentsPrefetch,
|
|
48136
|
+
effectiveDateString,
|
|
48137
|
+
effectiveShiftId,
|
|
48138
|
+
allVideos,
|
|
48139
|
+
applyPrefetchedFirstVideo,
|
|
48140
|
+
applyMetadataSnapshot
|
|
48141
|
+
]);
|
|
47533
48142
|
useEffect(() => {
|
|
47534
48143
|
if (previousIdleClipSortRef.current === idleClipSort) {
|
|
47535
48144
|
return;
|
|
@@ -47569,8 +48178,13 @@ var BottlenecksContent = ({
|
|
|
47569
48178
|
currentTotalRef.current = total;
|
|
47570
48179
|
setCurrentTotal(total);
|
|
47571
48180
|
previousFilterRef.current = activeFilter;
|
|
47572
|
-
|
|
47573
|
-
|
|
48181
|
+
const metadataLoadPlan = getCategoryMetadataLoadPlanForFilterChange({
|
|
48182
|
+
activeFilter,
|
|
48183
|
+
currentClipId,
|
|
48184
|
+
categoryTotal: total
|
|
48185
|
+
});
|
|
48186
|
+
if (metadataLoadPlan.shouldLoad) {
|
|
48187
|
+
loadCategoryMetadata(activeFilter, metadataLoadPlan.autoLoadFirstVideo);
|
|
47574
48188
|
}
|
|
47575
48189
|
const filtered = allVideos.filter((video) => {
|
|
47576
48190
|
if (activeFilter === "all") return true;
|
|
@@ -47593,11 +48207,11 @@ var BottlenecksContent = ({
|
|
|
47593
48207
|
if (!currentClipId || activeFilter === "all") {
|
|
47594
48208
|
return;
|
|
47595
48209
|
}
|
|
47596
|
-
if (categoryMetadataRef.current.length > 0
|
|
48210
|
+
if (categoryMetadataRef.current.length > 0) {
|
|
47597
48211
|
return;
|
|
47598
48212
|
}
|
|
47599
48213
|
loadCategoryMetadata(activeFilter, false);
|
|
47600
|
-
}, [currentClipId, activeFilter,
|
|
48214
|
+
}, [currentClipId, activeFilter, loadCategoryMetadata]);
|
|
47601
48215
|
const loadAndPlayClipById = useCallback(async (clipId, categoryId, position, metadataContext) => {
|
|
47602
48216
|
if (!workspaceId || !s3ClipsService || !isMountedRef.current) return;
|
|
47603
48217
|
console.log(`[BottlenecksContent] Loading clip by ID: ${clipId}, category=${categoryId}, position=${position}`);
|
|
@@ -48056,6 +48670,98 @@ var BottlenecksContent = ({
|
|
|
48056
48670
|
}
|
|
48057
48671
|
return filteredVideos[currentIndex];
|
|
48058
48672
|
}, [filteredVideos, currentIndex]);
|
|
48673
|
+
const currentLowEfficiencyClipId = currentVideo?.id || currentClipId || null;
|
|
48674
|
+
const isCurrentLowEfficiencyClip = Boolean(
|
|
48675
|
+
currentVideo?.type === "recent_flow_red_streak" || currentVideo?.red_flow_timeline
|
|
48676
|
+
);
|
|
48677
|
+
const currentLowEfficiencyAiSummary = currentLowEfficiencyClipId ? lowEfficiencyAiSummaryByClipId[currentLowEfficiencyClipId] || currentVideo?.low_efficiency_ai_summary || null : null;
|
|
48678
|
+
const isCurrentLowEfficiencyAiSummaryLoading = Boolean(
|
|
48679
|
+
currentLowEfficiencyClipId && lowEfficiencyAiSummaryLoadingByClipId[currentLowEfficiencyClipId]
|
|
48680
|
+
);
|
|
48681
|
+
const currentLowEfficiencyAiSummaryError = currentLowEfficiencyClipId ? lowEfficiencyAiSummaryErrorByClipId[currentLowEfficiencyClipId] || null : null;
|
|
48682
|
+
useEffect(() => {
|
|
48683
|
+
const clipId = currentLowEfficiencyClipId;
|
|
48684
|
+
if (!clipId || !isCurrentLowEfficiencyClip || !workspaceId) {
|
|
48685
|
+
return;
|
|
48686
|
+
}
|
|
48687
|
+
if (currentVideo?.low_efficiency_ai_summary || lowEfficiencyAiSummaryRequestStatusRef.current[clipId]) {
|
|
48688
|
+
return;
|
|
48689
|
+
}
|
|
48690
|
+
let cancelled = false;
|
|
48691
|
+
let timedOut = false;
|
|
48692
|
+
const controller = new AbortController();
|
|
48693
|
+
lowEfficiencyAiSummaryRequestStatusRef.current[clipId] = "loading";
|
|
48694
|
+
const timeout = setTimeout(() => {
|
|
48695
|
+
timedOut = true;
|
|
48696
|
+
controller.abort();
|
|
48697
|
+
}, 3e4);
|
|
48698
|
+
setLowEfficiencyAiSummaryLoadingByClipId((prev) => ({ ...prev, [clipId]: true }));
|
|
48699
|
+
setLowEfficiencyAiSummaryErrorByClipId((prev) => ({ ...prev, [clipId]: null }));
|
|
48700
|
+
void (async () => {
|
|
48701
|
+
try {
|
|
48702
|
+
const response = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
48703
|
+
method: "POST",
|
|
48704
|
+
headers: {
|
|
48705
|
+
"Content-Type": "application/json"
|
|
48706
|
+
},
|
|
48707
|
+
signal: controller.signal,
|
|
48708
|
+
body: JSON.stringify({
|
|
48709
|
+
action: "ai-summary",
|
|
48710
|
+
workspaceId,
|
|
48711
|
+
clipId,
|
|
48712
|
+
workspaceName
|
|
48713
|
+
}),
|
|
48714
|
+
redirectReason: "session_expired"
|
|
48715
|
+
});
|
|
48716
|
+
if (!response.ok) {
|
|
48717
|
+
throw new Error(`AI summary API error: ${response.status}`);
|
|
48718
|
+
}
|
|
48719
|
+
const payload = await response.json();
|
|
48720
|
+
const summary = payload?.summary;
|
|
48721
|
+
if (!summary || !Array.isArray(summary.bullets) || summary.bullets.filter((bullet) => String(bullet || "").trim()).length < 3) {
|
|
48722
|
+
throw new Error("AI summary response was empty");
|
|
48723
|
+
}
|
|
48724
|
+
if (!cancelled) {
|
|
48725
|
+
lowEfficiencyAiSummaryRequestStatusRef.current[clipId] = "success";
|
|
48726
|
+
setLowEfficiencyAiSummaryByClipId((prev) => ({ ...prev, [clipId]: summary }));
|
|
48727
|
+
}
|
|
48728
|
+
} catch (error2) {
|
|
48729
|
+
if (cancelled) {
|
|
48730
|
+
return;
|
|
48731
|
+
}
|
|
48732
|
+
lowEfficiencyAiSummaryRequestStatusRef.current[clipId] = "error";
|
|
48733
|
+
const message = timedOut ? "AI summary timed out" : error2 instanceof Error ? error2.message : "AI summary unavailable";
|
|
48734
|
+
console.warn("[BottlenecksContent] Failed to generate Low Efficiency AI summary:", error2);
|
|
48735
|
+
setLowEfficiencyAiSummaryErrorByClipId((prev) => ({
|
|
48736
|
+
...prev,
|
|
48737
|
+
[clipId]: message
|
|
48738
|
+
}));
|
|
48739
|
+
} finally {
|
|
48740
|
+
clearTimeout(timeout);
|
|
48741
|
+
if (isMountedRef.current) {
|
|
48742
|
+
setLowEfficiencyAiSummaryLoadingByClipId((prev) => ({ ...prev, [clipId]: false }));
|
|
48743
|
+
}
|
|
48744
|
+
}
|
|
48745
|
+
})();
|
|
48746
|
+
return () => {
|
|
48747
|
+
cancelled = true;
|
|
48748
|
+
clearTimeout(timeout);
|
|
48749
|
+
if (lowEfficiencyAiSummaryRequestStatusRef.current[clipId] === "loading") {
|
|
48750
|
+
delete lowEfficiencyAiSummaryRequestStatusRef.current[clipId];
|
|
48751
|
+
}
|
|
48752
|
+
if (isMountedRef.current) {
|
|
48753
|
+
setLowEfficiencyAiSummaryLoadingByClipId((prev) => ({ ...prev, [clipId]: false }));
|
|
48754
|
+
}
|
|
48755
|
+
controller.abort();
|
|
48756
|
+
};
|
|
48757
|
+
}, [
|
|
48758
|
+
currentLowEfficiencyClipId,
|
|
48759
|
+
currentVideo?.low_efficiency_ai_summary,
|
|
48760
|
+
isCurrentLowEfficiencyClip,
|
|
48761
|
+
supabase,
|
|
48762
|
+
workspaceId,
|
|
48763
|
+
workspaceName
|
|
48764
|
+
]);
|
|
48059
48765
|
const handleShareClip = useCallback(async () => {
|
|
48060
48766
|
if (!currentVideo?.id || isShareLoading) {
|
|
48061
48767
|
if (!currentVideo?.id) {
|
|
@@ -48127,11 +48833,11 @@ var BottlenecksContent = ({
|
|
|
48127
48833
|
}
|
|
48128
48834
|
return currentPosition;
|
|
48129
48835
|
}, [activeFilter, categoryMetadata.length, currentMetadataIndex, currentPosition, shouldUseMetadataNavigation]);
|
|
48130
|
-
const prefetchedExplorerMetadata = useMemo(() => activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
|
|
48836
|
+
const prefetchedExplorerMetadata = useMemo(() => activeFilter === "recent_flow_red_streak" && lowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`) && !lowMomentsPrefetch.loading && lowMomentsPrefetch.metadata.length > 0 ? { recent_flow_red_streak: lowMomentsPrefetch.metadata } : activeFilter === "idle_time" && categoryMetadataSort !== idleClipSort ? void 0 : buildPrefetchedExplorerMetadata(
|
|
48131
48837
|
activeFilter,
|
|
48132
48838
|
categoryMetadataCategoryId,
|
|
48133
48839
|
categoryMetadata
|
|
48134
|
-
), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort]);
|
|
48840
|
+
), [activeFilter, categoryMetadata, categoryMetadataCategoryId, categoryMetadataSort, idleClipSort, lowMomentsPrefetch, effectiveDateString, effectiveShiftId]);
|
|
48135
48841
|
const classificationClipIds = useMemo(() => {
|
|
48136
48842
|
if (!idleTimeVlmEnabled) {
|
|
48137
48843
|
return [];
|
|
@@ -48523,6 +49229,8 @@ var BottlenecksContent = ({
|
|
|
48523
49229
|
return "Cycle Completion";
|
|
48524
49230
|
case "idle_time":
|
|
48525
49231
|
return "Idle Time";
|
|
49232
|
+
case "recent_flow_red_streak":
|
|
49233
|
+
return "Low efficiency videos";
|
|
48526
49234
|
case "running_cycle":
|
|
48527
49235
|
return "Running Cycle";
|
|
48528
49236
|
case "setup_state":
|
|
@@ -48602,12 +49310,26 @@ var BottlenecksContent = ({
|
|
|
48602
49310
|
onShare: handleShareClip,
|
|
48603
49311
|
isShareLoading,
|
|
48604
49312
|
isShareCopied,
|
|
49313
|
+
timelineAnnotations: currentVideo.red_flow_timeline,
|
|
49314
|
+
timelineExplanation: currentVideo.red_flow_explanation,
|
|
49315
|
+
timelineTimezone: timezone,
|
|
48605
49316
|
options: videoPlayerOptions
|
|
48606
49317
|
},
|
|
48607
49318
|
`${currentVideo.id}-${playerInstanceNonce}-inline`
|
|
48608
49319
|
)
|
|
48609
49320
|
}
|
|
48610
49321
|
),
|
|
49322
|
+
currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
|
|
49323
|
+
RedFlowDiagnosticOverlay,
|
|
49324
|
+
{
|
|
49325
|
+
timeline: currentVideo.red_flow_timeline,
|
|
49326
|
+
explanation: currentVideo.red_flow_explanation,
|
|
49327
|
+
aiSummary: currentLowEfficiencyAiSummary,
|
|
49328
|
+
aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
|
|
49329
|
+
aiSummaryError: currentLowEfficiencyAiSummaryError,
|
|
49330
|
+
className: "right-4 top-4"
|
|
49331
|
+
}
|
|
49332
|
+
) : null,
|
|
48611
49333
|
showBlockingVideoLoader && !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..." }) }),
|
|
48612
49334
|
!shouldDeferPlayerRenderForCrop && !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..." }) }),
|
|
48613
49335
|
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: [
|
|
@@ -48707,10 +49429,10 @@ var BottlenecksContent = ({
|
|
|
48707
49429
|
] }) })
|
|
48708
49430
|
] });
|
|
48709
49431
|
})()
|
|
48710
|
-
) : /* @__PURE__ */ jsx("div", { className:
|
|
49432
|
+
) : /* @__PURE__ */ jsx("div", { className: `absolute top-3 z-10 bg-black/60 backdrop-blur-sm px-3 py-1.5 rounded-lg text-white shadow-lg text-xs ${currentVideo.type === "recent_flow_red_streak" ? "left-3" : "right-3"}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
48711
49433
|
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-2.5 w-2.5 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
|
|
48712
49434
|
/* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
|
|
48713
|
-
/* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
49435
|
+
currentVideo.type !== "recent_flow_red_streak" && /* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
48714
49436
|
] }) })
|
|
48715
49437
|
)
|
|
48716
49438
|
] }) }) }) : (
|
|
@@ -48720,14 +49442,21 @@ var BottlenecksContent = ({
|
|
|
48720
49442
|
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Clips Found" }),
|
|
48721
49443
|
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There were no video clips found for this workspace today." })
|
|
48722
49444
|
] }) }) : (
|
|
48723
|
-
/* Priority
|
|
48724
|
-
hasInitialLoad &&
|
|
49445
|
+
/* Priority 5.5: Show "no folder selected" if activeFilter is empty */
|
|
49446
|
+
hasInitialLoad && !activeFilter ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
48725
49447
|
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
48726
|
-
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No
|
|
48727
|
-
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "
|
|
49448
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Folder Selected" }),
|
|
49449
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "Please select a folder to view clips." })
|
|
48728
49450
|
] }) }) : (
|
|
48729
|
-
/* Priority
|
|
48730
|
-
|
|
49451
|
+
/* Priority 6: Show "no matching clips" only if we have data loaded and specifically no clips for this filter */
|
|
49452
|
+
hasInitialLoad && (mergedCounts[activeFilter] || 0) === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center min-h-[220px] sm:min-h-[320px] lg:h-full", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
49453
|
+
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
49454
|
+
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Matching Clips" }),
|
|
49455
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-500", children: "There are no clips matching the selected filter." })
|
|
49456
|
+
] }) }) : (
|
|
49457
|
+
/* Priority 7: Default loading state for any other case */
|
|
49458
|
+
/* @__PURE__ */ jsx("div", { className: "p-4 lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative lg:h-full", children: /* @__PURE__ */ jsx("div", { className: "relative w-full min-h-[220px] sm:min-h-[320px] lg:min-h-0 lg:h-full overflow-hidden rounded-md shadow-inner bg-gray-900 flex items-center justify-center", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "md", message: "Loading..." }) }) }) })
|
|
49459
|
+
)
|
|
48731
49460
|
)
|
|
48732
49461
|
)
|
|
48733
49462
|
) }) }),
|
|
@@ -48879,6 +49608,11 @@ var BottlenecksContent = ({
|
|
|
48879
49608
|
idleTimeVlmEnabled,
|
|
48880
49609
|
showPercentileCycleFilters: isFastSlowClipFiltersEnabled,
|
|
48881
49610
|
prefetchedClipMetadata: prefetchedExplorerMetadata,
|
|
49611
|
+
externallyManagedLoadingCategories: {
|
|
49612
|
+
recent_flow_red_streak: Boolean(
|
|
49613
|
+
activeFilter === "recent_flow_red_streak" && lowMomentsPrefetch?.key?.startsWith(`recent_flow_red_streak-${effectiveDateString}-${effectiveShiftId}-`) && lowMomentsPrefetch.loading
|
|
49614
|
+
)
|
|
49615
|
+
},
|
|
48882
49616
|
activeCategoryLoading: isCategoryLoading,
|
|
48883
49617
|
idleClipSort,
|
|
48884
49618
|
onIdleClipSortChange: setIdleClipSort,
|
|
@@ -48994,10 +49728,10 @@ var BottlenecksContent = ({
|
|
|
48994
49728
|
] }) })
|
|
48995
49729
|
] });
|
|
48996
49730
|
})()
|
|
48997
|
-
) : /* @__PURE__ */ jsx("div", { className:
|
|
49731
|
+
) : /* @__PURE__ */ jsx("div", { className: `absolute top-4 z-50 bg-black/60 backdrop-blur-sm px-4 py-2 rounded-lg text-white shadow-lg ${currentVideo.type === "recent_flow_red_streak" ? "left-4" : "right-20"}`, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
|
|
48998
49732
|
/* @__PURE__ */ jsx("div", { className: `flex-shrink-0 h-3 w-3 rounded-full ${getSeverityColor(currentVideo.severity)} mr-2 animate-pulse` }),
|
|
48999
49733
|
/* @__PURE__ */ jsx("span", { className: "font-medium mr-2", children: getClipTypeLabel(currentVideo) }),
|
|
49000
|
-
/* @__PURE__ */ jsx("span", { className: "opacity-80", children: currentVideo.description })
|
|
49734
|
+
currentVideo.type !== "recent_flow_red_streak" && /* @__PURE__ */ jsx("span", { className: "opacity-80", children: currentVideo.description })
|
|
49001
49735
|
] }) }),
|
|
49002
49736
|
/* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center p-8", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full max-w-7xl group", children: [
|
|
49003
49737
|
/* @__PURE__ */ jsx(
|
|
@@ -49033,12 +49767,26 @@ var BottlenecksContent = ({
|
|
|
49033
49767
|
onShare: handleShareClip,
|
|
49034
49768
|
isShareLoading,
|
|
49035
49769
|
isShareCopied,
|
|
49770
|
+
timelineAnnotations: currentVideo.red_flow_timeline,
|
|
49771
|
+
timelineExplanation: currentVideo.red_flow_explanation,
|
|
49772
|
+
timelineTimezone: timezone,
|
|
49036
49773
|
options: videoPlayerOptions
|
|
49037
49774
|
},
|
|
49038
49775
|
`${currentVideo.id}-${playerInstanceNonce}-fullscreen`
|
|
49039
49776
|
)
|
|
49040
49777
|
}
|
|
49041
49778
|
),
|
|
49779
|
+
currentVideo.type === "recent_flow_red_streak" && !shouldDeferPlayerRenderForCrop ? /* @__PURE__ */ jsx(
|
|
49780
|
+
RedFlowDiagnosticOverlay,
|
|
49781
|
+
{
|
|
49782
|
+
timeline: currentVideo.red_flow_timeline,
|
|
49783
|
+
explanation: currentVideo.red_flow_explanation,
|
|
49784
|
+
aiSummary: currentLowEfficiencyAiSummary,
|
|
49785
|
+
aiSummaryLoading: isCurrentLowEfficiencyAiSummaryLoading,
|
|
49786
|
+
aiSummaryError: currentLowEfficiencyAiSummaryError,
|
|
49787
|
+
className: "right-8 top-8"
|
|
49788
|
+
}
|
|
49789
|
+
) : null,
|
|
49042
49790
|
showBlockingVideoLoader && !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..." }) }),
|
|
49043
49791
|
!shouldDeferPlayerRenderForCrop && !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..." }) }),
|
|
49044
49792
|
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 p-4 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
|
|
@@ -51061,8 +51809,8 @@ var IdleTimeReasonChartComponent = ({
|
|
|
51061
51809
|
updateAnimation = "replay",
|
|
51062
51810
|
variant = "pie"
|
|
51063
51811
|
}) => {
|
|
51064
|
-
const [activeData, setActiveData] =
|
|
51065
|
-
|
|
51812
|
+
const [activeData, setActiveData] = React148__default.useState([]);
|
|
51813
|
+
React148__default.useEffect(() => {
|
|
51066
51814
|
if (updateAnimation === "smooth") {
|
|
51067
51815
|
setActiveData(data && data.length > 0 ? data : []);
|
|
51068
51816
|
return;
|
|
@@ -51081,7 +51829,7 @@ var IdleTimeReasonChartComponent = ({
|
|
|
51081
51829
|
setActiveData([]);
|
|
51082
51830
|
}
|
|
51083
51831
|
}, [data, updateAnimation]);
|
|
51084
|
-
|
|
51832
|
+
React148__default.useEffect(() => {
|
|
51085
51833
|
if (!data || data.length === 0) return;
|
|
51086
51834
|
data.forEach((entry, index) => {
|
|
51087
51835
|
if (entry.name.toLowerCase().includes("other")) {
|
|
@@ -51089,7 +51837,7 @@ var IdleTimeReasonChartComponent = ({
|
|
|
51089
51837
|
}
|
|
51090
51838
|
});
|
|
51091
51839
|
}, [data]);
|
|
51092
|
-
const pieKey =
|
|
51840
|
+
const pieKey = React148__default.useMemo(() => {
|
|
51093
51841
|
if (updateAnimation === "smooth") {
|
|
51094
51842
|
return "smooth";
|
|
51095
51843
|
}
|
|
@@ -51259,7 +52007,7 @@ var IdleTimeReasonChartComponent = ({
|
|
|
51259
52007
|
)
|
|
51260
52008
|
] });
|
|
51261
52009
|
};
|
|
51262
|
-
var IdleTimeReasonChart =
|
|
52010
|
+
var IdleTimeReasonChart = React148__default.memo(IdleTimeReasonChartComponent);
|
|
51263
52011
|
IdleTimeReasonChart.displayName = "IdleTimeReasonChart";
|
|
51264
52012
|
var IdleTimeReasonChart_default = IdleTimeReasonChart;
|
|
51265
52013
|
|
|
@@ -53483,7 +54231,7 @@ var StatusIndicator = ({ status }) => {
|
|
|
53483
54231
|
case "bottleneck":
|
|
53484
54232
|
return /* @__PURE__ */ jsx(Zap, { className: "h-5 w-5 text-orange-400", "aria-label": "Bottleneck" });
|
|
53485
54233
|
case "lowEfficiency":
|
|
53486
|
-
return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5 text-red-400", "aria-label": "Low
|
|
54234
|
+
return /* @__PURE__ */ jsx(AlertTriangle, { className: "h-5 w-5 text-red-400", "aria-label": "Low moments" });
|
|
53487
54235
|
case "inactive":
|
|
53488
54236
|
return /* @__PURE__ */ jsx("div", { className: "h-3 w-3 bg-gray-400 rounded-full", title: "Inactive", "aria-label": "Inactive Workspace" });
|
|
53489
54237
|
default:
|
|
@@ -55786,13 +56534,13 @@ var WorkspaceCycleTimeMetricCards = ({
|
|
|
55786
56534
|
liveSkuId
|
|
55787
56535
|
}) => {
|
|
55788
56536
|
const effectiveLegend = legend || DEFAULT_EFFICIENCY_LEGEND;
|
|
55789
|
-
const activeSku =
|
|
56537
|
+
const activeSku = React148__default.useMemo(() => {
|
|
55790
56538
|
if (skuAware && activeSkuId && skuBreakdown) {
|
|
55791
56539
|
return skuBreakdown.find((s) => s.sku_id === activeSkuId);
|
|
55792
56540
|
}
|
|
55793
56541
|
return null;
|
|
55794
56542
|
}, [skuAware, activeSkuId, skuBreakdown]);
|
|
55795
|
-
const displaySku =
|
|
56543
|
+
const displaySku = React148__default.useMemo(() => {
|
|
55796
56544
|
if (activeSku) return activeSku;
|
|
55797
56545
|
if (skuAware && !activeSkuId && liveSkuId && skuBreakdown) {
|
|
55798
56546
|
return skuBreakdown.find((s) => s.sku_id === liveSkuId) ?? null;
|
|
@@ -56037,7 +56785,7 @@ var arePropsEqual = (prevProps, nextProps) => {
|
|
|
56037
56785
|
return prevProps.data.efficiency === nextProps.data.efficiency && prevProps.data.trend_score === nextProps.data.trend_score && prevProps.data.workspace_id === nextProps.data.workspace_id && prevProps.data.workspace_name === nextProps.data.workspace_name && prevProps.isBottleneck === nextProps.isBottleneck && prevProps.isLowEfficiency === nextProps.isLowEfficiency && prevProps.isVeryLowEfficiency === nextProps.isVeryLowEfficiency && prevLegend.green_min === nextLegend.green_min && prevLegend.green_max === nextLegend.green_max && prevLegend.yellow_min === nextLegend.yellow_min && prevLegend.yellow_max === nextLegend.yellow_max && prevLegend.red_min === nextLegend.red_min && prevLegend.red_max === nextLegend.red_max && prevLegend.critical_threshold === nextLegend.critical_threshold && // Position doesn't need deep equality check as it's generally static
|
|
56038
56786
|
prevProps.position.id === nextProps.position.id;
|
|
56039
56787
|
};
|
|
56040
|
-
var WorkspaceGridItem =
|
|
56788
|
+
var WorkspaceGridItem = React148__default.memo(({
|
|
56041
56789
|
data,
|
|
56042
56790
|
position,
|
|
56043
56791
|
isBottleneck = false,
|
|
@@ -56132,7 +56880,7 @@ var WorkspaceGridItem = React147__default.memo(({
|
|
|
56132
56880
|
);
|
|
56133
56881
|
}, arePropsEqual);
|
|
56134
56882
|
WorkspaceGridItem.displayName = "WorkspaceGridItem";
|
|
56135
|
-
var WorkspaceGrid =
|
|
56883
|
+
var WorkspaceGrid = React148__default.memo(({
|
|
56136
56884
|
workspaces,
|
|
56137
56885
|
blueComparisonWorkspaces,
|
|
56138
56886
|
isPdfMode = false,
|
|
@@ -56385,7 +57133,7 @@ var KPICard = ({
|
|
|
56385
57133
|
}) => {
|
|
56386
57134
|
useThemeConfig();
|
|
56387
57135
|
const { formatNumber } = useFormatNumber();
|
|
56388
|
-
const trendInfo =
|
|
57136
|
+
const trendInfo = React148__default.useMemo(() => {
|
|
56389
57137
|
let trendValue = trend || "neutral";
|
|
56390
57138
|
if (change !== void 0 && trend === void 0) {
|
|
56391
57139
|
trendValue = change > 0 ? "up" : change < 0 ? "down" : "neutral";
|
|
@@ -56412,7 +57160,7 @@ var KPICard = ({
|
|
|
56412
57160
|
const shouldShowTrend = !(change === 0 && trend === void 0);
|
|
56413
57161
|
return { trendValue, Icon: Icon2, colorClass, bgClass, shouldShowTrend };
|
|
56414
57162
|
}, [trend, change]);
|
|
56415
|
-
const formattedValue =
|
|
57163
|
+
const formattedValue = React148__default.useMemo(() => {
|
|
56416
57164
|
if (title === "Quality Compliance" && typeof value === "number") {
|
|
56417
57165
|
return value.toFixed(1);
|
|
56418
57166
|
}
|
|
@@ -56426,7 +57174,7 @@ var KPICard = ({
|
|
|
56426
57174
|
}
|
|
56427
57175
|
return value;
|
|
56428
57176
|
}, [value, title]);
|
|
56429
|
-
const formattedChange =
|
|
57177
|
+
const formattedChange = React148__default.useMemo(() => {
|
|
56430
57178
|
if (change === void 0 || change === 0 && !showZeroChange) return null;
|
|
56431
57179
|
const absChange = Math.abs(change);
|
|
56432
57180
|
return formatNumber(absChange, { minimumFractionDigits: 0, maximumFractionDigits: 1 });
|
|
@@ -57933,7 +58681,7 @@ var Breadcrumbs = ({ items }) => {
|
|
|
57933
58681
|
}
|
|
57934
58682
|
}
|
|
57935
58683
|
};
|
|
57936
|
-
return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(
|
|
58684
|
+
return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className: "mb-1 flex items-center space-x-1 text-xs font-medium text-gray-500 dark:text-gray-400", children: items.map((item, index) => /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
|
|
57937
58685
|
index > 0 && /* @__PURE__ */ jsx(ChevronRight, { className: "h-3 w-3 text-gray-400 dark:text-gray-500" }),
|
|
57938
58686
|
/* @__PURE__ */ jsxs(
|
|
57939
58687
|
"span",
|
|
@@ -59457,7 +60205,7 @@ var AwardBadge = ({
|
|
|
59457
60205
|
}) => {
|
|
59458
60206
|
const styles2 = getBadgeStyles(type);
|
|
59459
60207
|
const Icon2 = CustomIcon || getDefaultIcon(type);
|
|
59460
|
-
const randomDelay =
|
|
60208
|
+
const randomDelay = React148__default.useMemo(() => Math.random() * 2, []);
|
|
59461
60209
|
const floatingAnimation = {
|
|
59462
60210
|
animate: {
|
|
59463
60211
|
y: [0, -10, 0],
|
|
@@ -67826,7 +68574,7 @@ function HomeView({
|
|
|
67826
68574
|
animate: { opacity: 1, scale: 1 },
|
|
67827
68575
|
transition: { duration: 0.3 },
|
|
67828
68576
|
className: "h-full",
|
|
67829
|
-
children:
|
|
68577
|
+
children: React148__default.createElement(WorkspaceGrid, {
|
|
67830
68578
|
workspaces: workspaceMetricsWithBreakState,
|
|
67831
68579
|
blueComparisonWorkspaces: currentBlueComparisonWorkspaceMetrics || workspaceMetricsWithBreakState,
|
|
67832
68580
|
lineNames: mergedLineNames,
|
|
@@ -67859,7 +68607,7 @@ function HomeView({
|
|
|
67859
68607
|
animate: { opacity: 1, scale: 1 },
|
|
67860
68608
|
transition: { duration: 0.3 },
|
|
67861
68609
|
className: "h-full",
|
|
67862
|
-
children:
|
|
68610
|
+
children: React148__default.createElement(WorkspaceGrid, {
|
|
67863
68611
|
workspaces: [],
|
|
67864
68612
|
// Show empty grid while loading
|
|
67865
68613
|
blueComparisonWorkspaces: [],
|
|
@@ -67906,7 +68654,7 @@ function HomeView({
|
|
|
67906
68654
|
contentVariant: "plain"
|
|
67907
68655
|
}
|
|
67908
68656
|
),
|
|
67909
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxs(
|
|
68657
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: showAllGreenCelebration ? /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
|
|
67910
68658
|
/* @__PURE__ */ jsx(
|
|
67911
68659
|
motion.div,
|
|
67912
68660
|
{
|
|
@@ -67985,7 +68733,7 @@ function HomeView({
|
|
|
67985
68733
|
"all-green-center-toast"
|
|
67986
68734
|
)
|
|
67987
68735
|
] }, "all-green-celebration") : null }),
|
|
67988
|
-
/* @__PURE__ */ jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxs(
|
|
68736
|
+
/* @__PURE__ */ jsx(AnimatePresence, { children: greenStreakMilestoneBanner ? /* @__PURE__ */ jsxs(React148__default.Fragment, { children: [
|
|
67989
68737
|
/* @__PURE__ */ jsx(
|
|
67990
68738
|
motion.div,
|
|
67991
68739
|
{
|
|
@@ -68079,7 +68827,7 @@ function HomeView({
|
|
|
68079
68827
|
}
|
|
68080
68828
|
);
|
|
68081
68829
|
}
|
|
68082
|
-
var AuthenticatedHomeView = withAuth(
|
|
68830
|
+
var AuthenticatedHomeView = withAuth(React148__default.memo(HomeView));
|
|
68083
68831
|
var HomeView_default = HomeView;
|
|
68084
68832
|
function withWorkspaceDisplayNames(Component3, options = {}) {
|
|
68085
68833
|
const {
|
|
@@ -71428,7 +72176,14 @@ var formatSupervisorFirstNames = (supervisors, fallbackSupervisorNames) => {
|
|
|
71428
72176
|
return fallbackFirstNames.length > 0 ? Array.from(new Set(fallbackFirstNames)).join(", ") : "Unassigned";
|
|
71429
72177
|
};
|
|
71430
72178
|
var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Finished", placeholder = "--", onFinished }) => {
|
|
71431
|
-
const [time2, setTime] = useState(
|
|
72179
|
+
const [time2, setTime] = useState(() => {
|
|
72180
|
+
if (!targetDate) return "";
|
|
72181
|
+
return targetDate.getTime() <= Date.now() ? finishedLabel : "";
|
|
72182
|
+
});
|
|
72183
|
+
const [showEndsInPrefix, setShowEndsInPrefix] = useState(() => {
|
|
72184
|
+
if (!targetDate) return true;
|
|
72185
|
+
return targetDate.getTime() > Date.now();
|
|
72186
|
+
});
|
|
71432
72187
|
const hasFinishedRef = useRef(false);
|
|
71433
72188
|
useEffect(() => {
|
|
71434
72189
|
hasFinishedRef.current = false;
|
|
@@ -71436,12 +72191,14 @@ var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Fin
|
|
|
71436
72191
|
useEffect(() => {
|
|
71437
72192
|
if (!targetDate) {
|
|
71438
72193
|
setTime(placeholder);
|
|
72194
|
+
setShowEndsInPrefix(true);
|
|
71439
72195
|
return;
|
|
71440
72196
|
}
|
|
71441
72197
|
const tick = () => {
|
|
71442
72198
|
const now4 = /* @__PURE__ */ new Date();
|
|
71443
72199
|
const diff = targetDate.getTime() - now4.getTime();
|
|
71444
72200
|
if (diff <= 0) {
|
|
72201
|
+
setShowEndsInPrefix(false);
|
|
71445
72202
|
setTime(finishedLabel);
|
|
71446
72203
|
if (!hasFinishedRef.current && onFinished) {
|
|
71447
72204
|
hasFinishedRef.current = true;
|
|
@@ -71449,6 +72206,7 @@ var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Fin
|
|
|
71449
72206
|
}
|
|
71450
72207
|
return;
|
|
71451
72208
|
}
|
|
72209
|
+
setShowEndsInPrefix(true);
|
|
71452
72210
|
if (format10 === "days") {
|
|
71453
72211
|
const days = Math.floor(diff / (1e3 * 60 * 60 * 24));
|
|
71454
72212
|
const hours = Math.floor(diff % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60));
|
|
@@ -71465,7 +72223,10 @@ var LeaderboardCountdown = ({ targetDate, format: format10, finishedLabel = "Fin
|
|
|
71465
72223
|
const interval = setInterval(tick, 1e3);
|
|
71466
72224
|
return () => clearInterval(interval);
|
|
71467
72225
|
}, [targetDate, format10, finishedLabel, placeholder, onFinished]);
|
|
71468
|
-
return /* @__PURE__ */
|
|
72226
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
72227
|
+
showEndsInPrefix && /* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-gray-400 uppercase tracking-wider", children: "Ends in" }),
|
|
72228
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-bold text-gray-900 tabular-nums tracking-tight font-mono", children: time2 })
|
|
72229
|
+
] });
|
|
71469
72230
|
};
|
|
71470
72231
|
var LinesLeaderboard = ({
|
|
71471
72232
|
lines,
|
|
@@ -71488,18 +72249,18 @@ var LinesLeaderboard = ({
|
|
|
71488
72249
|
isHistoricalDaily
|
|
71489
72250
|
}) => {
|
|
71490
72251
|
const formatEfficiency = (value) => typeof value === "number" && Number.isFinite(value) ? `${value.toFixed(1)}%` : "--";
|
|
71491
|
-
const assignedLineIdSet =
|
|
72252
|
+
const assignedLineIdSet = React148__default.useMemo(
|
|
71492
72253
|
() => new Set(assignedLineIds || []),
|
|
71493
72254
|
[assignedLineIds]
|
|
71494
72255
|
);
|
|
71495
|
-
const canClickLine =
|
|
72256
|
+
const canClickLine = React148__default.useCallback(
|
|
71496
72257
|
(lineId) => {
|
|
71497
72258
|
if (!assignedLineIds) return true;
|
|
71498
72259
|
return assignedLineIdSet.has(lineId);
|
|
71499
72260
|
},
|
|
71500
72261
|
[assignedLineIds, assignedLineIdSet]
|
|
71501
72262
|
);
|
|
71502
|
-
const handleTimeRangeChange =
|
|
72263
|
+
const handleTimeRangeChange = React148__default.useCallback((newRange) => {
|
|
71503
72264
|
if (newRange === timeRange) return;
|
|
71504
72265
|
trackCoreEvent("Leaderboard Time Range Changed", {
|
|
71505
72266
|
from_range: timeRange,
|
|
@@ -71510,11 +72271,11 @@ var LinesLeaderboard = ({
|
|
|
71510
72271
|
});
|
|
71511
72272
|
setTimeRange(newRange);
|
|
71512
72273
|
}, [timeRange, lines.length, monthlyEfficiencyByLineId, setTimeRange]);
|
|
71513
|
-
const canClickLeaderboardRow =
|
|
72274
|
+
const canClickLeaderboardRow = React148__default.useCallback(
|
|
71514
72275
|
(item) => item.rowType === "line" && !!item.line && canClickLine(item.line.id),
|
|
71515
72276
|
[canClickLine]
|
|
71516
72277
|
);
|
|
71517
|
-
const handleLeaderboardLineClick =
|
|
72278
|
+
const handleLeaderboardLineClick = React148__default.useCallback((item, clickSource) => {
|
|
71518
72279
|
if (!canClickLeaderboardRow(item) || !item.line) return;
|
|
71519
72280
|
trackCoreEvent("Leaderboard Line Clicked", {
|
|
71520
72281
|
line_id: item.line.id,
|
|
@@ -71528,8 +72289,8 @@ var LinesLeaderboard = ({
|
|
|
71528
72289
|
});
|
|
71529
72290
|
onLineClick(item.line);
|
|
71530
72291
|
}, [canClickLeaderboardRow, onLineClick, timeRange]);
|
|
71531
|
-
const viewLoadedTrackedRef =
|
|
71532
|
-
const leaderboardData =
|
|
72292
|
+
const viewLoadedTrackedRef = React148__default.useRef(null);
|
|
72293
|
+
const leaderboardData = React148__default.useMemo(() => {
|
|
71533
72294
|
const loading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
|
|
71534
72295
|
const efficiencyMap = timeRange === "today" ? todayEfficiencyByLineId : monthlyEfficiencyByLineId;
|
|
71535
72296
|
const fallbackEfficiencyMap = timeRange === "today" ? dailyFallbackEfficiencyByLineId : void 0;
|
|
@@ -71573,7 +72334,7 @@ var LinesLeaderboard = ({
|
|
|
71573
72334
|
isLoadingToday,
|
|
71574
72335
|
isLoadingMonthly
|
|
71575
72336
|
]);
|
|
71576
|
-
|
|
72337
|
+
React148__default.useEffect(() => {
|
|
71577
72338
|
const isLoading = timeRange === "today" ? isLoadingToday : isLoadingMonthly;
|
|
71578
72339
|
const trackingKey = `${timeRange}-${leaderboardData.length}`;
|
|
71579
72340
|
if (leaderboardData.length > 0 && !isLoading && viewLoadedTrackedRef.current !== trackingKey) {
|
|
@@ -71597,9 +72358,9 @@ var LinesLeaderboard = ({
|
|
|
71597
72358
|
const topThree = leaderboardData.slice(0, 3);
|
|
71598
72359
|
const countdownTarget = timeRange === "monthly" ? monthEndDate : shiftEndDate;
|
|
71599
72360
|
const countdownFormat = timeRange === "monthly" ? "days" : "clock";
|
|
71600
|
-
const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift
|
|
72361
|
+
const countdownFinishedLabel = timeRange === "monthly" ? "Finished" : "Shift ended";
|
|
71601
72362
|
const showCountdown = timeRange === "monthly" || !isHistoricalDaily;
|
|
71602
|
-
const handleCountdownFinished =
|
|
72363
|
+
const handleCountdownFinished = React148__default.useCallback(() => {
|
|
71603
72364
|
trackCoreEvent("Leaderboard Countdown Finished", {
|
|
71604
72365
|
countdown_type: timeRange === "monthly" ? "month_end" : "shift_end",
|
|
71605
72366
|
time_range: timeRange,
|
|
@@ -71626,7 +72387,7 @@ var LinesLeaderboard = ({
|
|
|
71626
72387
|
return "bg-white border-gray-100";
|
|
71627
72388
|
}
|
|
71628
72389
|
};
|
|
71629
|
-
|
|
72390
|
+
React148__default.useEffect(() => {
|
|
71630
72391
|
const style = document.createElement("style");
|
|
71631
72392
|
style.innerHTML = `
|
|
71632
72393
|
@keyframes float {
|
|
@@ -71674,19 +72435,16 @@ var LinesLeaderboard = ({
|
|
|
71674
72435
|
] }),
|
|
71675
72436
|
/* @__PURE__ */ jsx("div", { className: "md:absolute md:right-0 md:top-1/2 md:-translate-y-1/2 flex flex-wrap items-center justify-center md:justify-end gap-2", children: showCountdown && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2.5 px-4 py-2 bg-white rounded-full shadow-sm border border-gray-100", children: [
|
|
71676
72437
|
/* @__PURE__ */ jsx(Clock, { className: "w-4 h-4 text-orange-500" }),
|
|
71677
|
-
/* @__PURE__ */
|
|
71678
|
-
|
|
71679
|
-
|
|
71680
|
-
|
|
71681
|
-
|
|
71682
|
-
|
|
71683
|
-
|
|
71684
|
-
|
|
71685
|
-
|
|
71686
|
-
|
|
71687
|
-
}
|
|
71688
|
-
) })
|
|
71689
|
-
] })
|
|
72438
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-baseline gap-2", children: /* @__PURE__ */ jsx(
|
|
72439
|
+
LeaderboardCountdown,
|
|
72440
|
+
{
|
|
72441
|
+
targetDate: countdownTarget,
|
|
72442
|
+
format: countdownFormat,
|
|
72443
|
+
finishedLabel: countdownFinishedLabel,
|
|
72444
|
+
placeholder: timeRange === "monthly" ? "--" : "--:--:--",
|
|
72445
|
+
onFinished: handleCountdownFinished
|
|
72446
|
+
}
|
|
72447
|
+
) })
|
|
71690
72448
|
] }) })
|
|
71691
72449
|
] }),
|
|
71692
72450
|
/* @__PURE__ */ jsx("div", { className: "flex-1 hidden sm:flex justify-center items-end gap-2 md:gap-4 lg:gap-6 xl:gap-10 pb-4 pt-4 min-h-0", children: podiumOrder.map((item, index) => {
|
|
@@ -72128,36 +72886,36 @@ var KPIsOverviewView = ({
|
|
|
72128
72886
|
const configuredTimezone = dbTimezone || dateTimeConfig.defaultTimezone || "UTC";
|
|
72129
72887
|
const { startDate: monthStartDate, endDate: monthEndDateKey, monthEndDate } = getMonthDateInfo(configuredTimezone);
|
|
72130
72888
|
const isSuperAdmin = user?.scope_mode === "SUPER_ADMIN" || !!user?.access_scope?.is_super_admin;
|
|
72131
|
-
const scopedLineIds =
|
|
72889
|
+
const scopedLineIds = React148__default.useMemo(
|
|
72132
72890
|
() => Array.isArray(user?.access_scope?.line_ids) ? user.access_scope.line_ids.filter((lineId) => typeof lineId === "string" && lineId.length > 0) : [],
|
|
72133
72891
|
[user?.access_scope?.line_ids]
|
|
72134
72892
|
);
|
|
72135
72893
|
const hasCanonicalScope = !!user?.scope_mode || !!user?.access_scope;
|
|
72136
72894
|
const scopeRole = (user?.role_level || user?.role || "").toLowerCase();
|
|
72137
72895
|
const isStrictLineScopedRole = scopeRole === "supervisor" || isFactoryScopedRole(scopeRole);
|
|
72138
|
-
const resolvedAssignedLineIds =
|
|
72896
|
+
const resolvedAssignedLineIds = React148__default.useMemo(() => {
|
|
72139
72897
|
if (isSuperAdmin) return [];
|
|
72140
72898
|
if (scopedLineIds.length > 0) return scopedLineIds;
|
|
72141
72899
|
if (lineIds && lineIds.length > 0) return lineIds;
|
|
72142
72900
|
if (isStrictLineScopedRole && hasCanonicalScope) return [];
|
|
72143
72901
|
return [];
|
|
72144
72902
|
}, [isSuperAdmin, scopedLineIds, lineIds, isStrictLineScopedRole, hasCanonicalScope]);
|
|
72145
|
-
const assignedLineIdSet =
|
|
72903
|
+
const assignedLineIdSet = React148__default.useMemo(
|
|
72146
72904
|
() => new Set(resolvedAssignedLineIds),
|
|
72147
72905
|
[resolvedAssignedLineIds]
|
|
72148
72906
|
);
|
|
72149
|
-
const loadedLineIds =
|
|
72907
|
+
const loadedLineIds = React148__default.useMemo(
|
|
72150
72908
|
() => lines.map((line) => line.id).filter(Boolean),
|
|
72151
72909
|
[lines]
|
|
72152
72910
|
);
|
|
72153
|
-
const metricsLineIds =
|
|
72911
|
+
const metricsLineIds = React148__default.useMemo(() => {
|
|
72154
72912
|
if (isSuperAdmin) {
|
|
72155
72913
|
return loadedLineIds.length > 0 ? loadedLineIds : lineIds ?? [];
|
|
72156
72914
|
}
|
|
72157
72915
|
return resolvedAssignedLineIds;
|
|
72158
72916
|
}, [isSuperAdmin, loadedLineIds, lineIds, resolvedAssignedLineIds]);
|
|
72159
72917
|
const assignedLineIdsForLeaderboard = isSuperAdmin ? void 0 : resolvedAssignedLineIds;
|
|
72160
|
-
const leaderboardLinesForView =
|
|
72918
|
+
const leaderboardLinesForView = React148__default.useMemo(() => {
|
|
72161
72919
|
const targetMode = viewType === "machine" ? "uptime" : "output";
|
|
72162
72920
|
const metadataByLineId = new Map(lines.map((line) => [line.id, line]));
|
|
72163
72921
|
return leaderboardLines.map((line) => {
|
|
@@ -72176,17 +72934,17 @@ var KPIsOverviewView = ({
|
|
|
72176
72934
|
} : line;
|
|
72177
72935
|
}).filter((line) => (line.monitoring_mode ?? "output") === targetMode);
|
|
72178
72936
|
}, [leaderboardLines, lines, viewType]);
|
|
72179
|
-
const linesForView =
|
|
72937
|
+
const linesForView = React148__default.useMemo(() => {
|
|
72180
72938
|
const targetMode = viewType === "machine" ? "uptime" : "output";
|
|
72181
72939
|
return lines.filter((line) => (line.monitoring_mode ?? "output") === targetMode);
|
|
72182
72940
|
}, [lines, viewType]);
|
|
72183
|
-
const relevantLinesForMode =
|
|
72941
|
+
const relevantLinesForMode = React148__default.useMemo(() => {
|
|
72184
72942
|
if (activeTab === "leaderboard") {
|
|
72185
72943
|
return leaderboardLines.length > 0 ? leaderboardLines : lines;
|
|
72186
72944
|
}
|
|
72187
72945
|
return lines;
|
|
72188
72946
|
}, [activeTab, leaderboardLines, lines]);
|
|
72189
|
-
const { hasUptime, hasOutput } =
|
|
72947
|
+
const { hasUptime, hasOutput } = React148__default.useMemo(() => {
|
|
72190
72948
|
let uptime = false;
|
|
72191
72949
|
let output = false;
|
|
72192
72950
|
for (const line of relevantLinesForMode) {
|
|
@@ -72211,14 +72969,14 @@ var KPIsOverviewView = ({
|
|
|
72211
72969
|
const currentShiftDetails = getCurrentShift(configuredTimezone, shiftConfig);
|
|
72212
72970
|
const currentShiftDate = currentShiftDetails.date;
|
|
72213
72971
|
const currentShiftId = currentShiftDetails.shiftId;
|
|
72214
|
-
const activeFiltersCount =
|
|
72972
|
+
const activeFiltersCount = React148__default.useMemo(() => {
|
|
72215
72973
|
let count = 0;
|
|
72216
72974
|
if (leaderboardDailyScopeMode === "historical" && selectedLeaderboardShiftId !== currentShiftId) {
|
|
72217
72975
|
count++;
|
|
72218
72976
|
}
|
|
72219
72977
|
return count;
|
|
72220
72978
|
}, [leaderboardDailyScopeMode, selectedLeaderboardShiftId, currentShiftId]);
|
|
72221
|
-
const clearFilters =
|
|
72979
|
+
const clearFilters = React148__default.useCallback(() => {
|
|
72222
72980
|
setSelectedLeaderboardShiftId(currentShiftId);
|
|
72223
72981
|
setSelectedLeaderboardDate(currentShiftDate);
|
|
72224
72982
|
setLeaderboardDailyScopeMode("live");
|
|
@@ -72234,11 +72992,11 @@ var KPIsOverviewView = ({
|
|
|
72234
72992
|
document.addEventListener("mousedown", handleClickOutside);
|
|
72235
72993
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
72236
72994
|
}, []);
|
|
72237
|
-
const shiftEndDate =
|
|
72995
|
+
const shiftEndDate = React148__default.useMemo(
|
|
72238
72996
|
() => getShiftEndDate(currentShiftDetails, configuredTimezone),
|
|
72239
72997
|
[currentShiftDetails, configuredTimezone]
|
|
72240
72998
|
);
|
|
72241
|
-
const leaderboardShiftOptions =
|
|
72999
|
+
const leaderboardShiftOptions = React148__default.useMemo(() => {
|
|
72242
73000
|
if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
|
|
72243
73001
|
return shiftConfig.shifts.map((shift) => ({
|
|
72244
73002
|
id: shift.shiftId,
|
|
@@ -72255,34 +73013,34 @@ var KPIsOverviewView = ({
|
|
|
72255
73013
|
const effectiveLeaderboardDate = selectedLeaderboardDate || currentShiftDate;
|
|
72256
73014
|
const effectiveLeaderboardShiftId = Number.isFinite(selectedLeaderboardShiftId) ? selectedLeaderboardShiftId : currentShiftId;
|
|
72257
73015
|
const isHistoricalLeaderboardDaily = activeTab === "leaderboard" && timeRange === "today" && leaderboardDailyScopeMode === "historical" && (effectiveLeaderboardDate !== currentShiftDate || effectiveLeaderboardShiftId !== currentShiftId);
|
|
72258
|
-
const updateLeaderboardDate =
|
|
73016
|
+
const updateLeaderboardDate = React148__default.useCallback((dateKey) => {
|
|
72259
73017
|
setSelectedLeaderboardDate(dateKey);
|
|
72260
73018
|
setLeaderboardDailyScopeMode(
|
|
72261
73019
|
dateKey === currentShiftDate && effectiveLeaderboardShiftId === currentShiftId ? "live" : "historical"
|
|
72262
73020
|
);
|
|
72263
73021
|
}, [currentShiftDate, currentShiftId, effectiveLeaderboardShiftId]);
|
|
72264
|
-
const updateLeaderboardShiftId =
|
|
73022
|
+
const updateLeaderboardShiftId = React148__default.useCallback((shiftId) => {
|
|
72265
73023
|
setSelectedLeaderboardShiftId(shiftId);
|
|
72266
73024
|
setLeaderboardDailyScopeMode(
|
|
72267
73025
|
effectiveLeaderboardDate === currentShiftDate && shiftId === currentShiftId ? "live" : "historical"
|
|
72268
73026
|
);
|
|
72269
73027
|
}, [currentShiftDate, currentShiftId, effectiveLeaderboardDate]);
|
|
72270
|
-
const returnLeaderboardToLive =
|
|
73028
|
+
const returnLeaderboardToLive = React148__default.useCallback(() => {
|
|
72271
73029
|
setSelectedLeaderboardDate(currentShiftDate);
|
|
72272
73030
|
setSelectedLeaderboardShiftId(currentShiftId);
|
|
72273
73031
|
setLeaderboardDailyScopeMode("live");
|
|
72274
73032
|
}, [currentShiftDate, currentShiftId]);
|
|
72275
73033
|
const selectedFactoryIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_QUERY_PARAM]);
|
|
72276
73034
|
const selectedFactoryAreaIdFromUrl = getSingleQueryValue(router.query[KPI_FACTORY_AREA_QUERY_PARAM]);
|
|
72277
|
-
const kpiLineHierarchy =
|
|
73035
|
+
const kpiLineHierarchy = React148__default.useMemo(
|
|
72278
73036
|
() => buildKpiLineHierarchy(linesForView),
|
|
72279
73037
|
[linesForView]
|
|
72280
73038
|
);
|
|
72281
|
-
const selectedFactoryNode =
|
|
73039
|
+
const selectedFactoryNode = React148__default.useMemo(
|
|
72282
73040
|
() => kpiLineHierarchy.showFactoryLevel && selectedFactoryIdFromUrl ? kpiLineHierarchy.factories.find((factory) => factory.id === selectedFactoryIdFromUrl) : void 0,
|
|
72283
73041
|
[kpiLineHierarchy, selectedFactoryIdFromUrl]
|
|
72284
73042
|
);
|
|
72285
|
-
const selectedFactoryAreaNode =
|
|
73043
|
+
const selectedFactoryAreaNode = React148__default.useMemo(
|
|
72286
73044
|
() => selectedFactoryNode && selectedFactoryAreaIdFromUrl ? selectedFactoryNode.areas.find((area) => area.id === selectedFactoryAreaIdFromUrl) : void 0,
|
|
72287
73045
|
[selectedFactoryNode, selectedFactoryAreaIdFromUrl]
|
|
72288
73046
|
);
|
|
@@ -72371,15 +73129,15 @@ var KPIsOverviewView = ({
|
|
|
72371
73129
|
lineId: factoryViewId,
|
|
72372
73130
|
userAccessibleLineIds: metricsLineIds
|
|
72373
73131
|
});
|
|
72374
|
-
const defaultKPIs =
|
|
72375
|
-
const lineModeById =
|
|
73132
|
+
const defaultKPIs = React148__default.useMemo(() => createDefaultKPIs(), []);
|
|
73133
|
+
const lineModeById = React148__default.useMemo(() => {
|
|
72376
73134
|
const map = /* @__PURE__ */ new Map();
|
|
72377
73135
|
linesForView.forEach((line) => {
|
|
72378
73136
|
map.set(line.id, line.monitoring_mode ?? "output");
|
|
72379
73137
|
});
|
|
72380
73138
|
return map;
|
|
72381
73139
|
}, [linesForView]);
|
|
72382
|
-
const lineMetricRowsByLineId =
|
|
73140
|
+
const lineMetricRowsByLineId = React148__default.useMemo(() => {
|
|
72383
73141
|
const map = /* @__PURE__ */ new Map();
|
|
72384
73142
|
lineMetrics.forEach((row) => {
|
|
72385
73143
|
if (!row?.line_id) return;
|
|
@@ -72391,7 +73149,7 @@ var KPIsOverviewView = ({
|
|
|
72391
73149
|
});
|
|
72392
73150
|
return map;
|
|
72393
73151
|
}, [lineMetrics, lineModeById]);
|
|
72394
|
-
const liveDailyFallbackEfficiencyByLineId =
|
|
73152
|
+
const liveDailyFallbackEfficiencyByLineId = React148__default.useMemo(() => {
|
|
72395
73153
|
const map = /* @__PURE__ */ new Map();
|
|
72396
73154
|
lineMetricRowsByLineId.forEach((row, lineId) => {
|
|
72397
73155
|
const value = Number(row?.avg_efficiency);
|
|
@@ -72413,31 +73171,31 @@ var KPIsOverviewView = ({
|
|
|
72413
73171
|
isHistoricalLeaderboardDaily,
|
|
72414
73172
|
lineMetricRowsByLineId
|
|
72415
73173
|
]);
|
|
72416
|
-
const dailyFallbackEfficiencyByLineId =
|
|
73174
|
+
const dailyFallbackEfficiencyByLineId = React148__default.useMemo(() => {
|
|
72417
73175
|
const map = new Map(liveDailyFallbackEfficiencyByLineId);
|
|
72418
73176
|
scopedDailyFallbackEfficiencyByLineId.forEach((value, lineId) => {
|
|
72419
73177
|
map.set(lineId, value);
|
|
72420
73178
|
});
|
|
72421
73179
|
return map;
|
|
72422
73180
|
}, [liveDailyFallbackEfficiencyByLineId, scopedDailyFallbackEfficiencyByLineId]);
|
|
72423
|
-
const kpisByLineId =
|
|
73181
|
+
const kpisByLineId = React148__default.useMemo(() => {
|
|
72424
73182
|
const map = /* @__PURE__ */ new Map();
|
|
72425
73183
|
lineMetricRowsByLineId.forEach((row, lineId) => {
|
|
72426
73184
|
map.set(lineId, buildKPIsFromLineMetricsRow(row));
|
|
72427
73185
|
});
|
|
72428
73186
|
return map;
|
|
72429
73187
|
}, [lineMetricRowsByLineId]);
|
|
72430
|
-
const getLineCardKpis =
|
|
73188
|
+
const getLineCardKpis = React148__default.useCallback((line) => {
|
|
72431
73189
|
if (metricsError) return null;
|
|
72432
73190
|
return kpisByLineId.get(line.id) ?? (metricsLoading ? null : defaultKPIs);
|
|
72433
73191
|
}, [defaultKPIs, kpisByLineId, metricsError, metricsLoading]);
|
|
72434
|
-
const getAggregateCardKpis =
|
|
73192
|
+
const getAggregateCardKpis = React148__default.useCallback((cardLines) => {
|
|
72435
73193
|
if (metricsError) return null;
|
|
72436
73194
|
const rows = cardLines.map((line) => lineMetricRowsByLineId.get(line.id)).filter(Boolean);
|
|
72437
73195
|
if (metricsLoading && rows.length === 0) return null;
|
|
72438
73196
|
return aggregateKPIsFromLineMetricsRows(rows);
|
|
72439
73197
|
}, [lineMetricRowsByLineId, metricsError, metricsLoading]);
|
|
72440
|
-
const supervisorLineIds =
|
|
73198
|
+
const supervisorLineIds = React148__default.useMemo(
|
|
72441
73199
|
() => (leaderboardLines.length > 0 ? leaderboardLines : lines).map((l) => l.id),
|
|
72442
73200
|
[leaderboardLines, lines]
|
|
72443
73201
|
);
|
|
@@ -72689,7 +73447,7 @@ var KPIsOverviewView = ({
|
|
|
72689
73447
|
{ shallow: true }
|
|
72690
73448
|
);
|
|
72691
73449
|
}, [router]);
|
|
72692
|
-
const lineDetailReturnTo =
|
|
73450
|
+
const lineDetailReturnTo = React148__default.useMemo(() => {
|
|
72693
73451
|
if (activeTab !== "today" || !selectedFactoryNode) return void 0;
|
|
72694
73452
|
return createKpisOverviewUrl({
|
|
72695
73453
|
factoryId: selectedFactoryNode.id,
|
|
@@ -73489,7 +74247,7 @@ var LeaderboardDetailView = memo$1(({
|
|
|
73489
74247
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
73490
74248
|
}, []);
|
|
73491
74249
|
const [isMobile, setIsMobile] = useState(false);
|
|
73492
|
-
|
|
74250
|
+
React148__default.useEffect(() => {
|
|
73493
74251
|
const checkMobile = () => setIsMobile(window.innerWidth < 640);
|
|
73494
74252
|
checkMobile();
|
|
73495
74253
|
window.addEventListener("resize", checkMobile);
|
|
@@ -77539,7 +78297,7 @@ var ShiftsView = ({
|
|
|
77539
78297
|
] })
|
|
77540
78298
|
] });
|
|
77541
78299
|
};
|
|
77542
|
-
var AuthenticatedShiftsView = withAuth(
|
|
78300
|
+
var AuthenticatedShiftsView = withAuth(React148__default.memo(ShiftsView));
|
|
77543
78301
|
var ShiftsView_default = ShiftsView;
|
|
77544
78302
|
|
|
77545
78303
|
// src/views/TargetsView.utils.ts
|
|
@@ -79406,7 +80164,7 @@ var TargetsView = ({
|
|
|
79406
80164
|
};
|
|
79407
80165
|
var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
|
|
79408
80166
|
var TargetsView_default = TargetsViewWithDisplayNames;
|
|
79409
|
-
var AuthenticatedTargetsView = withAuth(
|
|
80167
|
+
var AuthenticatedTargetsView = withAuth(React148__default.memo(TargetsViewWithDisplayNames));
|
|
79410
80168
|
function useTimezone(options = {}) {
|
|
79411
80169
|
const dashboardConfig = useDashboardConfig();
|
|
79412
80170
|
const workspaceConfig = useWorkspaceConfig();
|
|
@@ -79554,7 +80312,7 @@ var formatWholeNumber = (value) => {
|
|
|
79554
80312
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
79555
80313
|
return Math.round(value).toLocaleString();
|
|
79556
80314
|
};
|
|
79557
|
-
var
|
|
80315
|
+
var formatSeconds2 = (value) => {
|
|
79558
80316
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
79559
80317
|
return `${value.toFixed(1)}s`;
|
|
79560
80318
|
};
|
|
@@ -79571,13 +80329,13 @@ var WorkspaceHourSummaryPanel = ({
|
|
|
79571
80329
|
}) => {
|
|
79572
80330
|
const { data, isLoading, error, summarize, reset } = useWorkspaceHourSummary();
|
|
79573
80331
|
const selectedKey = selectedHour ? `${selectedHour.source}:${selectedHour.hourIndex}:${date}:${shiftId}` : "none";
|
|
79574
|
-
const autoSummaryKeyRef =
|
|
79575
|
-
|
|
80332
|
+
const autoSummaryKeyRef = React148__default.useRef(null);
|
|
80333
|
+
React148__default.useEffect(() => {
|
|
79576
80334
|
reset();
|
|
79577
80335
|
autoSummaryKeyRef.current = null;
|
|
79578
80336
|
}, [reset, selectedKey]);
|
|
79579
80337
|
const canSummarize = Boolean(workspaceId && companyId && date && shiftId !== null && shiftId !== void 0);
|
|
79580
|
-
|
|
80338
|
+
React148__default.useEffect(() => {
|
|
79581
80339
|
if (!selectedHour || !canSummarize || !companyId || !date || shiftId === null || shiftId === void 0) {
|
|
79582
80340
|
return;
|
|
79583
80341
|
}
|
|
@@ -79606,8 +80364,8 @@ var WorkspaceHourSummaryPanel = ({
|
|
|
79606
80364
|
const formattedTimeRange = formatTimeRangeTo12Hour(verifiedTimeRange);
|
|
79607
80365
|
const selectedMetric = selectedHour.source === "cycle" ? {
|
|
79608
80366
|
label: "Cycle time",
|
|
79609
|
-
actual:
|
|
79610
|
-
standard:
|
|
80367
|
+
actual: formatSeconds2(selectedHour.cycleTime),
|
|
80368
|
+
standard: formatSeconds2(selectedHour.idealCycleTime)
|
|
79611
80369
|
} : {
|
|
79612
80370
|
label: "Hourly output",
|
|
79613
80371
|
actual: formatWholeNumber(selectedHour.output),
|
|
@@ -79783,6 +80541,7 @@ var WorkspaceDetailView = ({
|
|
|
79783
80541
|
const { legend: efficiencyLegend } = useEfficiencyLegend();
|
|
79784
80542
|
const prewarmedClipsRef = useRef(/* @__PURE__ */ new Set());
|
|
79785
80543
|
const prewarmInFlightRef = useRef(/* @__PURE__ */ new Set());
|
|
80544
|
+
const [lowMomentsPrefetch, setLowMomentsPrefetch] = useState(null);
|
|
79786
80545
|
const [aiSummaryHour, setAiSummaryHour] = useState(null);
|
|
79787
80546
|
const buildHourlyOutputActionTrackingProps = useCallback((payload) => ({
|
|
79788
80547
|
workspace_id: workspaceId,
|
|
@@ -80295,13 +81054,108 @@ var WorkspaceDetailView = ({
|
|
|
80295
81054
|
}
|
|
80296
81055
|
prewarmInFlightRef.current.add(cacheKey);
|
|
80297
81056
|
const s3Service = videoPrefetchManager.getS3Service(dashboardConfig);
|
|
80298
|
-
|
|
80299
|
-
|
|
80300
|
-
|
|
80301
|
-
|
|
80302
|
-
|
|
80303
|
-
|
|
80304
|
-
|
|
81057
|
+
const controller = new AbortController();
|
|
81058
|
+
let cancelled = false;
|
|
81059
|
+
const prefetchLowMoments = async () => {
|
|
81060
|
+
try {
|
|
81061
|
+
const initData = await s3Service.getClipsInit(workspaceId, resolvedDate, resolvedShiftId, totalOutput);
|
|
81062
|
+
const lowMomentsCount = Number(initData?.counts?.recent_flow_red_streak || 0);
|
|
81063
|
+
const lowMomentsKey = [
|
|
81064
|
+
"recent_flow_red_streak",
|
|
81065
|
+
resolvedDate,
|
|
81066
|
+
resolvedShiftId,
|
|
81067
|
+
initData?.snapshotDateTime ?? "nosnap",
|
|
81068
|
+
initData?.snapshotClipId ?? "nosnap",
|
|
81069
|
+
"red_flow_output_shortfall_desc"
|
|
81070
|
+
].join("-");
|
|
81071
|
+
if (cancelled) {
|
|
81072
|
+
return;
|
|
81073
|
+
}
|
|
81074
|
+
const initFirstVideo = initData?.firstClips?.recent_flow_red_streak ?? null;
|
|
81075
|
+
if (lowMomentsCount <= 0) {
|
|
81076
|
+
setLowMomentsPrefetch((prev) => prev?.key === lowMomentsKey ? {
|
|
81077
|
+
key: lowMomentsKey,
|
|
81078
|
+
metadata: [],
|
|
81079
|
+
firstVideo: null,
|
|
81080
|
+
total: 0,
|
|
81081
|
+
loading: false,
|
|
81082
|
+
error: null
|
|
81083
|
+
} : prev);
|
|
81084
|
+
prewarmedClipsRef.current.add(cacheKey);
|
|
81085
|
+
return;
|
|
81086
|
+
}
|
|
81087
|
+
setLowMomentsPrefetch((prev) => {
|
|
81088
|
+
if (prev?.key === lowMomentsKey && !prev.loading && prev.metadata.length > 0) {
|
|
81089
|
+
return prev;
|
|
81090
|
+
}
|
|
81091
|
+
return {
|
|
81092
|
+
key: lowMomentsKey,
|
|
81093
|
+
metadata: prev?.key === lowMomentsKey ? prev.metadata : [],
|
|
81094
|
+
firstVideo: prev?.key === lowMomentsKey ? prev.firstVideo || initFirstVideo : initFirstVideo,
|
|
81095
|
+
total: lowMomentsCount,
|
|
81096
|
+
loading: true,
|
|
81097
|
+
error: null
|
|
81098
|
+
};
|
|
81099
|
+
});
|
|
81100
|
+
const metadataResponse = await fetchWithSupabaseAuth(supabase, "/api/clips/supabase", {
|
|
81101
|
+
method: "POST",
|
|
81102
|
+
headers: {
|
|
81103
|
+
"Content-Type": "application/json"
|
|
81104
|
+
},
|
|
81105
|
+
body: JSON.stringify({
|
|
81106
|
+
action: "clip-metadata",
|
|
81107
|
+
workspaceId,
|
|
81108
|
+
date: resolvedDate,
|
|
81109
|
+
shift: resolvedShiftId,
|
|
81110
|
+
category: "recent_flow_red_streak",
|
|
81111
|
+
page: 1,
|
|
81112
|
+
limit: 100,
|
|
81113
|
+
knownTotal: lowMomentsCount,
|
|
81114
|
+
snapshotDateTime: initData?.snapshotDateTime ?? null,
|
|
81115
|
+
snapshotClipId: initData?.snapshotClipId ?? null,
|
|
81116
|
+
sort: "red_flow_output_shortfall_desc"
|
|
81117
|
+
}),
|
|
81118
|
+
signal: controller.signal,
|
|
81119
|
+
redirectReason: "session_expired"
|
|
81120
|
+
});
|
|
81121
|
+
if (!metadataResponse.ok) {
|
|
81122
|
+
throw new Error(`Low moments metadata prefetch failed: ${metadataResponse.status}`);
|
|
81123
|
+
}
|
|
81124
|
+
const metadataData = await metadataResponse.json();
|
|
81125
|
+
const metadata = Array.isArray(metadataData?.clips) ? metadataData.clips : [];
|
|
81126
|
+
const firstClipId = metadata[0]?.clipId || metadata[0]?.id || null;
|
|
81127
|
+
const firstVideo = initFirstVideo && (!firstClipId || initFirstVideo.id === firstClipId) ? initFirstVideo : firstClipId ? await s3Service.getClipById(firstClipId) : null;
|
|
81128
|
+
if (cancelled) {
|
|
81129
|
+
return;
|
|
81130
|
+
}
|
|
81131
|
+
setLowMomentsPrefetch({
|
|
81132
|
+
key: lowMomentsKey,
|
|
81133
|
+
metadata,
|
|
81134
|
+
firstVideo,
|
|
81135
|
+
total: typeof metadataData?.total === "number" ? metadataData.total : lowMomentsCount,
|
|
81136
|
+
loading: false,
|
|
81137
|
+
error: null
|
|
81138
|
+
});
|
|
81139
|
+
prewarmedClipsRef.current.add(cacheKey);
|
|
81140
|
+
} catch (error2) {
|
|
81141
|
+
if (error2.name === "AbortError") {
|
|
81142
|
+
return;
|
|
81143
|
+
}
|
|
81144
|
+
console.warn("[WorkspaceDetailView] Clips init prewarm failed:", error2);
|
|
81145
|
+
setLowMomentsPrefetch((prev) => prev ? {
|
|
81146
|
+
...prev,
|
|
81147
|
+
loading: false,
|
|
81148
|
+
error: error2 instanceof Error ? error2.message : "Low moments prefetch failed"
|
|
81149
|
+
} : prev);
|
|
81150
|
+
} finally {
|
|
81151
|
+
prewarmInFlightRef.current.delete(cacheKey);
|
|
81152
|
+
}
|
|
81153
|
+
};
|
|
81154
|
+
void prefetchLowMoments();
|
|
81155
|
+
return () => {
|
|
81156
|
+
cancelled = true;
|
|
81157
|
+
controller.abort();
|
|
81158
|
+
};
|
|
80305
81159
|
}, [
|
|
80306
81160
|
isClipsEnabled,
|
|
80307
81161
|
dashboardConfig,
|
|
@@ -80311,7 +81165,8 @@ var WorkspaceDetailView = ({
|
|
|
80311
81165
|
isShiftConfigLoading,
|
|
80312
81166
|
shiftConfig,
|
|
80313
81167
|
timezone,
|
|
80314
|
-
workspace
|
|
81168
|
+
workspace,
|
|
81169
|
+
supabase
|
|
80315
81170
|
]);
|
|
80316
81171
|
const { supervisorName, supervisors } = useLineSupervisor(workspace?.line_id || lineId);
|
|
80317
81172
|
useEffect(() => {
|
|
@@ -81530,6 +82385,7 @@ var WorkspaceDetailView = ({
|
|
|
81530
82385
|
totalOutput: workspace?.total_actions,
|
|
81531
82386
|
workspaceMetrics: detailedWorkspaceMetrics || void 0,
|
|
81532
82387
|
prefetchedPercentileCounts: isFastSlowClipFiltersEnabled ? prefetchedPercentileCounts : null,
|
|
82388
|
+
lowMomentsPrefetch,
|
|
81533
82389
|
initialTimeFilter: pendingClipHourFilter,
|
|
81534
82390
|
className: "h-[calc(100vh-10rem)]"
|
|
81535
82391
|
}
|
|
@@ -83168,7 +84024,7 @@ function BottleneckClipsView({
|
|
|
83168
84024
|
) })
|
|
83169
84025
|
] }) });
|
|
83170
84026
|
}
|
|
83171
|
-
var AuthenticatedBottleneckClipsView = withAuth(
|
|
84027
|
+
var AuthenticatedBottleneckClipsView = withAuth(React148__default.memo(BottleneckClipsView));
|
|
83172
84028
|
var BottleneckClipsView_default = BottleneckClipsView;
|
|
83173
84029
|
|
|
83174
84030
|
// src/lib/services/ticketService.ts
|
|
@@ -84011,7 +84867,7 @@ Please ensure:
|
|
|
84011
84867
|
)
|
|
84012
84868
|
] });
|
|
84013
84869
|
}
|
|
84014
|
-
var AuthenticatedTicketsView = withAuth(
|
|
84870
|
+
var AuthenticatedTicketsView = withAuth(React148__default.memo(TicketsView));
|
|
84015
84871
|
var TicketsView_default = TicketsView;
|
|
84016
84872
|
|
|
84017
84873
|
// src/lib/utils/improvementDisplay.ts
|
|
@@ -84982,7 +85838,7 @@ var ImprovementCenterView = () => {
|
|
|
84982
85838
|
setSelectedMemberId("all");
|
|
84983
85839
|
}
|
|
84984
85840
|
}, [memberOptions, selectedMemberId]);
|
|
84985
|
-
const getRecommendationDisplayMetadata =
|
|
85841
|
+
const getRecommendationDisplayMetadata = React148__default.useCallback((rec) => {
|
|
84986
85842
|
const supervisors = rec.line_id ? supervisorsByLineId.get(rec.line_id) || [] : [];
|
|
84987
85843
|
return getImprovementDisplayMetadata({
|
|
84988
85844
|
location: rec.location,
|
|
@@ -85456,7 +86312,7 @@ var ThreadSidebar = ({
|
|
|
85456
86312
|
] }) })
|
|
85457
86313
|
] });
|
|
85458
86314
|
};
|
|
85459
|
-
var ProfilePicture =
|
|
86315
|
+
var ProfilePicture = React148__default.memo(({
|
|
85460
86316
|
alt = "Axel",
|
|
85461
86317
|
className = "",
|
|
85462
86318
|
size = "md",
|
|
@@ -88016,7 +88872,7 @@ var OverviewImprovementsSkeleton = () => /* @__PURE__ */ jsx("div", { className:
|
|
|
88016
88872
|
] }),
|
|
88017
88873
|
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-end flex-shrink-0 ml-4", children: /* @__PURE__ */ jsx(SectionPulse, { className: "h-6 w-20 rounded-full" }) })
|
|
88018
88874
|
] }, index)) });
|
|
88019
|
-
var OperationsOverviewHeader =
|
|
88875
|
+
var OperationsOverviewHeader = React148__default.memo(({
|
|
88020
88876
|
dateRange,
|
|
88021
88877
|
displayDateRange,
|
|
88022
88878
|
trendMode,
|
|
@@ -88037,65 +88893,65 @@ var OperationsOverviewHeader = React147__default.memo(({
|
|
|
88037
88893
|
bumpRenderCounter();
|
|
88038
88894
|
const subtitleRange = displayDateRange || dateRange;
|
|
88039
88895
|
const showLiveShiftMeta = isLiveScope && trendMode !== "all";
|
|
88040
|
-
const liveShiftLabel =
|
|
88896
|
+
const liveShiftLabel = React148__default.useMemo(
|
|
88041
88897
|
() => normalizeShiftLabel(liveShiftName, trendMode),
|
|
88042
88898
|
[liveShiftName, trendMode]
|
|
88043
88899
|
);
|
|
88044
|
-
const liveShiftIcon =
|
|
88900
|
+
const liveShiftIcon = React148__default.useMemo(
|
|
88045
88901
|
() => getShiftIcon(liveShiftName, trendMode),
|
|
88046
88902
|
[liveShiftName, trendMode]
|
|
88047
88903
|
);
|
|
88048
|
-
const [isFilterOpen, setIsFilterOpen] =
|
|
88049
|
-
const [isLinesDropdownOpen, setIsLinesDropdownOpen] =
|
|
88050
|
-
const filterRef =
|
|
88051
|
-
const filterButtonRef =
|
|
88052
|
-
const mobileFilterButtonRef =
|
|
88053
|
-
const linesDropdownRef =
|
|
88054
|
-
const mobileSubtitle =
|
|
88904
|
+
const [isFilterOpen, setIsFilterOpen] = React148__default.useState(false);
|
|
88905
|
+
const [isLinesDropdownOpen, setIsLinesDropdownOpen] = React148__default.useState(false);
|
|
88906
|
+
const filterRef = React148__default.useRef(null);
|
|
88907
|
+
const filterButtonRef = React148__default.useRef(null);
|
|
88908
|
+
const mobileFilterButtonRef = React148__default.useRef(null);
|
|
88909
|
+
const linesDropdownRef = React148__default.useRef(null);
|
|
88910
|
+
const mobileSubtitle = React148__default.useMemo(() => {
|
|
88055
88911
|
if (subtitleRange.startKey === subtitleRange.endKey) {
|
|
88056
88912
|
return format(parseDateKeyToDate(subtitleRange.startKey), "do MMM, yyyy");
|
|
88057
88913
|
}
|
|
88058
88914
|
return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMM")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMM, yyyy")}`;
|
|
88059
88915
|
}, [subtitleRange.endKey, subtitleRange.startKey]);
|
|
88060
|
-
const desktopSubtitle =
|
|
88916
|
+
const desktopSubtitle = React148__default.useMemo(() => {
|
|
88061
88917
|
if (subtitleRange.startKey === subtitleRange.endKey) {
|
|
88062
88918
|
return format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy");
|
|
88063
88919
|
}
|
|
88064
88920
|
return `${format(parseDateKeyToDate(subtitleRange.startKey), "do MMMM, yyyy")} - ${format(parseDateKeyToDate(subtitleRange.endKey), "do MMMM, yyyy")}`;
|
|
88065
88921
|
}, [subtitleRange.endKey, subtitleRange.startKey]);
|
|
88066
|
-
const availableLineIds =
|
|
88922
|
+
const availableLineIds = React148__default.useMemo(
|
|
88067
88923
|
() => lineOptions.map((line) => line.id),
|
|
88068
88924
|
[lineOptions]
|
|
88069
88925
|
);
|
|
88070
|
-
const selectedLineIdSet =
|
|
88926
|
+
const selectedLineIdSet = React148__default.useMemo(
|
|
88071
88927
|
() => new Set(selectedLineIds),
|
|
88072
88928
|
[selectedLineIds]
|
|
88073
88929
|
);
|
|
88074
|
-
const isAllLinesSelected =
|
|
88930
|
+
const isAllLinesSelected = React148__default.useMemo(() => {
|
|
88075
88931
|
if (availableLineIds.length === 0) return true;
|
|
88076
88932
|
return availableLineIds.every((lineId) => selectedLineIdSet.has(lineId));
|
|
88077
88933
|
}, [availableLineIds, selectedLineIdSet]);
|
|
88078
|
-
const activeFilterCount =
|
|
88934
|
+
const activeFilterCount = React148__default.useMemo(() => {
|
|
88079
88935
|
let count = 0;
|
|
88080
88936
|
if (trendMode !== "all") count += 1;
|
|
88081
88937
|
if (selectedSupervisorId !== "all") count += 1;
|
|
88082
88938
|
if (!isAllLinesSelected) count += 1;
|
|
88083
88939
|
return count;
|
|
88084
88940
|
}, [isAllLinesSelected, selectedSupervisorId, trendMode]);
|
|
88085
|
-
const handleFilterToggle =
|
|
88941
|
+
const handleFilterToggle = React148__default.useCallback(() => {
|
|
88086
88942
|
trackCoreEvent("Operations Overview Filter Toggled", {
|
|
88087
88943
|
action: !isFilterOpen ? "open" : "close"
|
|
88088
88944
|
});
|
|
88089
88945
|
setIsFilterOpen((previous) => !previous);
|
|
88090
88946
|
}, [isFilterOpen]);
|
|
88091
|
-
const handleTrendModeChange =
|
|
88947
|
+
const handleTrendModeChange = React148__default.useCallback((event) => {
|
|
88092
88948
|
const nextMode = event.target.value;
|
|
88093
88949
|
trackCoreEvent("Operations Overview Shift Filter Changed", {
|
|
88094
88950
|
shift_mode: nextMode
|
|
88095
88951
|
});
|
|
88096
88952
|
onTrendModeChange(nextMode);
|
|
88097
88953
|
}, [onTrendModeChange]);
|
|
88098
|
-
const handleAllLinesToggle =
|
|
88954
|
+
const handleAllLinesToggle = React148__default.useCallback(() => {
|
|
88099
88955
|
trackCoreEvent("Operations Overview Line Filter Changed", {
|
|
88100
88956
|
selected_line_ids: availableLineIds,
|
|
88101
88957
|
selected_line_count: availableLineIds.length,
|
|
@@ -88103,7 +88959,7 @@ var OperationsOverviewHeader = React147__default.memo(({
|
|
|
88103
88959
|
});
|
|
88104
88960
|
onSelectedLineIdsChange(availableLineIds);
|
|
88105
88961
|
}, [availableLineIds, onSelectedLineIdsChange]);
|
|
88106
|
-
const handleSupervisorChange =
|
|
88962
|
+
const handleSupervisorChange = React148__default.useCallback((event) => {
|
|
88107
88963
|
const supervisorId = event.target.value;
|
|
88108
88964
|
const selectedSupervisor = supervisorOptions.find((option) => option.id === supervisorId);
|
|
88109
88965
|
trackCoreEvent("Operations Overview Supervisor Filter Changed", {
|
|
@@ -88114,7 +88970,7 @@ var OperationsOverviewHeader = React147__default.memo(({
|
|
|
88114
88970
|
});
|
|
88115
88971
|
onSelectedSupervisorIdChange(supervisorId);
|
|
88116
88972
|
}, [availableLineIds, onSelectedSupervisorIdChange, supervisorOptions]);
|
|
88117
|
-
const handleLineToggle =
|
|
88973
|
+
const handleLineToggle = React148__default.useCallback((lineId) => {
|
|
88118
88974
|
const current = new Set(selectedLineIds);
|
|
88119
88975
|
if (current.has(lineId)) {
|
|
88120
88976
|
if (current.size <= 1) return;
|
|
@@ -88130,13 +88986,13 @@ var OperationsOverviewHeader = React147__default.memo(({
|
|
|
88130
88986
|
});
|
|
88131
88987
|
onSelectedLineIdsChange(next);
|
|
88132
88988
|
}, [availableLineIds, onSelectedLineIdsChange, selectedLineIds]);
|
|
88133
|
-
const handleClearAllFilters =
|
|
88989
|
+
const handleClearAllFilters = React148__default.useCallback(() => {
|
|
88134
88990
|
onTrendModeChange("all");
|
|
88135
88991
|
onSelectedSupervisorIdChange("all");
|
|
88136
88992
|
onSelectedLineIdsChange(availableLineIds);
|
|
88137
88993
|
setIsFilterOpen(false);
|
|
88138
88994
|
}, [availableLineIds, onSelectedLineIdsChange, onSelectedSupervisorIdChange, onTrendModeChange]);
|
|
88139
|
-
|
|
88995
|
+
React148__default.useEffect(() => {
|
|
88140
88996
|
const handleClickOutside = (event) => {
|
|
88141
88997
|
const target = event.target;
|
|
88142
88998
|
if (filterRef.current && !filterRef.current.contains(target) && filterButtonRef.current && !filterButtonRef.current.contains(target) && mobileFilterButtonRef.current && !mobileFilterButtonRef.current.contains(target)) {
|
|
@@ -88371,12 +89227,12 @@ var OperationsOverviewHeader = React147__default.memo(({
|
|
|
88371
89227
|
] }) });
|
|
88372
89228
|
});
|
|
88373
89229
|
OperationsOverviewHeader.displayName = "OperationsOverviewHeader";
|
|
88374
|
-
var OverviewSummaryCards =
|
|
89230
|
+
var OverviewSummaryCards = React148__default.memo(({ store }) => {
|
|
88375
89231
|
bumpRenderCounter();
|
|
88376
89232
|
const scope = useOperationsOverviewScope(store);
|
|
88377
89233
|
const snapshot = useOperationsOverviewSnapshot(store);
|
|
88378
89234
|
const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
|
|
88379
|
-
const comparisonLabel =
|
|
89235
|
+
const comparisonLabel = React148__default.useMemo(() => {
|
|
88380
89236
|
return formatComparisonWindow({
|
|
88381
89237
|
currentDayCount: scope.current_range?.day_count ?? null,
|
|
88382
89238
|
previousDayCount: scope.previous_range?.day_count ?? null,
|
|
@@ -88389,27 +89245,27 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
|
|
|
88389
89245
|
scope.previous_range?.day_count,
|
|
88390
89246
|
scope.shift_mode
|
|
88391
89247
|
]);
|
|
88392
|
-
const [isIdleContributorsOpen, setIsIdleContributorsOpen] =
|
|
88393
|
-
const [isIdleContributorsPinned, setIsIdleContributorsPinned] =
|
|
88394
|
-
const idleContributorsRef =
|
|
88395
|
-
const plantEfficiencyBadge =
|
|
89248
|
+
const [isIdleContributorsOpen, setIsIdleContributorsOpen] = React148__default.useState(false);
|
|
89249
|
+
const [isIdleContributorsPinned, setIsIdleContributorsPinned] = React148__default.useState(false);
|
|
89250
|
+
const idleContributorsRef = React148__default.useRef(null);
|
|
89251
|
+
const plantEfficiencyBadge = React148__default.useMemo(() => {
|
|
88396
89252
|
return buildDeltaBadge(snapshot.data.summary.plant_efficiency?.delta_pp, {
|
|
88397
89253
|
positiveIsGood: true,
|
|
88398
89254
|
formatter: (value) => `${value >= 0 ? "+" : ""}${roundOne(value)}%`,
|
|
88399
89255
|
comparisonLabel
|
|
88400
89256
|
});
|
|
88401
89257
|
}, [comparisonLabel, snapshot.data.summary.plant_efficiency?.delta_pp]);
|
|
88402
|
-
const idleBadge =
|
|
89258
|
+
const idleBadge = React148__default.useMemo(() => {
|
|
88403
89259
|
return buildDeltaBadge(snapshot.data.summary.avg_idle_per_workstation?.delta_seconds, {
|
|
88404
89260
|
positiveIsGood: false,
|
|
88405
89261
|
formatter: (value) => formatSignedIdleDuration(value),
|
|
88406
89262
|
comparisonLabel
|
|
88407
89263
|
});
|
|
88408
89264
|
}, [comparisonLabel, snapshot.data.summary.avg_idle_per_workstation?.delta_seconds]);
|
|
88409
|
-
const canInspectIdleContributors =
|
|
89265
|
+
const canInspectIdleContributors = React148__default.useMemo(() => {
|
|
88410
89266
|
return !showSnapshotSkeleton && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== null && snapshot.data.summary.avg_idle_per_workstation?.current_seconds !== void 0;
|
|
88411
89267
|
}, [showSnapshotSkeleton, snapshot.data.summary.avg_idle_per_workstation?.current_seconds]);
|
|
88412
|
-
const idleTopContributors =
|
|
89268
|
+
const idleTopContributors = React148__default.useMemo(() => {
|
|
88413
89269
|
return (snapshot.data.summary.avg_idle_per_workstation?.top_contributors || []).map((item) => ({
|
|
88414
89270
|
workspaceId: item.workspace_id || "",
|
|
88415
89271
|
workspaceName: item.workspace_name?.trim() || item.workspace_id || "Unknown",
|
|
@@ -88417,14 +89273,14 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
|
|
|
88417
89273
|
avgIdleSeconds: toNumber4(item.avg_idle_seconds)
|
|
88418
89274
|
})).slice(0, 5);
|
|
88419
89275
|
}, [snapshot.data.summary.avg_idle_per_workstation?.top_contributors]);
|
|
88420
|
-
const showIdleContributorLineNames =
|
|
89276
|
+
const showIdleContributorLineNames = React148__default.useMemo(() => {
|
|
88421
89277
|
return (scope.line_count ?? 0) > 1;
|
|
88422
89278
|
}, [scope.line_count]);
|
|
88423
|
-
const closeIdleContributors =
|
|
89279
|
+
const closeIdleContributors = React148__default.useCallback(() => {
|
|
88424
89280
|
setIsIdleContributorsOpen(false);
|
|
88425
89281
|
setIsIdleContributorsPinned(false);
|
|
88426
89282
|
}, []);
|
|
88427
|
-
const handleIdleContributorsToggle =
|
|
89283
|
+
const handleIdleContributorsToggle = React148__default.useCallback(() => {
|
|
88428
89284
|
if (!canInspectIdleContributors) return;
|
|
88429
89285
|
setIsIdleContributorsPinned((previous) => {
|
|
88430
89286
|
const next = !previous;
|
|
@@ -88432,7 +89288,7 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
|
|
|
88432
89288
|
return next;
|
|
88433
89289
|
});
|
|
88434
89290
|
}, [canInspectIdleContributors]);
|
|
88435
|
-
const handleIdleContributorsKeyDown =
|
|
89291
|
+
const handleIdleContributorsKeyDown = React148__default.useCallback((event) => {
|
|
88436
89292
|
if (!canInspectIdleContributors) return;
|
|
88437
89293
|
if (event.key === "Enter" || event.key === " ") {
|
|
88438
89294
|
event.preventDefault();
|
|
@@ -88444,11 +89300,11 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
|
|
|
88444
89300
|
closeIdleContributors();
|
|
88445
89301
|
}
|
|
88446
89302
|
}, [canInspectIdleContributors, closeIdleContributors, handleIdleContributorsToggle]);
|
|
88447
|
-
|
|
89303
|
+
React148__default.useEffect(() => {
|
|
88448
89304
|
setIsIdleContributorsOpen(false);
|
|
88449
89305
|
setIsIdleContributorsPinned(false);
|
|
88450
89306
|
}, [scope.comparison_strategy, scope.current_range?.start_date, scope.current_range?.end_date, scope.line_count, scope.shift_mode]);
|
|
88451
|
-
|
|
89307
|
+
React148__default.useEffect(() => {
|
|
88452
89308
|
if (!isIdleContributorsOpen) return void 0;
|
|
88453
89309
|
const handleClickOutside = (event) => {
|
|
88454
89310
|
if (!isIdleContributorsPinned) return;
|
|
@@ -88586,7 +89442,7 @@ var OverviewSummaryCards = React147__default.memo(({ store }) => {
|
|
|
88586
89442
|
] });
|
|
88587
89443
|
});
|
|
88588
89444
|
OverviewSummaryCards.displayName = "OverviewSummaryCards";
|
|
88589
|
-
var PoorestPerformersCard =
|
|
89445
|
+
var PoorestPerformersCard = React148__default.memo(({
|
|
88590
89446
|
store,
|
|
88591
89447
|
supervisorsByLineId,
|
|
88592
89448
|
onViewAll,
|
|
@@ -88595,9 +89451,9 @@ var PoorestPerformersCard = React147__default.memo(({
|
|
|
88595
89451
|
bumpRenderCounter();
|
|
88596
89452
|
const scope = useOperationsOverviewScope(store);
|
|
88597
89453
|
const snapshot = useOperationsOverviewSnapshot(store);
|
|
88598
|
-
const [poorestLineMode, setPoorestLineMode] =
|
|
89454
|
+
const [poorestLineMode, setPoorestLineMode] = React148__default.useState("output");
|
|
88599
89455
|
const availableLineModes = scope.available_line_modes;
|
|
88600
|
-
|
|
89456
|
+
React148__default.useEffect(() => {
|
|
88601
89457
|
const hasOutput = !!availableLineModes?.has_output;
|
|
88602
89458
|
const hasUptime = !!availableLineModes?.has_uptime;
|
|
88603
89459
|
if (hasOutput && !hasUptime && poorestLineMode !== "output") {
|
|
@@ -88606,7 +89462,7 @@ var PoorestPerformersCard = React147__default.memo(({
|
|
|
88606
89462
|
setPoorestLineMode("uptime");
|
|
88607
89463
|
}
|
|
88608
89464
|
}, [availableLineModes?.has_output, availableLineModes?.has_uptime, poorestLineMode]);
|
|
88609
|
-
const comparisonLabel =
|
|
89465
|
+
const comparisonLabel = React148__default.useMemo(() => {
|
|
88610
89466
|
return formatComparisonWindow({
|
|
88611
89467
|
currentDayCount: scope.current_range?.day_count ?? null,
|
|
88612
89468
|
previousDayCount: scope.previous_range?.day_count ?? null,
|
|
@@ -88620,7 +89476,7 @@ var PoorestPerformersCard = React147__default.memo(({
|
|
|
88620
89476
|
scope.shift_mode
|
|
88621
89477
|
]);
|
|
88622
89478
|
const showSnapshotSkeleton = snapshot.loading && !snapshot.hasLoadedOnce;
|
|
88623
|
-
const mergedPoorestLines =
|
|
89479
|
+
const mergedPoorestLines = React148__default.useMemo(() => {
|
|
88624
89480
|
const rows = snapshot.data.poorest_lines?.[poorestLineMode] || [];
|
|
88625
89481
|
const lineRows = [];
|
|
88626
89482
|
const areaGroups = /* @__PURE__ */ new Map();
|
|
@@ -88700,7 +89556,7 @@ var PoorestPerformersCard = React147__default.memo(({
|
|
|
88700
89556
|
}, [poorestLineMode, snapshot.data.poorest_lines, supervisorsByLineId]);
|
|
88701
89557
|
const showPoorestModeToggle = !!availableLineModes?.has_output && !!availableLineModes?.has_uptime;
|
|
88702
89558
|
const poorestMetricLabel = poorestLineMode === "uptime" ? "Uptime" : "Efficiency";
|
|
88703
|
-
const handlePoorestLineModeChange =
|
|
89559
|
+
const handlePoorestLineModeChange = React148__default.useCallback((mode) => {
|
|
88704
89560
|
trackCoreEvent("Operations Overview Poorest Line Mode Changed", { mode });
|
|
88705
89561
|
setPoorestLineMode(mode);
|
|
88706
89562
|
}, []);
|
|
@@ -88786,14 +89642,14 @@ var PoorestPerformersCard = React147__default.memo(({
|
|
|
88786
89642
|
] });
|
|
88787
89643
|
});
|
|
88788
89644
|
PoorestPerformersCard.displayName = "PoorestPerformersCard";
|
|
88789
|
-
var IdleBreakdownCard =
|
|
89645
|
+
var IdleBreakdownCard = React148__default.memo(({
|
|
88790
89646
|
store,
|
|
88791
89647
|
scopedLineCount
|
|
88792
89648
|
}) => {
|
|
88793
89649
|
bumpRenderCounter();
|
|
88794
89650
|
const idle = useOperationsOverviewIdle(store);
|
|
88795
89651
|
const showInitialSkeleton = idle.loading && idle.lastUpdated === null;
|
|
88796
|
-
const idleBreakdown =
|
|
89652
|
+
const idleBreakdown = React148__default.useMemo(() => {
|
|
88797
89653
|
return idle.data.map((item) => ({
|
|
88798
89654
|
name: item.display_name?.trim() || item.reason?.trim() || "Unknown",
|
|
88799
89655
|
reasonKey: item.reason_key?.trim() || item.reason?.trim() || "unknown",
|
|
@@ -88812,7 +89668,7 @@ var IdleBreakdownCard = React147__default.memo(({
|
|
|
88812
89668
|
}))
|
|
88813
89669
|
})).filter((item) => item.value > 0);
|
|
88814
89670
|
}, [idle.data]);
|
|
88815
|
-
const showIdleModuleNotEnabledState =
|
|
89671
|
+
const showIdleModuleNotEnabledState = React148__default.useMemo(() => {
|
|
88816
89672
|
const enabledLineCount = idle.scope.idle_time_vlm_enabled_line_count;
|
|
88817
89673
|
return !showInitialSkeleton && scopedLineCount > 0 && typeof enabledLineCount === "number" && enabledLineCount === 0;
|
|
88818
89674
|
}, [idle.scope.idle_time_vlm_enabled_line_count, scopedLineCount, showInitialSkeleton]);
|
|
@@ -88833,7 +89689,7 @@ var IdleBreakdownCard = React147__default.memo(({
|
|
|
88833
89689
|
] });
|
|
88834
89690
|
});
|
|
88835
89691
|
IdleBreakdownCard.displayName = "IdleBreakdownCard";
|
|
88836
|
-
var EfficiencyTrendCard =
|
|
89692
|
+
var EfficiencyTrendCard = React148__default.memo(({
|
|
88837
89693
|
store,
|
|
88838
89694
|
dateRange,
|
|
88839
89695
|
appTimezone,
|
|
@@ -88841,14 +89697,14 @@ var EfficiencyTrendCard = React147__default.memo(({
|
|
|
88841
89697
|
}) => {
|
|
88842
89698
|
bumpRenderCounter();
|
|
88843
89699
|
const trend = useOperationsOverviewTrend(store);
|
|
88844
|
-
const currentWeekRange =
|
|
89700
|
+
const currentWeekRange = React148__default.useMemo(
|
|
88845
89701
|
() => getCurrentWeekToDateRange(appTimezone),
|
|
88846
89702
|
[appTimezone]
|
|
88847
89703
|
);
|
|
88848
89704
|
const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
|
|
88849
89705
|
const showInitialSkeleton = trend.loading && trend.lastUpdated === null;
|
|
88850
89706
|
const isHourlyTrend = trend.data.granularity === "hour";
|
|
88851
|
-
const trendData =
|
|
89707
|
+
const trendData = React148__default.useMemo(() => {
|
|
88852
89708
|
if (isHourlyTrend) {
|
|
88853
89709
|
return (trend.data.points || []).map((point, index) => ({
|
|
88854
89710
|
name: (() => {
|
|
@@ -88920,13 +89776,13 @@ var EfficiencyTrendCard = React147__default.memo(({
|
|
|
88920
89776
|
};
|
|
88921
89777
|
});
|
|
88922
89778
|
}, [currentWeekRange.startKey, hourlyLabelStartTime, isCurrentWeekToDateRange, isHourlyTrend, trend.data.points]);
|
|
88923
|
-
const trendTooltipLabelFormatter =
|
|
89779
|
+
const trendTooltipLabelFormatter = React148__default.useCallback((label, payload) => {
|
|
88924
89780
|
if (isHourlyTrend) return label;
|
|
88925
89781
|
const dayOfWeek = payload?.[0]?.payload?.dayOfWeek;
|
|
88926
89782
|
if (!dayOfWeek || typeof label !== "string") return label;
|
|
88927
89783
|
return `${label} (${dayOfWeek})`;
|
|
88928
89784
|
}, [isHourlyTrend]);
|
|
88929
|
-
const trendXAxisTickFormatter =
|
|
89785
|
+
const trendXAxisTickFormatter = React148__default.useCallback((value, index) => {
|
|
88930
89786
|
if (!isHourlyTrend) {
|
|
88931
89787
|
return typeof value === "string" ? value : String(value ?? "");
|
|
88932
89788
|
}
|
|
@@ -88953,7 +89809,7 @@ var EfficiencyTrendCard = React147__default.memo(({
|
|
|
88953
89809
|
] });
|
|
88954
89810
|
});
|
|
88955
89811
|
EfficiencyTrendCard.displayName = "EfficiencyTrendCard";
|
|
88956
|
-
var TopImprovementsCard =
|
|
89812
|
+
var TopImprovementsCard = React148__default.memo(({
|
|
88957
89813
|
store,
|
|
88958
89814
|
supervisorsByLineId,
|
|
88959
89815
|
onViewAll,
|
|
@@ -88962,7 +89818,7 @@ var TopImprovementsCard = React147__default.memo(({
|
|
|
88962
89818
|
bumpRenderCounter();
|
|
88963
89819
|
const improvements = useOperationsOverviewImprovements(store);
|
|
88964
89820
|
const showInitialSkeleton = improvements.loading && improvements.lastUpdated === null;
|
|
88965
|
-
const displayImprovements =
|
|
89821
|
+
const displayImprovements = React148__default.useMemo(() => {
|
|
88966
89822
|
return improvements.data.map((item) => {
|
|
88967
89823
|
const supervisors = item.lineId ? supervisorsByLineId.get(item.lineId) || [] : [];
|
|
88968
89824
|
return {
|
|
@@ -89090,33 +89946,33 @@ var useOperationsOverviewRefresh = ({
|
|
|
89090
89946
|
isLiveScope,
|
|
89091
89947
|
enabled = true
|
|
89092
89948
|
}) => {
|
|
89093
|
-
const lineIdsKey =
|
|
89094
|
-
const scopeSignature =
|
|
89949
|
+
const lineIdsKey = React148__default.useMemo(() => lineIds.join(","), [lineIds]);
|
|
89950
|
+
const scopeSignature = React148__default.useMemo(
|
|
89095
89951
|
() => [companyId || "", startKey, endKey, trendMode, comparisonStrategy || "", lineIdsKey].join("::"),
|
|
89096
89952
|
[companyId, comparisonStrategy, endKey, lineIdsKey, startKey, trendMode]
|
|
89097
89953
|
);
|
|
89098
|
-
const controllersRef =
|
|
89099
|
-
const requestIdsRef =
|
|
89954
|
+
const controllersRef = React148__default.useRef({});
|
|
89955
|
+
const requestIdsRef = React148__default.useRef({
|
|
89100
89956
|
snapshot: 0,
|
|
89101
89957
|
trend: 0,
|
|
89102
89958
|
idle: 0,
|
|
89103
89959
|
improvements: 0
|
|
89104
89960
|
});
|
|
89105
|
-
const intervalRef =
|
|
89106
|
-
const isPageActiveRef =
|
|
89107
|
-
const lastResumeRefreshAtRef =
|
|
89108
|
-
const abortAll =
|
|
89961
|
+
const intervalRef = React148__default.useRef(null);
|
|
89962
|
+
const isPageActiveRef = React148__default.useRef(true);
|
|
89963
|
+
const lastResumeRefreshAtRef = React148__default.useRef(0);
|
|
89964
|
+
const abortAll = React148__default.useCallback(() => {
|
|
89109
89965
|
Object.values(controllersRef.current).forEach((controller) => {
|
|
89110
89966
|
controller?.abort();
|
|
89111
89967
|
});
|
|
89112
89968
|
controllersRef.current = {};
|
|
89113
89969
|
}, []);
|
|
89114
|
-
|
|
89970
|
+
React148__default.useEffect(() => {
|
|
89115
89971
|
return () => {
|
|
89116
89972
|
abortAll();
|
|
89117
89973
|
};
|
|
89118
89974
|
}, [abortAll]);
|
|
89119
|
-
const getIsPageActive =
|
|
89975
|
+
const getIsPageActive = React148__default.useCallback(() => {
|
|
89120
89976
|
if (typeof document === "undefined") {
|
|
89121
89977
|
return true;
|
|
89122
89978
|
}
|
|
@@ -89124,7 +89980,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89124
89980
|
const hasFocus = typeof document.hasFocus === "function" ? document.hasFocus() : true;
|
|
89125
89981
|
return isVisible && hasFocus;
|
|
89126
89982
|
}, []);
|
|
89127
|
-
const stopPolling =
|
|
89983
|
+
const stopPolling = React148__default.useCallback((reason) => {
|
|
89128
89984
|
if (intervalRef.current === null) {
|
|
89129
89985
|
return;
|
|
89130
89986
|
}
|
|
@@ -89132,7 +89988,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89132
89988
|
intervalRef.current = null;
|
|
89133
89989
|
debugRefreshLog("poll stopped", { reason });
|
|
89134
89990
|
}, []);
|
|
89135
|
-
const runRefresh =
|
|
89991
|
+
const runRefresh = React148__default.useCallback(
|
|
89136
89992
|
async (section, begin, onSuccess, onError, request, reason) => {
|
|
89137
89993
|
if (!enabled || !supabase || !companyId || lineIds.length === 0) return;
|
|
89138
89994
|
const requestId = requestIdsRef.current[section] + 1;
|
|
@@ -89179,7 +90035,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89179
90035
|
},
|
|
89180
90036
|
[companyId, comparisonStrategy, enabled, endKey, lineIds, startKey, supabase, trendMode]
|
|
89181
90037
|
);
|
|
89182
|
-
const refreshSnapshot =
|
|
90038
|
+
const refreshSnapshot = React148__default.useCallback(
|
|
89183
90039
|
async (reason) => {
|
|
89184
90040
|
await runRefresh(
|
|
89185
90041
|
"snapshot",
|
|
@@ -89211,7 +90067,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89211
90067
|
},
|
|
89212
90068
|
[companyId, comparisonStrategy, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
|
|
89213
90069
|
);
|
|
89214
|
-
const refreshTrend =
|
|
90070
|
+
const refreshTrend = React148__default.useCallback(
|
|
89215
90071
|
async (reason) => {
|
|
89216
90072
|
await runRefresh(
|
|
89217
90073
|
"trend",
|
|
@@ -89240,7 +90096,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89240
90096
|
},
|
|
89241
90097
|
[companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
|
|
89242
90098
|
);
|
|
89243
|
-
const refreshIdle =
|
|
90099
|
+
const refreshIdle = React148__default.useCallback(
|
|
89244
90100
|
async (reason) => {
|
|
89245
90101
|
await runRefresh(
|
|
89246
90102
|
"idle",
|
|
@@ -89269,7 +90125,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89269
90125
|
},
|
|
89270
90126
|
[companyId, endKey, lineIdsKey, runRefresh, scopeSignature, startKey, store, supabase, trendMode]
|
|
89271
90127
|
);
|
|
89272
|
-
const refreshImprovements =
|
|
90128
|
+
const refreshImprovements = React148__default.useCallback(
|
|
89273
90129
|
async (reason) => {
|
|
89274
90130
|
await runRefresh(
|
|
89275
90131
|
"improvements",
|
|
@@ -89299,7 +90155,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89299
90155
|
},
|
|
89300
90156
|
[companyId, lineIds, lineIdsKey, runRefresh, scopeSignature, store, supabase]
|
|
89301
90157
|
);
|
|
89302
|
-
const refreshAll =
|
|
90158
|
+
const refreshAll = React148__default.useCallback(
|
|
89303
90159
|
async (reason) => {
|
|
89304
90160
|
await Promise.allSettled([
|
|
89305
90161
|
refreshSnapshot(reason),
|
|
@@ -89310,7 +90166,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89310
90166
|
},
|
|
89311
90167
|
[refreshIdle, refreshImprovements, refreshSnapshot, refreshTrend]
|
|
89312
90168
|
);
|
|
89313
|
-
const startPolling =
|
|
90169
|
+
const startPolling = React148__default.useCallback((reason) => {
|
|
89314
90170
|
if (!isLiveScope || !supabase || !companyId || lineIds.length === 0) {
|
|
89315
90171
|
return;
|
|
89316
90172
|
}
|
|
@@ -89331,7 +90187,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89331
90187
|
}, LIVE_REFRESH_INTERVAL_MS);
|
|
89332
90188
|
debugRefreshLog("poll started", { reason, intervalMs: LIVE_REFRESH_INTERVAL_MS });
|
|
89333
90189
|
}, [companyId, isLiveScope, lineIds.length, refreshAll, stopPolling, supabase]);
|
|
89334
|
-
const refreshFromResume =
|
|
90190
|
+
const refreshFromResume = React148__default.useCallback((reason) => {
|
|
89335
90191
|
const now4 = Date.now();
|
|
89336
90192
|
if (now4 - lastResumeRefreshAtRef.current < 1e3) {
|
|
89337
90193
|
debugRefreshLog("resume refresh suppressed", { reason });
|
|
@@ -89346,7 +90202,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89346
90202
|
}
|
|
89347
90203
|
});
|
|
89348
90204
|
}, [refreshAll, startPolling, stopPolling]);
|
|
89349
|
-
|
|
90205
|
+
React148__default.useEffect(() => {
|
|
89350
90206
|
if (!enabled) {
|
|
89351
90207
|
stopPolling("disabled");
|
|
89352
90208
|
abortAll();
|
|
@@ -89361,7 +90217,7 @@ var useOperationsOverviewRefresh = ({
|
|
|
89361
90217
|
}
|
|
89362
90218
|
void refreshAll("scope_change");
|
|
89363
90219
|
}, [abortAll, companyId, enabled, lineIds.length, refreshAll, scopeSignature, stopPolling, store, supabase]);
|
|
89364
|
-
|
|
90220
|
+
React148__default.useEffect(() => {
|
|
89365
90221
|
if (!enabled || !isLiveScope || !supabase || !companyId || lineIds.length === 0) {
|
|
89366
90222
|
isPageActiveRef.current = false;
|
|
89367
90223
|
stopPolling("live_scope_disabled");
|
|
@@ -89574,55 +90430,55 @@ var PlantHeadView = () => {
|
|
|
89574
90430
|
const { accessibleLineIds } = useUserLineAccess();
|
|
89575
90431
|
const mobileMenuContext = useMobileMenu();
|
|
89576
90432
|
useHideMobileHeader(!!mobileMenuContext);
|
|
89577
|
-
const storeRef =
|
|
90433
|
+
const storeRef = React148__default.useRef(createOperationsOverviewStore());
|
|
89578
90434
|
const store = storeRef.current;
|
|
89579
|
-
const fallbackOperationalDate =
|
|
90435
|
+
const fallbackOperationalDate = React148__default.useMemo(
|
|
89580
90436
|
() => getOperationalDate(appTimezone),
|
|
89581
90437
|
[appTimezone]
|
|
89582
90438
|
);
|
|
89583
|
-
const [dateRange, setDateRange] =
|
|
90439
|
+
const [dateRange, setDateRange] = React148__default.useState(() => ({
|
|
89584
90440
|
startKey: fallbackOperationalDate,
|
|
89585
90441
|
endKey: fallbackOperationalDate
|
|
89586
90442
|
}));
|
|
89587
|
-
const [usesThisWeekComparison, setUsesThisWeekComparison] =
|
|
89588
|
-
const [trendMode, setTrendMode] =
|
|
89589
|
-
const [selectedSupervisorId, setSelectedSupervisorId] =
|
|
89590
|
-
const [selectedLineIds, setSelectedLineIds] =
|
|
89591
|
-
const [isInitialScopeReady, setIsInitialScopeReady] =
|
|
89592
|
-
const [shiftResolutionTick, setShiftResolutionTick] =
|
|
89593
|
-
const hasAutoInitializedScopeRef =
|
|
89594
|
-
const hasUserAdjustedScopeRef =
|
|
89595
|
-
|
|
90443
|
+
const [usesThisWeekComparison, setUsesThisWeekComparison] = React148__default.useState(false);
|
|
90444
|
+
const [trendMode, setTrendMode] = React148__default.useState("all");
|
|
90445
|
+
const [selectedSupervisorId, setSelectedSupervisorId] = React148__default.useState("all");
|
|
90446
|
+
const [selectedLineIds, setSelectedLineIds] = React148__default.useState([]);
|
|
90447
|
+
const [isInitialScopeReady, setIsInitialScopeReady] = React148__default.useState(false);
|
|
90448
|
+
const [shiftResolutionTick, setShiftResolutionTick] = React148__default.useState(0);
|
|
90449
|
+
const hasAutoInitializedScopeRef = React148__default.useRef(false);
|
|
90450
|
+
const hasUserAdjustedScopeRef = React148__default.useRef(false);
|
|
90451
|
+
React148__default.useEffect(() => {
|
|
89596
90452
|
trackCorePageView("Operations Overview", {
|
|
89597
90453
|
dashboard_surface: "operations_overview"
|
|
89598
90454
|
});
|
|
89599
90455
|
}, []);
|
|
89600
|
-
const currentWeekRange =
|
|
90456
|
+
const currentWeekRange = React148__default.useMemo(
|
|
89601
90457
|
() => getCurrentWeekToDateRange(appTimezone),
|
|
89602
90458
|
[appTimezone]
|
|
89603
90459
|
);
|
|
89604
|
-
const currentWeekDisplayRange =
|
|
90460
|
+
const currentWeekDisplayRange = React148__default.useMemo(
|
|
89605
90461
|
() => getCurrentWeekFullRange(appTimezone),
|
|
89606
90462
|
[appTimezone]
|
|
89607
90463
|
);
|
|
89608
90464
|
const isCurrentWeekToDateRange = dateRange.startKey === currentWeekRange.startKey && dateRange.endKey === currentWeekRange.endKey;
|
|
89609
|
-
const headerDateRange =
|
|
90465
|
+
const headerDateRange = React148__default.useMemo(() => {
|
|
89610
90466
|
if (usesThisWeekComparison && isCurrentWeekToDateRange) {
|
|
89611
90467
|
return currentWeekDisplayRange;
|
|
89612
90468
|
}
|
|
89613
90469
|
return dateRange;
|
|
89614
90470
|
}, [currentWeekDisplayRange, dateRange, isCurrentWeekToDateRange, usesThisWeekComparison]);
|
|
89615
|
-
const normalizedLineIds =
|
|
90471
|
+
const normalizedLineIds = React148__default.useMemo(
|
|
89616
90472
|
() => Array.from(new Set(
|
|
89617
90473
|
(accessibleLineIds || []).filter(Boolean).filter((lineId) => lineId !== factoryViewId)
|
|
89618
90474
|
)).sort(),
|
|
89619
90475
|
[accessibleLineIds, factoryViewId]
|
|
89620
90476
|
);
|
|
89621
|
-
const lineIdsKey =
|
|
90477
|
+
const lineIdsKey = React148__default.useMemo(
|
|
89622
90478
|
() => normalizedLineIds.join(","),
|
|
89623
90479
|
[normalizedLineIds]
|
|
89624
90480
|
);
|
|
89625
|
-
const lineOptions =
|
|
90481
|
+
const lineOptions = React148__default.useMemo(
|
|
89626
90482
|
() => normalizedLineIds.map((lineId) => ({
|
|
89627
90483
|
id: lineId,
|
|
89628
90484
|
name: getLineDisplayName(entityConfig, lineId)
|
|
@@ -89634,7 +90490,7 @@ var PlantHeadView = () => {
|
|
|
89634
90490
|
companyId: entityConfig.companyId,
|
|
89635
90491
|
useBackend: true
|
|
89636
90492
|
});
|
|
89637
|
-
const supervisorOptions =
|
|
90493
|
+
const supervisorOptions = React148__default.useMemo(
|
|
89638
90494
|
() => {
|
|
89639
90495
|
const optionsById = /* @__PURE__ */ new Map();
|
|
89640
90496
|
normalizedLineIds.forEach((lineId) => {
|
|
@@ -89660,7 +90516,7 @@ var PlantHeadView = () => {
|
|
|
89660
90516
|
},
|
|
89661
90517
|
[normalizedLineIds, supervisorsByLineId]
|
|
89662
90518
|
);
|
|
89663
|
-
|
|
90519
|
+
React148__default.useEffect(() => {
|
|
89664
90520
|
if (selectedSupervisorId === "all") {
|
|
89665
90521
|
setSelectedLineIds((previous) => {
|
|
89666
90522
|
if (normalizedLineIds.length === 0) {
|
|
@@ -89686,7 +90542,7 @@ var PlantHeadView = () => {
|
|
|
89686
90542
|
const scopedSupervisorLineIds = normalizedLineIds.filter((lineId) => supervisorLineIdSet.has(lineId));
|
|
89687
90543
|
setSelectedLineIds((previous) => previous.length === scopedSupervisorLineIds.length && previous.every((lineId, index) => lineId === scopedSupervisorLineIds[index]) ? previous : scopedSupervisorLineIds);
|
|
89688
90544
|
}, [lineIdsKey, normalizedLineIds, selectedSupervisorId, supervisorOptions]);
|
|
89689
|
-
const scopedLineIds =
|
|
90545
|
+
const scopedLineIds = React148__default.useMemo(
|
|
89690
90546
|
() => selectedLineIds.length > 0 ? selectedLineIds : normalizedLineIds,
|
|
89691
90547
|
[normalizedLineIds, selectedLineIds]
|
|
89692
90548
|
);
|
|
@@ -89694,7 +90550,7 @@ var PlantHeadView = () => {
|
|
|
89694
90550
|
shiftConfigMap,
|
|
89695
90551
|
isLoading: isShiftConfigLoading
|
|
89696
90552
|
} = useMultiLineShiftConfigs(scopedLineIds, staticShiftConfig);
|
|
89697
|
-
const shiftFilterOptions =
|
|
90553
|
+
const shiftFilterOptions = React148__default.useMemo(() => {
|
|
89698
90554
|
const optionsById = /* @__PURE__ */ new Map();
|
|
89699
90555
|
scopedLineIds.forEach((lineId) => {
|
|
89700
90556
|
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
@@ -89733,7 +90589,7 @@ var PlantHeadView = () => {
|
|
|
89733
90589
|
...dynamicOptions
|
|
89734
90590
|
];
|
|
89735
90591
|
}, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
|
|
89736
|
-
|
|
90592
|
+
React148__default.useEffect(() => {
|
|
89737
90593
|
if (scopedLineIds.length === 0 || isShiftConfigLoading) {
|
|
89738
90594
|
return;
|
|
89739
90595
|
}
|
|
@@ -89744,11 +90600,11 @@ var PlantHeadView = () => {
|
|
|
89744
90600
|
clearInterval(intervalId);
|
|
89745
90601
|
};
|
|
89746
90602
|
}, [isShiftConfigLoading, scopedLineIds.length]);
|
|
89747
|
-
const shiftResolutionNow =
|
|
90603
|
+
const shiftResolutionNow = React148__default.useMemo(
|
|
89748
90604
|
() => /* @__PURE__ */ new Date(),
|
|
89749
90605
|
[shiftResolutionTick]
|
|
89750
90606
|
);
|
|
89751
|
-
const earliestDayShiftStartTime =
|
|
90607
|
+
const earliestDayShiftStartTime = React148__default.useMemo(() => {
|
|
89752
90608
|
const candidateStarts = [];
|
|
89753
90609
|
scopedLineIds.forEach((lineId) => {
|
|
89754
90610
|
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
@@ -89784,11 +90640,11 @@ var PlantHeadView = () => {
|
|
|
89784
90640
|
const minutes = earliestMinutes % 60;
|
|
89785
90641
|
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
89786
90642
|
}, [appTimezone, scopedLineIds, shiftConfigMap, staticShiftConfig]);
|
|
89787
|
-
const resolvedOperationalToday =
|
|
90643
|
+
const resolvedOperationalToday = React148__default.useMemo(
|
|
89788
90644
|
() => getOperationalDate(appTimezone, shiftResolutionNow, earliestDayShiftStartTime),
|
|
89789
90645
|
[appTimezone, earliestDayShiftStartTime, shiftResolutionNow]
|
|
89790
90646
|
);
|
|
89791
|
-
const activeLineShiftStates =
|
|
90647
|
+
const activeLineShiftStates = React148__default.useMemo(() => {
|
|
89792
90648
|
return scopedLineIds.flatMap((lineId) => {
|
|
89793
90649
|
const shiftConfig = shiftConfigMap.get(lineId) || staticShiftConfig;
|
|
89794
90650
|
const activeShift = getActiveShift(appTimezone, shiftConfig, shiftResolutionNow);
|
|
@@ -89818,7 +90674,7 @@ var PlantHeadView = () => {
|
|
|
89818
90674
|
});
|
|
89819
90675
|
}, [appTimezone, scopedLineIds, shiftConfigMap, shiftResolutionNow, staticShiftConfig]);
|
|
89820
90676
|
const resolvedTrendMode = isInitialScopeReady ? trendMode : "all";
|
|
89821
|
-
const hourlyWindowStartTime =
|
|
90677
|
+
const hourlyWindowStartTime = React148__default.useMemo(() => {
|
|
89822
90678
|
if (scopedLineIds.length === 0) {
|
|
89823
90679
|
return null;
|
|
89824
90680
|
}
|
|
@@ -89875,12 +90731,12 @@ var PlantHeadView = () => {
|
|
|
89875
90731
|
const minutes = earliestMinutes % 60;
|
|
89876
90732
|
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
89877
90733
|
}, [appTimezone, resolvedTrendMode, scopedLineIds, shiftConfigMap, staticShiftConfig]);
|
|
89878
|
-
const isShiftScopeResolved =
|
|
90734
|
+
const isShiftScopeResolved = React148__default.useMemo(
|
|
89879
90735
|
() => !isShiftConfigLoading,
|
|
89880
90736
|
[isShiftConfigLoading]
|
|
89881
90737
|
);
|
|
89882
|
-
const initializedTimezoneRef =
|
|
89883
|
-
|
|
90738
|
+
const initializedTimezoneRef = React148__default.useRef(appTimezone);
|
|
90739
|
+
React148__default.useEffect(() => {
|
|
89884
90740
|
if (initializedTimezoneRef.current === appTimezone) return;
|
|
89885
90741
|
hasAutoInitializedScopeRef.current = false;
|
|
89886
90742
|
hasUserAdjustedScopeRef.current = false;
|
|
@@ -89893,7 +90749,7 @@ var PlantHeadView = () => {
|
|
|
89893
90749
|
setIsInitialScopeReady(false);
|
|
89894
90750
|
initializedTimezoneRef.current = appTimezone;
|
|
89895
90751
|
}, [appTimezone, fallbackOperationalDate]);
|
|
89896
|
-
|
|
90752
|
+
React148__default.useEffect(() => {
|
|
89897
90753
|
if (hasAutoInitializedScopeRef.current || hasUserAdjustedScopeRef.current) {
|
|
89898
90754
|
return;
|
|
89899
90755
|
}
|
|
@@ -89918,7 +90774,7 @@ var PlantHeadView = () => {
|
|
|
89918
90774
|
hasAutoInitializedScopeRef.current = true;
|
|
89919
90775
|
setIsInitialScopeReady(true);
|
|
89920
90776
|
}, [fallbackOperationalDate, isShiftScopeResolved, resolvedOperationalToday, scopedLineIds.length]);
|
|
89921
|
-
const handleDateRangeChange =
|
|
90777
|
+
const handleDateRangeChange = React148__default.useCallback((range, meta) => {
|
|
89922
90778
|
hasUserAdjustedScopeRef.current = true;
|
|
89923
90779
|
setIsInitialScopeReady(true);
|
|
89924
90780
|
trackCoreEvent("Operations Overview Date Range Changed", {
|
|
@@ -89936,12 +90792,12 @@ var PlantHeadView = () => {
|
|
|
89936
90792
|
return previous;
|
|
89937
90793
|
});
|
|
89938
90794
|
}, []);
|
|
89939
|
-
const handleTrendModeChange =
|
|
90795
|
+
const handleTrendModeChange = React148__default.useCallback((mode) => {
|
|
89940
90796
|
hasUserAdjustedScopeRef.current = true;
|
|
89941
90797
|
setIsInitialScopeReady(true);
|
|
89942
90798
|
setTrendMode(mode);
|
|
89943
90799
|
}, []);
|
|
89944
|
-
const handleSelectedLineIdsChange =
|
|
90800
|
+
const handleSelectedLineIdsChange = React148__default.useCallback((lineIds) => {
|
|
89945
90801
|
setSelectedSupervisorId("all");
|
|
89946
90802
|
if (normalizedLineIds.length === 0) {
|
|
89947
90803
|
setSelectedLineIds([]);
|
|
@@ -89952,10 +90808,10 @@ var PlantHeadView = () => {
|
|
|
89952
90808
|
const next = normalizedLineIds.filter((lineId) => selectedSet.has(lineId));
|
|
89953
90809
|
setSelectedLineIds(next.length > 0 ? next : normalizedLineIds);
|
|
89954
90810
|
}, [normalizedLineIds]);
|
|
89955
|
-
const handleSelectedSupervisorIdChange =
|
|
90811
|
+
const handleSelectedSupervisorIdChange = React148__default.useCallback((supervisorId) => {
|
|
89956
90812
|
setSelectedSupervisorId(supervisorId);
|
|
89957
90813
|
}, []);
|
|
89958
|
-
const buildLineMonthlyHistoryUrl =
|
|
90814
|
+
const buildLineMonthlyHistoryUrl = React148__default.useCallback((lineId) => {
|
|
89959
90815
|
const rangeStartDate = parseDateKeyToDate(dateRange.startKey);
|
|
89960
90816
|
const params = new URLSearchParams();
|
|
89961
90817
|
params.set("tab", "monthly_history");
|
|
@@ -89965,15 +90821,15 @@ var PlantHeadView = () => {
|
|
|
89965
90821
|
params.set("rangeEnd", dateRange.endKey);
|
|
89966
90822
|
return `/kpis/${lineId}?${params.toString()}`;
|
|
89967
90823
|
}, [dateRange.endKey, dateRange.startKey]);
|
|
89968
|
-
const handleViewAllPoorestPerformers =
|
|
90824
|
+
const handleViewAllPoorestPerformers = React148__default.useCallback(() => {
|
|
89969
90825
|
trackCoreEvent("Operations Overview View All Clicked", { section: "poorest_performers" });
|
|
89970
90826
|
navigate("/kpis?tab=leaderboard");
|
|
89971
90827
|
}, [navigate]);
|
|
89972
|
-
const handleViewAllImprovements =
|
|
90828
|
+
const handleViewAllImprovements = React148__default.useCallback(() => {
|
|
89973
90829
|
trackCoreEvent("Operations Overview View All Clicked", { section: "improvements" });
|
|
89974
90830
|
navigate("/improvement-center");
|
|
89975
90831
|
}, [navigate]);
|
|
89976
|
-
const handleOpenImprovement =
|
|
90832
|
+
const handleOpenImprovement = React148__default.useCallback((item) => {
|
|
89977
90833
|
trackCoreEvent("Operations Overview Improvement Clicked", {
|
|
89978
90834
|
issue_id: item.issueId,
|
|
89979
90835
|
issue_number: item.issueNumber,
|
|
@@ -89984,13 +90840,13 @@ var PlantHeadView = () => {
|
|
|
89984
90840
|
});
|
|
89985
90841
|
navigate(`/improvement-center?${params.toString()}`);
|
|
89986
90842
|
}, [navigate]);
|
|
89987
|
-
const comparisonStrategy =
|
|
90843
|
+
const comparisonStrategy = React148__default.useMemo(() => {
|
|
89988
90844
|
if (usesThisWeekComparison && isCurrentWeekToDateRange) {
|
|
89989
90845
|
return "previous_full_week";
|
|
89990
90846
|
}
|
|
89991
90847
|
return void 0;
|
|
89992
90848
|
}, [isCurrentWeekToDateRange, usesThisWeekComparison]);
|
|
89993
|
-
const effectiveDateRange =
|
|
90849
|
+
const effectiveDateRange = React148__default.useMemo(() => {
|
|
89994
90850
|
if (isInitialScopeReady) {
|
|
89995
90851
|
return dateRange;
|
|
89996
90852
|
}
|
|
@@ -90000,11 +90856,11 @@ var PlantHeadView = () => {
|
|
|
90000
90856
|
endKey: nextStartKey
|
|
90001
90857
|
};
|
|
90002
90858
|
}, [dateRange, fallbackOperationalDate, isInitialScopeReady, resolvedOperationalToday]);
|
|
90003
|
-
const effectiveTrendMode =
|
|
90859
|
+
const effectiveTrendMode = React148__default.useMemo(
|
|
90004
90860
|
() => resolvedTrendMode,
|
|
90005
90861
|
[resolvedTrendMode]
|
|
90006
90862
|
);
|
|
90007
|
-
const hasActiveSelectedShiftLine =
|
|
90863
|
+
const hasActiveSelectedShiftLine = React148__default.useMemo(
|
|
90008
90864
|
() => activeLineShiftStates.some((shift) => {
|
|
90009
90865
|
if (shift.date !== resolvedOperationalToday) return false;
|
|
90010
90866
|
if (effectiveTrendMode === "all") return true;
|
|
@@ -90016,7 +90872,7 @@ var PlantHeadView = () => {
|
|
|
90016
90872
|
}),
|
|
90017
90873
|
[activeLineShiftStates, effectiveTrendMode, resolvedOperationalToday]
|
|
90018
90874
|
);
|
|
90019
|
-
const activeLiveShiftName =
|
|
90875
|
+
const activeLiveShiftName = React148__default.useMemo(
|
|
90020
90876
|
() => {
|
|
90021
90877
|
if (effectiveTrendMode === "all") return null;
|
|
90022
90878
|
const matchingShift = activeLineShiftStates.find((shift) => {
|
|
@@ -90031,17 +90887,17 @@ var PlantHeadView = () => {
|
|
|
90031
90887
|
},
|
|
90032
90888
|
[activeLineShiftStates, effectiveTrendMode, resolvedOperationalToday]
|
|
90033
90889
|
);
|
|
90034
|
-
const hourlyLabelStartTime =
|
|
90890
|
+
const hourlyLabelStartTime = React148__default.useMemo(() => {
|
|
90035
90891
|
if (scopedLineIds.length === 0) {
|
|
90036
90892
|
return null;
|
|
90037
90893
|
}
|
|
90038
90894
|
return hourlyWindowStartTime;
|
|
90039
90895
|
}, [hourlyWindowStartTime, scopedLineIds.length]);
|
|
90040
|
-
const isSingleDayScope =
|
|
90896
|
+
const isSingleDayScope = React148__default.useMemo(
|
|
90041
90897
|
() => effectiveDateRange.startKey === effectiveDateRange.endKey,
|
|
90042
90898
|
[effectiveDateRange.endKey, effectiveDateRange.startKey]
|
|
90043
90899
|
);
|
|
90044
|
-
const isLiveScope =
|
|
90900
|
+
const isLiveScope = React148__default.useMemo(
|
|
90045
90901
|
() => isSingleDayScope && effectiveDateRange.startKey === resolvedOperationalToday && hasActiveSelectedShiftLine,
|
|
90046
90902
|
[
|
|
90047
90903
|
effectiveDateRange.startKey,
|
|
@@ -90051,7 +90907,7 @@ var PlantHeadView = () => {
|
|
|
90051
90907
|
resolvedOperationalToday
|
|
90052
90908
|
]
|
|
90053
90909
|
);
|
|
90054
|
-
const handleOpenLineDetails =
|
|
90910
|
+
const handleOpenLineDetails = React148__default.useCallback((line) => {
|
|
90055
90911
|
trackCoreEvent("Operations Overview Line Clicked", {
|
|
90056
90912
|
line_id: line.rowType === "line" ? line.id : null,
|
|
90057
90913
|
line_name: line.name,
|