@optifye/dashboard-core 6.11.13 → 6.11.15
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 +13 -0
- package/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +362 -97
- package/dist/index.mjs +362 -97
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -11771,6 +11771,9 @@ var toWorkspaceDetailedMetrics = ({
|
|
|
11771
11771
|
const idealOutput = coerceNumber(data.ideal_output ?? data.ideal_output_until_now, 0);
|
|
11772
11772
|
const outputDifference = totalActions - idealOutput;
|
|
11773
11773
|
const hourlyCycleTimes = Array.isArray(data.hourly_cycle_times) ? data.hourly_cycle_times.map((value) => coerceNumber(value, 0)) : [];
|
|
11774
|
+
const cycleCompletionClipCount = data.cycle_completion_clip_count === null || data.cycle_completion_clip_count === void 0 ? null : coerceNumber(data.cycle_completion_clip_count, 0);
|
|
11775
|
+
const cycleTimeDataStatus = data.cycle_time_data_status === "missing_clips" ? "missing_clips" : data.cycle_time_data_status === "available" ? "available" : null;
|
|
11776
|
+
const cycleTimeTimezone = typeof data.cycle_time_timezone === "string" ? data.cycle_time_timezone : null;
|
|
11774
11777
|
const totalWorkspacesValue = coerceNumber(
|
|
11775
11778
|
data.total_workspaces ?? lineMetricsById?.[data.line_id || ""]?.total_workspaces ?? workspaceConfig.totalWorkspaces,
|
|
11776
11779
|
0
|
|
@@ -11818,6 +11821,9 @@ var toWorkspaceDetailedMetrics = ({
|
|
|
11818
11821
|
total_actions: totalActions,
|
|
11819
11822
|
hourly_action_counts: hourlyActionCounts,
|
|
11820
11823
|
hourly_cycle_times: hourlyCycleTimes,
|
|
11824
|
+
cycle_completion_clip_count: cycleCompletionClipCount,
|
|
11825
|
+
cycle_time_data_status: cycleTimeDataStatus,
|
|
11826
|
+
cycle_time_timezone: cycleTimeTimezone,
|
|
11821
11827
|
workspace_rank: coerceNumber(data.workspace_rank, 0),
|
|
11822
11828
|
total_workspaces: totalWorkspacesValue,
|
|
11823
11829
|
ideal_output_until_now: idealOutput,
|
|
@@ -32698,16 +32704,162 @@ var CycleTimeOverTimeChart = ({
|
|
|
32698
32704
|
return `${minutes} minutes ${seconds} seconds ago`;
|
|
32699
32705
|
}
|
|
32700
32706
|
};
|
|
32707
|
+
const getNumericValue = React141__namespace.default.useCallback((value) => typeof value === "number" && Number.isFinite(value) ? value : null, []);
|
|
32708
|
+
const renderChartTooltip = React141__namespace.default.useCallback((tooltipProps) => {
|
|
32709
|
+
const { active, payload } = tooltipProps;
|
|
32710
|
+
if (!active || !Array.isArray(payload) || payload.length === 0) {
|
|
32711
|
+
return null;
|
|
32712
|
+
}
|
|
32713
|
+
const visibleEntries = payload.filter((entry) => getNumericValue(entry.value) !== null);
|
|
32714
|
+
if (!visibleEntries.length) {
|
|
32715
|
+
return null;
|
|
32716
|
+
}
|
|
32717
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
32718
|
+
"div",
|
|
32719
|
+
{
|
|
32720
|
+
style: {
|
|
32721
|
+
backgroundColor: "white",
|
|
32722
|
+
border: "none",
|
|
32723
|
+
borderRadius: "8px",
|
|
32724
|
+
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
|
|
32725
|
+
padding: "8px 12px",
|
|
32726
|
+
fontSize: "13px"
|
|
32727
|
+
},
|
|
32728
|
+
children: [
|
|
32729
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
32730
|
+
"div",
|
|
32731
|
+
{
|
|
32732
|
+
style: {
|
|
32733
|
+
color: "#374151",
|
|
32734
|
+
fontWeight: 600,
|
|
32735
|
+
marginBottom: "4px"
|
|
32736
|
+
},
|
|
32737
|
+
children: payload[0]?.payload?.tooltip || ""
|
|
32738
|
+
}
|
|
32739
|
+
),
|
|
32740
|
+
visibleEntries.map((entry) => {
|
|
32741
|
+
const numericValue = getNumericValue(entry.value);
|
|
32742
|
+
if (numericValue === null) {
|
|
32743
|
+
return null;
|
|
32744
|
+
}
|
|
32745
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32746
|
+
"div",
|
|
32747
|
+
{
|
|
32748
|
+
style: {
|
|
32749
|
+
color: "#4B5563",
|
|
32750
|
+
padding: "2px 0"
|
|
32751
|
+
},
|
|
32752
|
+
children: entry.name === "idleMinutes" ? `Idle Time: ${numericValue.toFixed(0)} minutes` : `Cycle Time: ${numericValue.toFixed(1)} seconds`
|
|
32753
|
+
},
|
|
32754
|
+
`${entry.name}-${numericValue}`
|
|
32755
|
+
);
|
|
32756
|
+
})
|
|
32757
|
+
]
|
|
32758
|
+
}
|
|
32759
|
+
);
|
|
32760
|
+
}, [getNumericValue]);
|
|
32761
|
+
const renderCycleDot = React141__namespace.default.useCallback((props) => {
|
|
32762
|
+
const { cx: cx2, cy, payload } = props;
|
|
32763
|
+
const cycleTime = getNumericValue(payload?.cycleTime);
|
|
32764
|
+
if (cycleTime === null) {
|
|
32765
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", {});
|
|
32766
|
+
}
|
|
32767
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32768
|
+
"circle",
|
|
32769
|
+
{
|
|
32770
|
+
cx: cx2,
|
|
32771
|
+
cy,
|
|
32772
|
+
r: 4,
|
|
32773
|
+
fill: cycleTime <= idealCycleTime ? "#00AB45" : "#E34329",
|
|
32774
|
+
stroke: "#fff",
|
|
32775
|
+
strokeWidth: 1,
|
|
32776
|
+
style: {
|
|
32777
|
+
filter: "brightness(1)",
|
|
32778
|
+
transition: "filter 0.3s ease, transform 0.3s ease",
|
|
32779
|
+
cursor: "pointer"
|
|
32780
|
+
},
|
|
32781
|
+
onMouseEnter: (e) => {
|
|
32782
|
+
const target = e.target;
|
|
32783
|
+
target.style.filter = "brightness(1.2)";
|
|
32784
|
+
target.style.transform = "scale(1.2)";
|
|
32785
|
+
},
|
|
32786
|
+
onMouseLeave: (e) => {
|
|
32787
|
+
const target = e.target;
|
|
32788
|
+
target.style.filter = "brightness(1)";
|
|
32789
|
+
target.style.transform = "scale(1)";
|
|
32790
|
+
}
|
|
32791
|
+
}
|
|
32792
|
+
);
|
|
32793
|
+
}, [getNumericValue, idealCycleTime]);
|
|
32794
|
+
const renderCycleActiveDot = React141__namespace.default.useCallback((props) => {
|
|
32795
|
+
const { cx: cx2, cy, payload } = props;
|
|
32796
|
+
const cycleTime = getNumericValue(payload?.cycleTime);
|
|
32797
|
+
if (cycleTime === null) {
|
|
32798
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", {});
|
|
32799
|
+
}
|
|
32800
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32801
|
+
"circle",
|
|
32802
|
+
{
|
|
32803
|
+
cx: cx2,
|
|
32804
|
+
cy,
|
|
32805
|
+
r: 6,
|
|
32806
|
+
fill: cycleTime <= idealCycleTime ? "#00AB45" : "#E34329",
|
|
32807
|
+
stroke: "#fff",
|
|
32808
|
+
strokeWidth: 2,
|
|
32809
|
+
style: {
|
|
32810
|
+
filter: "drop-shadow(0 0 2px rgba(0,0,0,0.2))"
|
|
32811
|
+
}
|
|
32812
|
+
}
|
|
32813
|
+
);
|
|
32814
|
+
}, [getNumericValue, idealCycleTime]);
|
|
32815
|
+
const renderIdleDot = React141__namespace.default.useCallback((props) => {
|
|
32816
|
+
const { cx: cx2, cy, payload } = props;
|
|
32817
|
+
const idleMinutes = getNumericValue(payload?.idleMinutes);
|
|
32818
|
+
if (idleMinutes === null) {
|
|
32819
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", {});
|
|
32820
|
+
}
|
|
32821
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32822
|
+
"circle",
|
|
32823
|
+
{
|
|
32824
|
+
cx: cx2,
|
|
32825
|
+
cy,
|
|
32826
|
+
r: 4,
|
|
32827
|
+
fill: "#f59e0b",
|
|
32828
|
+
stroke: "#fff",
|
|
32829
|
+
strokeWidth: 1
|
|
32830
|
+
}
|
|
32831
|
+
);
|
|
32832
|
+
}, [getNumericValue]);
|
|
32833
|
+
const renderIdleActiveDot = React141__namespace.default.useCallback((props) => {
|
|
32834
|
+
const { cx: cx2, cy, payload } = props;
|
|
32835
|
+
const idleMinutes = getNumericValue(payload?.idleMinutes);
|
|
32836
|
+
if (idleMinutes === null) {
|
|
32837
|
+
return /* @__PURE__ */ jsxRuntime.jsx("g", {});
|
|
32838
|
+
}
|
|
32839
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32840
|
+
"circle",
|
|
32841
|
+
{
|
|
32842
|
+
cx: cx2,
|
|
32843
|
+
cy,
|
|
32844
|
+
r: 6,
|
|
32845
|
+
fill: "#f59e0b",
|
|
32846
|
+
stroke: "#fff",
|
|
32847
|
+
strokeWidth: 2
|
|
32848
|
+
}
|
|
32849
|
+
);
|
|
32850
|
+
}, [getNumericValue]);
|
|
32701
32851
|
const chartData = React141__namespace.default.useMemo(() => Array.from({ length: DURATION }, (_, i) => {
|
|
32852
|
+
const cycleTime = getNumericValue(finalData[i]);
|
|
32853
|
+
const idleMinutes = showIdleTime ? getNumericValue(idleTimeData[i]) : null;
|
|
32702
32854
|
return {
|
|
32703
32855
|
timeIndex: i,
|
|
32704
32856
|
label: formatTimeLabel(i),
|
|
32705
32857
|
tooltip: formatTooltipTime(i),
|
|
32706
|
-
cycleTime
|
|
32707
|
-
idleMinutes
|
|
32708
|
-
color:
|
|
32858
|
+
cycleTime,
|
|
32859
|
+
idleMinutes,
|
|
32860
|
+
color: cycleTime !== null && cycleTime <= idealCycleTime ? "#00AB45" : "#E34329"
|
|
32709
32861
|
};
|
|
32710
|
-
}), [DURATION, finalData, showIdleTime, idleTimeData, idealCycleTime]);
|
|
32862
|
+
}), [DURATION, finalData, showIdleTime, idleTimeData, idealCycleTime, getNumericValue]);
|
|
32711
32863
|
const renderLegend = () => {
|
|
32712
32864
|
if (!showIdleTime) return null;
|
|
32713
32865
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-start text-[10px] font-bold text-gray-500 mb-6 tracking-[0.05em] gap-5", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
@@ -32794,36 +32946,7 @@ var CycleTimeOverTimeChart = ({
|
|
|
32794
32946
|
recharts.Tooltip,
|
|
32795
32947
|
{
|
|
32796
32948
|
cursor: { stroke: "#E5E7EB", strokeWidth: 1 },
|
|
32797
|
-
|
|
32798
|
-
backgroundColor: "white",
|
|
32799
|
-
border: "none",
|
|
32800
|
-
borderRadius: "8px",
|
|
32801
|
-
boxShadow: "0 4px 12px rgba(0,0,0,0.1)",
|
|
32802
|
-
padding: "8px 12px",
|
|
32803
|
-
fontSize: "13px"
|
|
32804
|
-
},
|
|
32805
|
-
labelStyle: {
|
|
32806
|
-
color: "#374151",
|
|
32807
|
-
fontWeight: 600,
|
|
32808
|
-
marginBottom: "4px"
|
|
32809
|
-
},
|
|
32810
|
-
itemStyle: {
|
|
32811
|
-
color: "#4B5563",
|
|
32812
|
-
padding: "2px 0"
|
|
32813
|
-
},
|
|
32814
|
-
labelFormatter: (label, payload) => {
|
|
32815
|
-
if (payload && payload[0]) {
|
|
32816
|
-
return payload[0].payload.tooltip;
|
|
32817
|
-
}
|
|
32818
|
-
return label;
|
|
32819
|
-
},
|
|
32820
|
-
formatter: (value, name) => {
|
|
32821
|
-
const numValue = typeof value === "number" ? value : Number(value);
|
|
32822
|
-
if (name === "idleMinutes") {
|
|
32823
|
-
return [`${numValue.toFixed(0)} minutes`, "Idle Time"];
|
|
32824
|
-
}
|
|
32825
|
-
return [`${numValue.toFixed(1)} seconds`, "Cycle Time"];
|
|
32826
|
-
},
|
|
32949
|
+
content: renderChartTooltip,
|
|
32827
32950
|
animationDuration: 200
|
|
32828
32951
|
}
|
|
32829
32952
|
),
|
|
@@ -32852,52 +32975,9 @@ var CycleTimeOverTimeChart = ({
|
|
|
32852
32975
|
dataKey: "cycleTime",
|
|
32853
32976
|
stroke: "#3B82F6",
|
|
32854
32977
|
strokeWidth: 2,
|
|
32855
|
-
|
|
32856
|
-
|
|
32857
|
-
|
|
32858
|
-
"circle",
|
|
32859
|
-
{
|
|
32860
|
-
cx: cx2,
|
|
32861
|
-
cy,
|
|
32862
|
-
r: 4,
|
|
32863
|
-
fill: payload.cycleTime <= idealCycleTime ? "#00AB45" : "#E34329",
|
|
32864
|
-
stroke: "#fff",
|
|
32865
|
-
strokeWidth: 1,
|
|
32866
|
-
style: {
|
|
32867
|
-
filter: "brightness(1)",
|
|
32868
|
-
transition: "filter 0.3s ease, transform 0.3s ease",
|
|
32869
|
-
cursor: "pointer"
|
|
32870
|
-
},
|
|
32871
|
-
onMouseEnter: (e) => {
|
|
32872
|
-
const target = e.target;
|
|
32873
|
-
target.style.filter = "brightness(1.2)";
|
|
32874
|
-
target.style.transform = "scale(1.2)";
|
|
32875
|
-
},
|
|
32876
|
-
onMouseLeave: (e) => {
|
|
32877
|
-
const target = e.target;
|
|
32878
|
-
target.style.filter = "brightness(1)";
|
|
32879
|
-
target.style.transform = "scale(1)";
|
|
32880
|
-
}
|
|
32881
|
-
}
|
|
32882
|
-
);
|
|
32883
|
-
},
|
|
32884
|
-
activeDot: (props) => {
|
|
32885
|
-
const { cx: cx2, cy, payload } = props;
|
|
32886
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32887
|
-
"circle",
|
|
32888
|
-
{
|
|
32889
|
-
cx: cx2,
|
|
32890
|
-
cy,
|
|
32891
|
-
r: 6,
|
|
32892
|
-
fill: payload.cycleTime <= idealCycleTime ? "#00AB45" : "#E34329",
|
|
32893
|
-
stroke: "#fff",
|
|
32894
|
-
strokeWidth: 2,
|
|
32895
|
-
style: {
|
|
32896
|
-
filter: "drop-shadow(0 0 2px rgba(0,0,0,0.2))"
|
|
32897
|
-
}
|
|
32898
|
-
}
|
|
32899
|
-
);
|
|
32900
|
-
},
|
|
32978
|
+
connectNulls: false,
|
|
32979
|
+
dot: renderCycleDot,
|
|
32980
|
+
activeDot: renderCycleActiveDot,
|
|
32901
32981
|
isAnimationActive: shouldAnimate,
|
|
32902
32982
|
animationBegin: 0,
|
|
32903
32983
|
animationDuration: 1200,
|
|
@@ -32915,8 +32995,9 @@ var CycleTimeOverTimeChart = ({
|
|
|
32915
32995
|
stroke: "#f59e0b",
|
|
32916
32996
|
strokeWidth: 2,
|
|
32917
32997
|
strokeDasharray: "4 4",
|
|
32918
|
-
|
|
32919
|
-
|
|
32998
|
+
connectNulls: false,
|
|
32999
|
+
dot: renderIdleDot,
|
|
33000
|
+
activeDot: renderIdleActiveDot,
|
|
32920
33001
|
isAnimationActive: shouldAnimate,
|
|
32921
33002
|
animationBegin: 0,
|
|
32922
33003
|
animationDuration: 1200,
|
|
@@ -34644,8 +34725,20 @@ var CardFooter2 = (props) => {
|
|
|
34644
34725
|
return /* @__PURE__ */ jsxRuntime.jsx(RegisteredCardFooter, { ...props });
|
|
34645
34726
|
};
|
|
34646
34727
|
|
|
34728
|
+
// src/lib/utils/workspaceDetailCycleTime.ts
|
|
34729
|
+
var resolveWorkspaceDetailActionFamily = (workspace) => {
|
|
34730
|
+
if (workspace?.action_family === "assembly" || workspace?.action_family === "output" || workspace?.action_family === "other") {
|
|
34731
|
+
return workspace.action_family;
|
|
34732
|
+
}
|
|
34733
|
+
if (workspace?.action_type === "assembly" || workspace?.action_type === "output") {
|
|
34734
|
+
return workspace.action_type;
|
|
34735
|
+
}
|
|
34736
|
+
return null;
|
|
34737
|
+
};
|
|
34738
|
+
var shouldUseAssemblyCycleTimeLayout = (workspace) => workspace?.line_assembly_enabled === true && resolveWorkspaceDetailActionFamily(workspace) === "assembly";
|
|
34739
|
+
|
|
34647
34740
|
// src/components/dashboard/workspace/workspaceDetailCardRules.ts
|
|
34648
|
-
var shouldHideWorkspaceEfficiencyCard = (workspace) => workspace
|
|
34741
|
+
var shouldHideWorkspaceEfficiencyCard = (workspace) => shouldUseAssemblyCycleTimeLayout(workspace);
|
|
34649
34742
|
var WorkspaceMetricCardsImpl = ({
|
|
34650
34743
|
workspace,
|
|
34651
34744
|
className,
|
|
@@ -35354,6 +35447,37 @@ var getShiftElapsedMinutes = ({
|
|
|
35354
35447
|
const elapsed = dateFns.differenceInMinutes(now4, shiftStartDate);
|
|
35355
35448
|
return Math.min(Math.max(elapsed, 0), shiftMinutes);
|
|
35356
35449
|
};
|
|
35450
|
+
var maskFutureHourlySeries = ({
|
|
35451
|
+
data,
|
|
35452
|
+
shiftStart,
|
|
35453
|
+
shiftEnd,
|
|
35454
|
+
shiftDate,
|
|
35455
|
+
timezone,
|
|
35456
|
+
now: now4 = /* @__PURE__ */ new Date()
|
|
35457
|
+
}) => {
|
|
35458
|
+
if (!Array.isArray(data)) {
|
|
35459
|
+
return [];
|
|
35460
|
+
}
|
|
35461
|
+
const normalizedData = data.map((value) => typeof value === "number" && Number.isFinite(value) ? value : null);
|
|
35462
|
+
if (!normalizedData.length) {
|
|
35463
|
+
return normalizedData;
|
|
35464
|
+
}
|
|
35465
|
+
const shiftMinutes = getShiftDurationMinutes(shiftStart, shiftEnd);
|
|
35466
|
+
const elapsedMinutes = getShiftElapsedMinutes({
|
|
35467
|
+
shiftStart,
|
|
35468
|
+
shiftEnd,
|
|
35469
|
+
shiftDate,
|
|
35470
|
+
timezone,
|
|
35471
|
+
now: now4
|
|
35472
|
+
});
|
|
35473
|
+
if (shiftMinutes === null || elapsedMinutes === null || elapsedMinutes >= shiftMinutes) {
|
|
35474
|
+
return normalizedData;
|
|
35475
|
+
}
|
|
35476
|
+
return normalizedData.map((value, index) => {
|
|
35477
|
+
const slotStartMinutes = index * 60;
|
|
35478
|
+
return slotStartMinutes > elapsedMinutes ? null : value;
|
|
35479
|
+
});
|
|
35480
|
+
};
|
|
35357
35481
|
var buildUptimeSeries = ({
|
|
35358
35482
|
idleTimeHourly,
|
|
35359
35483
|
shiftStart,
|
|
@@ -48892,7 +49016,7 @@ var WorkspacePdfGenerator = ({ workspace, className, idleTimeReasons, efficiency
|
|
|
48892
49016
|
setIsGenerating(true);
|
|
48893
49017
|
try {
|
|
48894
49018
|
const isUptimeMode = workspace.monitoring_mode === "uptime";
|
|
48895
|
-
const isAssemblyCycleMode = !isUptimeMode && workspace
|
|
49019
|
+
const isAssemblyCycleMode = !isUptimeMode && shouldUseAssemblyCycleTimeLayout(workspace);
|
|
48896
49020
|
const shiftMinutes = getShiftDurationMinutes(workspace.shift_start, workspace.shift_end);
|
|
48897
49021
|
const shiftSeconds = shiftMinutes ? shiftMinutes * 60 : 0;
|
|
48898
49022
|
const idleSeconds = Math.max(workspace.idle_time || 0, 0);
|
|
@@ -60353,6 +60477,7 @@ var MonthlyRangeFilter = ({
|
|
|
60353
60477
|
{
|
|
60354
60478
|
type: "button",
|
|
60355
60479
|
onClick: () => setIsOpen((prev) => !prev),
|
|
60480
|
+
"aria-label": showLabel ? void 0 : singleDateOnly ? "Select date" : "Select date range",
|
|
60356
60481
|
className: clsx(
|
|
60357
60482
|
"flex items-center transition-all duration-200 focus:outline-none",
|
|
60358
60483
|
!showLabel && "p-2 rounded-full hover:bg-gray-100",
|
|
@@ -62965,7 +63090,7 @@ var KPIsOverviewView = ({
|
|
|
62965
63090
|
() => getShiftEndDate(currentShiftDetails, configuredTimezone),
|
|
62966
63091
|
[currentShiftDetails, configuredTimezone]
|
|
62967
63092
|
);
|
|
62968
|
-
React141__namespace.default.useMemo(() => {
|
|
63093
|
+
const leaderboardShiftOptions = React141__namespace.default.useMemo(() => {
|
|
62969
63094
|
if (shiftConfig?.shifts && shiftConfig.shifts.length > 0) {
|
|
62970
63095
|
return shiftConfig.shifts.map((shift) => ({
|
|
62971
63096
|
id: shift.shiftId,
|
|
@@ -63764,6 +63889,17 @@ var KPIsOverviewView = ({
|
|
|
63764
63889
|
singleDateOnly: true
|
|
63765
63890
|
}
|
|
63766
63891
|
),
|
|
63892
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
63893
|
+
"select",
|
|
63894
|
+
{
|
|
63895
|
+
"aria-label": "Leaderboard shift",
|
|
63896
|
+
value: effectiveLeaderboardShiftId,
|
|
63897
|
+
onChange: (e) => setSelectedLeaderboardShiftId(Number(e.target.value)),
|
|
63898
|
+
className: "appearance-none pl-3 pr-8 py-1.5 text-sm font-medium bg-white border border-gray-200 hover:border-gray-300 rounded-lg text-gray-700 focus:outline-none focus:ring-2 focus:ring-blue-500 transition-all cursor-pointer shadow-sm min-w-[170px]",
|
|
63899
|
+
style: { backgroundImage: `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`, backgroundPosition: `right 0.5rem center`, backgroundRepeat: `no-repeat`, backgroundSize: `1.2em 1.2em` },
|
|
63900
|
+
children: leaderboardShiftOptions.map((shiftOption) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: shiftOption.id, children: shiftOption.label }, shiftOption.id))
|
|
63901
|
+
}
|
|
63902
|
+
) }),
|
|
63767
63903
|
isHistoricalLeaderboardDaily && /* @__PURE__ */ jsxRuntime.jsx(
|
|
63768
63904
|
"button",
|
|
63769
63905
|
{
|
|
@@ -68051,8 +68187,74 @@ var TargetsView = ({
|
|
|
68051
68187
|
var TargetsViewWithDisplayNames = withAllWorkspaceDisplayNames(TargetsView);
|
|
68052
68188
|
var TargetsView_default = TargetsViewWithDisplayNames;
|
|
68053
68189
|
var AuthenticatedTargetsView = withAuth(React141__namespace.default.memo(TargetsViewWithDisplayNames));
|
|
68190
|
+
function useTimezone(options = {}) {
|
|
68191
|
+
const dashboardConfig = useDashboardConfig();
|
|
68192
|
+
const workspaceConfig = useWorkspaceConfig();
|
|
68193
|
+
const defaultTimezone = dashboardConfig?.dateTimeConfig?.defaultTimezone || "Asia/Kolkata";
|
|
68194
|
+
const [timezone, setTimezone] = React141.useState(defaultTimezone);
|
|
68195
|
+
const [isLoading, setIsLoading] = React141.useState(true);
|
|
68196
|
+
const [error, setError] = React141.useState(null);
|
|
68197
|
+
const fetchTimezone = React141.useCallback(async () => {
|
|
68198
|
+
setIsLoading(true);
|
|
68199
|
+
setError(null);
|
|
68200
|
+
try {
|
|
68201
|
+
let fetchedTimezone = defaultTimezone;
|
|
68202
|
+
if (options.lineId) {
|
|
68203
|
+
fetchedTimezone = await timezoneService.getTimezoneForLine(options.lineId, defaultTimezone);
|
|
68204
|
+
} else if (options.workspaceId || workspaceConfig && "id" in workspaceConfig) {
|
|
68205
|
+
const wsId = options.workspaceId || (workspaceConfig && "id" in workspaceConfig ? workspaceConfig.id : void 0);
|
|
68206
|
+
if (wsId) {
|
|
68207
|
+
fetchedTimezone = await timezoneService.getTimezoneForWorkspace(wsId, defaultTimezone);
|
|
68208
|
+
}
|
|
68209
|
+
} else if (options.companyId || dashboardConfig && "company" in dashboardConfig) {
|
|
68210
|
+
const compId = options.companyId || (dashboardConfig && "company" in dashboardConfig ? dashboardConfig.company?.id : void 0);
|
|
68211
|
+
if (compId) {
|
|
68212
|
+
fetchedTimezone = await timezoneService.getTimezoneForCompany(compId, defaultTimezone);
|
|
68213
|
+
}
|
|
68214
|
+
}
|
|
68215
|
+
setTimezone(fetchedTimezone);
|
|
68216
|
+
} catch (err) {
|
|
68217
|
+
console.error("Error fetching timezone:", err);
|
|
68218
|
+
setError(err instanceof Error ? err : new Error("Failed to fetch timezone"));
|
|
68219
|
+
setTimezone(defaultTimezone);
|
|
68220
|
+
} finally {
|
|
68221
|
+
setIsLoading(false);
|
|
68222
|
+
}
|
|
68223
|
+
}, [
|
|
68224
|
+
options.lineId,
|
|
68225
|
+
options.workspaceId,
|
|
68226
|
+
options.companyId,
|
|
68227
|
+
workspaceConfig,
|
|
68228
|
+
dashboardConfig,
|
|
68229
|
+
defaultTimezone
|
|
68230
|
+
]);
|
|
68231
|
+
React141.useEffect(() => {
|
|
68232
|
+
fetchTimezone();
|
|
68233
|
+
}, [fetchTimezone]);
|
|
68234
|
+
return {
|
|
68235
|
+
timezone,
|
|
68236
|
+
isLoading,
|
|
68237
|
+
error,
|
|
68238
|
+
refetch: fetchTimezone
|
|
68239
|
+
};
|
|
68240
|
+
}
|
|
68054
68241
|
|
|
68055
68242
|
// src/views/workspace-detail-view.utils.ts
|
|
68243
|
+
var getWorkspaceCycleTimePresentation = ({
|
|
68244
|
+
workspace,
|
|
68245
|
+
showCycleTimeChart
|
|
68246
|
+
}) => {
|
|
68247
|
+
if (workspace?.monitoring_mode === "uptime") {
|
|
68248
|
+
return "output";
|
|
68249
|
+
}
|
|
68250
|
+
if (showCycleTimeChart === false) {
|
|
68251
|
+
return "output";
|
|
68252
|
+
}
|
|
68253
|
+
if (!shouldUseAssemblyCycleTimeLayout(workspace)) {
|
|
68254
|
+
return "output";
|
|
68255
|
+
}
|
|
68256
|
+
return workspace?.cycle_time_data_status === "missing_clips" ? "cycle_unavailable" : "cycle_chart";
|
|
68257
|
+
};
|
|
68056
68258
|
var formatDateInTimezone = (date = /* @__PURE__ */ new Date(), timezone, options) => {
|
|
68057
68259
|
const defaultOptions = {
|
|
68058
68260
|
day: "numeric",
|
|
@@ -68436,6 +68638,7 @@ var WorkspaceDetailView = ({
|
|
|
68436
68638
|
date: cachedOverviewMetrics.date,
|
|
68437
68639
|
shift_id: cachedOverviewMetrics.shift_id,
|
|
68438
68640
|
action_name: "",
|
|
68641
|
+
action_family: cachedOverviewMetrics.action_family ?? null,
|
|
68439
68642
|
action_type: cachedOverviewMetrics.action_type ?? null,
|
|
68440
68643
|
monitoring_mode: cachedOverviewMetrics.monitoring_mode ?? "output",
|
|
68441
68644
|
shift_start: shiftDefinition?.startTime || "",
|
|
@@ -68459,6 +68662,11 @@ var WorkspaceDetailView = ({
|
|
|
68459
68662
|
};
|
|
68460
68663
|
}, [cachedOverviewMetrics, shiftConfig?.shifts]);
|
|
68461
68664
|
const workspace = (isHistoricView ? historicMetrics : liveMetrics) || cachedDetailedMetrics || overviewFallback;
|
|
68665
|
+
const { timezone: cycleTimeTimezone } = useTimezone({
|
|
68666
|
+
lineId: effectiveLineId || workspace?.line_id || void 0,
|
|
68667
|
+
workspaceId: workspaceId || void 0
|
|
68668
|
+
});
|
|
68669
|
+
const effectiveCycleTimeTimezone = cycleTimeTimezone || timezone;
|
|
68462
68670
|
const detailedWorkspaceMetrics = (isHistoricView ? historicMetrics : liveMetrics) || cachedDetailedMetrics;
|
|
68463
68671
|
const cycleTimeChartData = React141.useMemo(
|
|
68464
68672
|
() => Array.isArray(workspace?.hourly_cycle_times) ? workspace.hourly_cycle_times.map((value) => {
|
|
@@ -68467,12 +68675,31 @@ var WorkspaceDetailView = ({
|
|
|
68467
68675
|
}) : [],
|
|
68468
68676
|
[workspace?.hourly_cycle_times]
|
|
68469
68677
|
);
|
|
68678
|
+
const maskedCycleTimeChartData = React141.useMemo(
|
|
68679
|
+
() => maskFutureHourlySeries({
|
|
68680
|
+
data: cycleTimeChartData,
|
|
68681
|
+
shiftStart: workspace?.shift_start,
|
|
68682
|
+
shiftEnd: workspace?.shift_end,
|
|
68683
|
+
shiftDate: workspace?.date || date || calculatedOperationalDate || null,
|
|
68684
|
+
timezone: effectiveCycleTimeTimezone
|
|
68685
|
+
}),
|
|
68686
|
+
[
|
|
68687
|
+
cycleTimeChartData,
|
|
68688
|
+
workspace?.shift_start,
|
|
68689
|
+
workspace?.shift_end,
|
|
68690
|
+
workspace?.date,
|
|
68691
|
+
date,
|
|
68692
|
+
calculatedOperationalDate,
|
|
68693
|
+
effectiveCycleTimeTimezone
|
|
68694
|
+
]
|
|
68695
|
+
);
|
|
68470
68696
|
const cycleTimeDatasetKey = React141.useMemo(
|
|
68471
68697
|
() => [
|
|
68472
68698
|
workspace?.workspace_id || workspaceId || "workspace",
|
|
68473
68699
|
date || workspace?.date || "live",
|
|
68474
68700
|
parsedShiftId ?? workspace?.shift_id ?? "current",
|
|
68475
|
-
"hourly"
|
|
68701
|
+
"hourly",
|
|
68702
|
+
"backend"
|
|
68476
68703
|
].join(":"),
|
|
68477
68704
|
[workspace?.workspace_id, workspaceId, date, workspace?.date, parsedShiftId, workspace?.shift_id]
|
|
68478
68705
|
);
|
|
@@ -68717,14 +68944,28 @@ var WorkspaceDetailView = ({
|
|
|
68717
68944
|
return filterDataByDateKeyRange(monthlyData, range);
|
|
68718
68945
|
}, [monthlyData, range]);
|
|
68719
68946
|
const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
|
|
68720
|
-
const
|
|
68721
|
-
|
|
68722
|
-
|
|
68723
|
-
|
|
68947
|
+
const workspaceCycleTimeEligibility = workspace ? {
|
|
68948
|
+
line_assembly_enabled: workspace.line_assembly_enabled,
|
|
68949
|
+
action_family: workspace.action_family,
|
|
68950
|
+
action_type: workspace.action_type
|
|
68951
|
+
} : null;
|
|
68952
|
+
const isAssemblyWorkspace = shouldUseAssemblyCycleTimeLayout(workspaceCycleTimeEligibility);
|
|
68953
|
+
const cycleTimePresentation = getWorkspaceCycleTimePresentation({
|
|
68954
|
+
workspace: workspace ? {
|
|
68955
|
+
monitoring_mode: workspace.monitoring_mode,
|
|
68956
|
+
line_assembly_enabled: workspace.line_assembly_enabled,
|
|
68957
|
+
action_family: workspace.action_family,
|
|
68958
|
+
action_type: workspace.action_type,
|
|
68959
|
+
cycle_time_data_status: workspace.cycle_time_data_status
|
|
68960
|
+
} : null,
|
|
68961
|
+
showCycleTimeChart
|
|
68962
|
+
});
|
|
68963
|
+
const shouldShowCycleTimeChart = cycleTimePresentation !== "output";
|
|
68964
|
+
const shouldShowCycleTimeUnavailableState = cycleTimePresentation === "cycle_unavailable";
|
|
68724
68965
|
const showIdleBreakdownChart = !shouldShowCycleTimeChart && idleTimeVlmEnabled;
|
|
68725
68966
|
const idleClipDate = date || workspace?.date || calculatedOperationalDate || getOperationalDate(timezone);
|
|
68726
68967
|
const idleClipShiftId = parsedShiftId ?? workspace?.shift_id;
|
|
68727
|
-
const
|
|
68968
|
+
const rawHourlyIdleMinutes = React141.useMemo(() => {
|
|
68728
68969
|
if (!shouldShowCycleTimeChart || !workspace?.idle_time_hourly || !workspace?.shift_start) return [];
|
|
68729
68970
|
const parseTimeToMinutes3 = (time2) => {
|
|
68730
68971
|
const [h, m] = time2.split(":").map(Number);
|
|
@@ -68758,6 +68999,30 @@ var WorkspaceDetailView = ({
|
|
|
68758
68999
|
}
|
|
68759
69000
|
return result;
|
|
68760
69001
|
}, [shouldShowCycleTimeChart, workspace?.idle_time_hourly, workspace?.shift_start, workspace?.shift_end]);
|
|
69002
|
+
const hourlyIdleMinutes = React141.useMemo(
|
|
69003
|
+
() => maskFutureHourlySeries({
|
|
69004
|
+
data: rawHourlyIdleMinutes,
|
|
69005
|
+
shiftStart: workspace?.shift_start,
|
|
69006
|
+
shiftEnd: workspace?.shift_end,
|
|
69007
|
+
shiftDate: idleClipDate,
|
|
69008
|
+
timezone: effectiveCycleTimeTimezone
|
|
69009
|
+
}),
|
|
69010
|
+
[
|
|
69011
|
+
rawHourlyIdleMinutes,
|
|
69012
|
+
workspace?.shift_start,
|
|
69013
|
+
workspace?.shift_end,
|
|
69014
|
+
idleClipDate,
|
|
69015
|
+
effectiveCycleTimeTimezone
|
|
69016
|
+
]
|
|
69017
|
+
);
|
|
69018
|
+
const cycleTimeUnavailableView = React141.useMemo(() => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full h-full rounded-lg border border-amber-200 bg-amber-50/70 px-6 py-5 text-center flex flex-col items-center justify-center", children: [
|
|
69019
|
+
/* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-base font-semibold text-amber-900", children: "Cycle data unavailable" }),
|
|
69020
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 max-w-md text-sm text-amber-800", children: "This workstation has cycle-time metrics for the selected shift, but no matching `cycle_completion` clips were found for the chart." }),
|
|
69021
|
+
typeof workspace?.cycle_completion_clip_count === "number" && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-3 text-xs font-medium uppercase tracking-[0.08em] text-amber-700", children: [
|
|
69022
|
+
"matched cycle clips: ",
|
|
69023
|
+
workspace.cycle_completion_clip_count
|
|
69024
|
+
] })
|
|
69025
|
+
] }), [workspace?.cycle_completion_clip_count]);
|
|
68761
69026
|
const shiftDurationMinutes = React141.useMemo(
|
|
68762
69027
|
() => getShiftDurationMinutes(workspace?.shift_start, workspace?.shift_end),
|
|
68763
69028
|
[workspace?.shift_start, workspace?.shift_end]
|
|
@@ -69254,7 +69519,7 @@ var WorkspaceDetailView = ({
|
|
|
69254
69519
|
children: [
|
|
69255
69520
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-4", children: [
|
|
69256
69521
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700", children: isUptimeMode ? "Machine Utilization" : shouldShowCycleTimeChart ? "Cycle time trend" : "Hourly Output" }),
|
|
69257
|
-
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
69522
|
+
!isUptimeMode && !shouldShowCycleTimeUnavailableState && /* @__PURE__ */ jsxRuntime.jsx(
|
|
69258
69523
|
"button",
|
|
69259
69524
|
{
|
|
69260
69525
|
onClick: () => setShowChartIdleTime(!showChartIdleTime),
|
|
@@ -69283,10 +69548,10 @@ var WorkspaceDetailView = ({
|
|
|
69283
69548
|
timezone,
|
|
69284
69549
|
elapsedMinutes: elapsedShiftMinutes
|
|
69285
69550
|
}
|
|
69286
|
-
) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
69551
|
+
) : shouldShowCycleTimeUnavailableState ? cycleTimeUnavailableView : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
69287
69552
|
CycleTimeOverTimeChart,
|
|
69288
69553
|
{
|
|
69289
|
-
data:
|
|
69554
|
+
data: maskedCycleTimeChartData,
|
|
69290
69555
|
idealCycleTime: workspace.ideal_cycle_time || 0,
|
|
69291
69556
|
shiftStart: workspace.shift_start || "",
|
|
69292
69557
|
shiftEnd: workspace.shift_end || "",
|
|
@@ -69387,7 +69652,7 @@ var WorkspaceDetailView = ({
|
|
|
69387
69652
|
children: [
|
|
69388
69653
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 mb-4 flex-none", children: [
|
|
69389
69654
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-bold text-gray-700", children: isUptimeMode ? "Machine Utilization" : shouldShowCycleTimeChart ? "Cycle time trend" : "Hourly Output" }),
|
|
69390
|
-
!isUptimeMode && /* @__PURE__ */ jsxRuntime.jsx(
|
|
69655
|
+
!isUptimeMode && !shouldShowCycleTimeUnavailableState && /* @__PURE__ */ jsxRuntime.jsx(
|
|
69391
69656
|
"button",
|
|
69392
69657
|
{
|
|
69393
69658
|
onClick: () => setShowChartIdleTime(!showChartIdleTime),
|
|
@@ -69412,10 +69677,10 @@ var WorkspaceDetailView = ({
|
|
|
69412
69677
|
timezone,
|
|
69413
69678
|
elapsedMinutes: elapsedShiftMinutes
|
|
69414
69679
|
}
|
|
69415
|
-
) : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
69680
|
+
) : shouldShowCycleTimeUnavailableState ? cycleTimeUnavailableView : shouldShowCycleTimeChart ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
69416
69681
|
CycleTimeOverTimeChart,
|
|
69417
69682
|
{
|
|
69418
|
-
data:
|
|
69683
|
+
data: maskedCycleTimeChartData,
|
|
69419
69684
|
idealCycleTime: workspace.ideal_cycle_time || 0,
|
|
69420
69685
|
shiftStart: workspace.shift_start || "",
|
|
69421
69686
|
shiftEnd: workspace.shift_end || "",
|