@optifye/dashboard-core 6.12.19 → 6.12.21
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.js +142 -57
- package/dist/index.mjs +142 -57
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -19916,6 +19916,9 @@ function useNavigation(customNavigate) {
|
|
|
19916
19916
|
await router$1.push(path, void 0, { shallow: options?.shallow ?? false });
|
|
19917
19917
|
}
|
|
19918
19918
|
} catch (error) {
|
|
19919
|
+
if (error?.cancelled || error?.message?.includes("Route change aborted")) {
|
|
19920
|
+
return;
|
|
19921
|
+
}
|
|
19919
19922
|
if (error.message?.includes("Page not compiled") && retryCount < MAX_RETRIES) {
|
|
19920
19923
|
setTimeout(() => attemptNavigation(retryCount + 1), RETRY_DELAY);
|
|
19921
19924
|
} else if (retryCount >= MAX_RETRIES) {
|
|
@@ -54907,27 +54910,34 @@ var WorkspaceGrid = React144__namespace.default.memo(({
|
|
|
54907
54910
|
[viewMode, workspaces]
|
|
54908
54911
|
);
|
|
54909
54912
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col w-full h-full overflow-hidden bg-slate-50/50 ${className}`, children: [
|
|
54910
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
54911
|
-
|
|
54912
|
-
|
|
54913
|
-
|
|
54914
|
-
|
|
54915
|
-
|
|
54916
|
-
{
|
|
54917
|
-
|
|
54918
|
-
|
|
54919
|
-
|
|
54920
|
-
|
|
54921
|
-
|
|
54922
|
-
|
|
54923
|
-
|
|
54924
|
-
|
|
54925
|
-
|
|
54926
|
-
|
|
54927
|
-
|
|
54928
|
-
|
|
54929
|
-
|
|
54930
|
-
|
|
54913
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
54914
|
+
"div",
|
|
54915
|
+
{
|
|
54916
|
+
"data-testid": "workspace-grid-toolbar",
|
|
54917
|
+
className: "relative z-[100] flex-none px-4 py-3 flex flex-row items-center justify-between gap-4",
|
|
54918
|
+
children: [
|
|
54919
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-flex bg-white/95 rounded-lg shadow-sm px-4 py-2 border border-slate-200/60 backdrop-blur-sm", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, metricLabel: legendMetricLabel }) }) }),
|
|
54920
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-3 shrink-0", children: [
|
|
54921
|
+
toolbarRightContent,
|
|
54922
|
+
mapViewEnabled && /* @__PURE__ */ jsxRuntime.jsx(
|
|
54923
|
+
"button",
|
|
54924
|
+
{
|
|
54925
|
+
onClick: handleViewModeToggle,
|
|
54926
|
+
className: "flex items-center gap-2 px-3 py-1.5 bg-white border border-slate-200 rounded-md shadow-sm hover:bg-slate-50 transition-colors duration-200 text-slate-700",
|
|
54927
|
+
title: viewMode === "video" ? "Switch to Map View" : "Switch to Video View",
|
|
54928
|
+
children: viewMode === "video" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
54929
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Map, { className: "w-4 h-4 text-slate-500" }),
|
|
54930
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Map View" })
|
|
54931
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
54932
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Video, { className: "w-4 h-4 text-slate-500" }),
|
|
54933
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Video View" })
|
|
54934
|
+
] })
|
|
54935
|
+
}
|
|
54936
|
+
)
|
|
54937
|
+
] })
|
|
54938
|
+
]
|
|
54939
|
+
}
|
|
54940
|
+
),
|
|
54931
54941
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "sm:hidden px-3 py-2 bg-white border-b border-slate-200/60 z-10", children: /* @__PURE__ */ jsxRuntime.jsx(Legend5, { legend, metricLabel: legendMetricLabel }) }),
|
|
54932
54942
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 relative overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(AnimatePresence, { mode: "wait", children: viewMode === "video" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
54933
54943
|
motion.div,
|
|
@@ -72340,6 +72350,46 @@ var ClipsCostView = () => {
|
|
|
72340
72350
|
] });
|
|
72341
72351
|
};
|
|
72342
72352
|
var ClipsCostView_default = ClipsCostView;
|
|
72353
|
+
var DEFAULT_UNSAVED_CHANGES_MESSAGE = "You have unsaved changes. Leave this page and lose them?";
|
|
72354
|
+
var useUnsavedChangesPrompt = (shouldBlock, message = DEFAULT_UNSAVED_CHANGES_MESSAGE) => {
|
|
72355
|
+
const router$1 = router.useRouter();
|
|
72356
|
+
React144.useEffect(() => {
|
|
72357
|
+
if (!shouldBlock || typeof window === "undefined") {
|
|
72358
|
+
return;
|
|
72359
|
+
}
|
|
72360
|
+
const handleBeforeUnload = (event) => {
|
|
72361
|
+
event.preventDefault();
|
|
72362
|
+
event.returnValue = message;
|
|
72363
|
+
return message;
|
|
72364
|
+
};
|
|
72365
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
72366
|
+
return () => {
|
|
72367
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
72368
|
+
};
|
|
72369
|
+
}, [message, shouldBlock]);
|
|
72370
|
+
React144.useEffect(() => {
|
|
72371
|
+
if (!shouldBlock || !router$1?.events || typeof window === "undefined") {
|
|
72372
|
+
return;
|
|
72373
|
+
}
|
|
72374
|
+
const handleRouteChangeStart = (url) => {
|
|
72375
|
+
const currentUrl = router$1.asPath || window.location.pathname;
|
|
72376
|
+
if (url === currentUrl) {
|
|
72377
|
+
return;
|
|
72378
|
+
}
|
|
72379
|
+
if (window.confirm(message)) {
|
|
72380
|
+
return;
|
|
72381
|
+
}
|
|
72382
|
+
const routeChangeError = new Error("Route change aborted due to unsaved changes");
|
|
72383
|
+
routeChangeError.cancelled = true;
|
|
72384
|
+
router$1.events.emit("routeChangeError", routeChangeError, url, { shallow: false });
|
|
72385
|
+
throw routeChangeError;
|
|
72386
|
+
};
|
|
72387
|
+
router$1.events.on("routeChangeStart", handleRouteChangeStart);
|
|
72388
|
+
return () => {
|
|
72389
|
+
router$1.events.off("routeChangeStart", handleRouteChangeStart);
|
|
72390
|
+
};
|
|
72391
|
+
}, [message, router$1, shouldBlock]);
|
|
72392
|
+
};
|
|
72343
72393
|
var calculateShiftHours = (startTime, endTime, breaks = []) => {
|
|
72344
72394
|
if (!startTime || !endTime) return 8;
|
|
72345
72395
|
const [startHour, startMinute] = startTime.split(":").map(Number);
|
|
@@ -72669,6 +72719,11 @@ var ShiftsView = ({
|
|
|
72669
72719
|
className = ""
|
|
72670
72720
|
}) => {
|
|
72671
72721
|
const supabase = useSupabase();
|
|
72722
|
+
const lineIdsKey = React144.useMemo(() => lineIds.join("|"), [lineIds]);
|
|
72723
|
+
const stableLineIds = React144.useMemo(
|
|
72724
|
+
() => lineIdsKey.split("|").filter(Boolean),
|
|
72725
|
+
[lineIdsKey]
|
|
72726
|
+
);
|
|
72672
72727
|
const { lines: dbLines } = useLines();
|
|
72673
72728
|
const mergedLineNames = React144.useMemo(() => {
|
|
72674
72729
|
const merged = { ...lineNames };
|
|
@@ -72682,14 +72737,14 @@ var ShiftsView = ({
|
|
|
72682
72737
|
React144.useEffect(() => {
|
|
72683
72738
|
console.log("[ShiftsView] Component mounted/re-rendered", {
|
|
72684
72739
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
72685
|
-
lineIds:
|
|
72740
|
+
lineIds: stableLineIds.length
|
|
72686
72741
|
});
|
|
72687
72742
|
return () => {
|
|
72688
72743
|
console.log("[ShiftsView] Component unmounting");
|
|
72689
72744
|
};
|
|
72690
|
-
}, []);
|
|
72745
|
+
}, [stableLineIds.length]);
|
|
72691
72746
|
const [lineConfigs, setLineConfigs] = React144.useState(
|
|
72692
|
-
() =>
|
|
72747
|
+
() => stableLineIds.map((id3) => ({
|
|
72693
72748
|
id: id3,
|
|
72694
72749
|
name: lineNames[id3] || `Line ${id3.substring(0, 4)}`,
|
|
72695
72750
|
timezone: "Asia/Kolkata",
|
|
@@ -72703,8 +72758,18 @@ var ShiftsView = ({
|
|
|
72703
72758
|
const [loading, setLoading] = React144.useState(true);
|
|
72704
72759
|
const [error, setError] = React144.useState(null);
|
|
72705
72760
|
const [saveStatusMessages, setSaveStatusMessages] = React144.useState(
|
|
72706
|
-
() =>
|
|
72761
|
+
() => stableLineIds.reduce((acc, id3) => ({ ...acc, [id3]: null }), {})
|
|
72707
72762
|
);
|
|
72763
|
+
const [dirtyLineIds, setDirtyLineIds] = React144.useState(/* @__PURE__ */ new Set());
|
|
72764
|
+
useUnsavedChangesPrompt(dirtyLineIds.size > 0);
|
|
72765
|
+
const markLineDirty = React144.useCallback((lineId) => {
|
|
72766
|
+
setDirtyLineIds((prev) => {
|
|
72767
|
+
if (prev.has(lineId)) return prev;
|
|
72768
|
+
const next = new Set(prev);
|
|
72769
|
+
next.add(lineId);
|
|
72770
|
+
return next;
|
|
72771
|
+
});
|
|
72772
|
+
}, []);
|
|
72708
72773
|
const showToast = React144.useCallback((type, message) => {
|
|
72709
72774
|
if (onToast) {
|
|
72710
72775
|
try {
|
|
@@ -72724,7 +72789,7 @@ var ShiftsView = ({
|
|
|
72724
72789
|
try {
|
|
72725
72790
|
setLoading(true);
|
|
72726
72791
|
setError(null);
|
|
72727
|
-
const { data: enabledLines, error: linesError } = await supabase.from("lines").select("id, enable").in("id",
|
|
72792
|
+
const { data: enabledLines, error: linesError } = await supabase.from("lines").select("id, enable").in("id", stableLineIds).eq("enable", true);
|
|
72728
72793
|
if (linesError) {
|
|
72729
72794
|
console.error("Error fetching enabled lines:", linesError);
|
|
72730
72795
|
showToast("error", "Error loading lines");
|
|
@@ -72756,18 +72821,21 @@ var ShiftsView = ({
|
|
|
72756
72821
|
return acc;
|
|
72757
72822
|
}, {});
|
|
72758
72823
|
setLineConfigs((prev) => {
|
|
72759
|
-
const
|
|
72760
|
-
return
|
|
72761
|
-
const
|
|
72824
|
+
const previousByLineId = new Map(prev.map((config) => [config.id, config]));
|
|
72825
|
+
return enabledLineIds.map((lineId) => {
|
|
72826
|
+
const existingConfig = previousByLineId.get(lineId);
|
|
72827
|
+
const rows = shiftsByLine[lineId] || [];
|
|
72762
72828
|
const builtConfig = buildShiftConfigFromOperatingHoursRows(rows);
|
|
72763
|
-
const lineName = lineNameMap[
|
|
72829
|
+
const lineName = lineNameMap[lineId] || mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}`;
|
|
72764
72830
|
const sortedShifts = [...builtConfig.shifts || []].sort((a, b) => a.shiftId - b.shiftId);
|
|
72765
72831
|
return {
|
|
72766
|
-
|
|
72832
|
+
id: lineId,
|
|
72767
72833
|
name: lineName,
|
|
72834
|
+
timezone: builtConfig.timezone || existingConfig?.timezone || "Asia/Kolkata",
|
|
72768
72835
|
shifts: sortedShifts,
|
|
72769
|
-
|
|
72770
|
-
|
|
72836
|
+
isSaving: existingConfig?.isSaving ?? false,
|
|
72837
|
+
saveSuccess: existingConfig?.saveSuccess ?? false,
|
|
72838
|
+
isOpen: existingConfig?.isOpen ?? getStoredLineState(lineId)
|
|
72771
72839
|
};
|
|
72772
72840
|
});
|
|
72773
72841
|
});
|
|
@@ -72780,7 +72848,7 @@ var ShiftsView = ({
|
|
|
72780
72848
|
}
|
|
72781
72849
|
};
|
|
72782
72850
|
fetchShiftConfigs();
|
|
72783
|
-
}, [
|
|
72851
|
+
}, [stableLineIds, showToast]);
|
|
72784
72852
|
React144.useCallback((lineId) => {
|
|
72785
72853
|
setLineConfigs((prev) => {
|
|
72786
72854
|
const typedPrev = prev;
|
|
@@ -72792,6 +72860,7 @@ var ShiftsView = ({
|
|
|
72792
72860
|
});
|
|
72793
72861
|
}, []);
|
|
72794
72862
|
const updateShiftTime = React144.useCallback((lineId, shiftIndex, field, value) => {
|
|
72863
|
+
markLineDirty(lineId);
|
|
72795
72864
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72796
72865
|
if (config.id === lineId && config.shifts) {
|
|
72797
72866
|
const newShifts = [...config.shifts];
|
|
@@ -72802,8 +72871,9 @@ var ShiftsView = ({
|
|
|
72802
72871
|
}
|
|
72803
72872
|
return config;
|
|
72804
72873
|
}));
|
|
72805
|
-
}, []);
|
|
72874
|
+
}, [markLineDirty]);
|
|
72806
72875
|
const addShiftBreak = React144.useCallback((lineId, shiftIndex) => {
|
|
72876
|
+
markLineDirty(lineId);
|
|
72807
72877
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72808
72878
|
if (config.id === lineId && config.shifts) {
|
|
72809
72879
|
const newShifts = [...config.shifts];
|
|
@@ -72824,8 +72894,9 @@ var ShiftsView = ({
|
|
|
72824
72894
|
}
|
|
72825
72895
|
return config;
|
|
72826
72896
|
}));
|
|
72827
|
-
}, []);
|
|
72897
|
+
}, [markLineDirty]);
|
|
72828
72898
|
const updateShiftBreak = React144.useCallback((lineId, shiftIndex, breakIndex, field, value) => {
|
|
72899
|
+
markLineDirty(lineId);
|
|
72829
72900
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72830
72901
|
if (config.id === lineId && config.shifts) {
|
|
72831
72902
|
const newShifts = [...config.shifts];
|
|
@@ -72851,8 +72922,9 @@ var ShiftsView = ({
|
|
|
72851
72922
|
}
|
|
72852
72923
|
return config;
|
|
72853
72924
|
}));
|
|
72854
|
-
}, []);
|
|
72925
|
+
}, [markLineDirty]);
|
|
72855
72926
|
const removeShiftBreak = React144.useCallback((lineId, shiftIndex, breakIndex) => {
|
|
72927
|
+
markLineDirty(lineId);
|
|
72856
72928
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72857
72929
|
if (config.id === lineId && config.shifts) {
|
|
72858
72930
|
const newShifts = [...config.shifts];
|
|
@@ -72867,7 +72939,7 @@ var ShiftsView = ({
|
|
|
72867
72939
|
}
|
|
72868
72940
|
return config;
|
|
72869
72941
|
}));
|
|
72870
|
-
}, []);
|
|
72942
|
+
}, [markLineDirty]);
|
|
72871
72943
|
const getOperationalDateForLine = React144.useCallback((lineConfig) => {
|
|
72872
72944
|
const sortedShifts = [...lineConfig.shifts || []].sort((a, b) => a.shiftId - b.shiftId);
|
|
72873
72945
|
const dayBoundaryStart = sortedShifts[0]?.startTime || "06:00";
|
|
@@ -73152,6 +73224,11 @@ var ShiftsView = ({
|
|
|
73152
73224
|
setLineConfigs((prev) => prev.map(
|
|
73153
73225
|
(config) => config.id === lineId ? { ...config, isSaving: false, saveSuccess: true } : config
|
|
73154
73226
|
));
|
|
73227
|
+
setDirtyLineIds((prev) => {
|
|
73228
|
+
const next = new Set(prev);
|
|
73229
|
+
next.delete(lineId);
|
|
73230
|
+
return next;
|
|
73231
|
+
});
|
|
73155
73232
|
let successMessage = "Shift configurations saved successfully.";
|
|
73156
73233
|
if (changedShiftCount > 0 && recalculatedTargetsCount > 0) {
|
|
73157
73234
|
successMessage = `Shift configurations saved. Targets updated successfully for ${recalculatedTargetsCount} workspace${recalculatedTargetsCount === 1 ? "" : "s"}.`;
|
|
@@ -74236,8 +74313,13 @@ var TargetsView = ({
|
|
|
74236
74313
|
onSaveChanges
|
|
74237
74314
|
}) => {
|
|
74238
74315
|
const timezone = useAppTimezone();
|
|
74316
|
+
const lineIdsKey = React144.useMemo(() => lineIds.join("|"), [lineIds]);
|
|
74317
|
+
const stableLineIds = React144.useMemo(
|
|
74318
|
+
() => lineIdsKey.split("|").filter(Boolean),
|
|
74319
|
+
[lineIdsKey]
|
|
74320
|
+
);
|
|
74239
74321
|
React144.useMemo(() => {
|
|
74240
|
-
return
|
|
74322
|
+
return stableLineIds.reduce((acc, lineId) => ({
|
|
74241
74323
|
...acc,
|
|
74242
74324
|
[lineId]: {
|
|
74243
74325
|
productId: "",
|
|
@@ -74251,9 +74333,9 @@ var TargetsView = ({
|
|
|
74251
74333
|
// Initialize factoryId
|
|
74252
74334
|
}
|
|
74253
74335
|
}), {});
|
|
74254
|
-
}, [
|
|
74336
|
+
}, [stableLineIds]);
|
|
74255
74337
|
const [dropdownStates, setDropdownStates] = React144.useState(() => {
|
|
74256
|
-
return
|
|
74338
|
+
return stableLineIds.reduce((acc, lineId) => ({
|
|
74257
74339
|
...acc,
|
|
74258
74340
|
[lineId]: getStoredLineState2(lineId)
|
|
74259
74341
|
}), {});
|
|
@@ -74261,10 +74343,10 @@ var TargetsView = ({
|
|
|
74261
74343
|
const [allShiftsData, setAllShiftsData] = React144.useState({});
|
|
74262
74344
|
const [actionIds, setActionIds] = React144.useState(null);
|
|
74263
74345
|
const [savingLines, setSavingLines] = React144.useState(
|
|
74264
|
-
() =>
|
|
74346
|
+
() => stableLineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
|
|
74265
74347
|
);
|
|
74266
74348
|
const [saveSuccess, setSaveSuccess] = React144.useState(
|
|
74267
|
-
() =>
|
|
74349
|
+
() => stableLineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
|
|
74268
74350
|
);
|
|
74269
74351
|
const [isLoading, setIsLoading] = React144.useState(true);
|
|
74270
74352
|
const [isConfigureLegendOpen, setIsConfigureLegendOpen] = React144.useState(false);
|
|
@@ -74274,6 +74356,8 @@ var TargetsView = ({
|
|
|
74274
74356
|
const canSaveTargets = useCanSaveTargets();
|
|
74275
74357
|
const [dbValues, setDbValues] = React144.useState({ 0: {}, 1: {} });
|
|
74276
74358
|
const [userEditedFields, setUserEditedFields] = React144.useState(/* @__PURE__ */ new Set());
|
|
74359
|
+
const hasUnsavedChanges = userEditedFields.size > 0;
|
|
74360
|
+
useUnsavedChangesPrompt(hasUnsavedChanges);
|
|
74277
74361
|
const lineWorkspaces = allShiftsData[selectedShift] || {};
|
|
74278
74362
|
const setLineWorkspaces = React144.useCallback((updater) => {
|
|
74279
74363
|
setAllShiftsData((prev) => ({
|
|
@@ -74290,13 +74374,13 @@ var TargetsView = ({
|
|
|
74290
74374
|
dbLines.forEach((line) => {
|
|
74291
74375
|
merged[line.id] = line.line_name;
|
|
74292
74376
|
});
|
|
74293
|
-
|
|
74377
|
+
stableLineIds.forEach((lineId) => {
|
|
74294
74378
|
if (!merged[lineId]) {
|
|
74295
74379
|
merged[lineId] = `Line ${lineId.substring(0, 4)}`;
|
|
74296
74380
|
}
|
|
74297
74381
|
});
|
|
74298
74382
|
return merged;
|
|
74299
|
-
}, [lineNames, dbLines,
|
|
74383
|
+
}, [lineNames, dbLines, stableLineIds]);
|
|
74300
74384
|
const { legend, updateLegend } = useEfficiencyLegend(companyId);
|
|
74301
74385
|
const { skus, isLoading: skusLoading } = useSKUs(companyId);
|
|
74302
74386
|
const { skus: skuCatalog, isLoading: skuCatalogLoading } = useSKUs(companyId, {
|
|
@@ -74355,22 +74439,22 @@ var TargetsView = ({
|
|
|
74355
74439
|
React144.useEffect(() => {
|
|
74356
74440
|
console.log("[TargetsView] Component mounted/re-rendered", {
|
|
74357
74441
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
74358
|
-
lineIds:
|
|
74442
|
+
lineIds: stableLineIds.length,
|
|
74359
74443
|
effectiveUserId
|
|
74360
74444
|
});
|
|
74361
74445
|
return () => {
|
|
74362
74446
|
console.log("[TargetsView] Component unmounting");
|
|
74363
74447
|
};
|
|
74364
|
-
}, []);
|
|
74448
|
+
}, [effectiveUserId, stableLineIds.length]);
|
|
74365
74449
|
React144.useEffect(() => {
|
|
74366
74450
|
const fetchInitialData = async () => {
|
|
74367
|
-
if (
|
|
74451
|
+
if (stableLineIds.length === 0 || !companyId) return;
|
|
74368
74452
|
if (skuCatalogLoading) return;
|
|
74369
74453
|
console.log("[TargetsView] Starting optimized fetchInitialData with bulk endpoint");
|
|
74370
74454
|
setIsLoading(true);
|
|
74371
74455
|
try {
|
|
74372
74456
|
const currentDate = getOperationalDate(timezone);
|
|
74373
|
-
const { data: shiftsData, error: shiftsError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name").in("line_id",
|
|
74457
|
+
const { data: shiftsData, error: shiftsError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name").in("line_id", stableLineIds);
|
|
74374
74458
|
if (shiftsError) {
|
|
74375
74459
|
console.warn("[TargetsView] Error fetching shift definitions, falling back to defaults", shiftsError);
|
|
74376
74460
|
}
|
|
@@ -74388,7 +74472,7 @@ var TargetsView = ({
|
|
|
74388
74472
|
setSelectedShift(defaultShiftId);
|
|
74389
74473
|
const bulkResponse = await workspaceService.fetchBulkTargets({
|
|
74390
74474
|
companyId,
|
|
74391
|
-
lineIds,
|
|
74475
|
+
lineIds: stableLineIds,
|
|
74392
74476
|
date: currentDate,
|
|
74393
74477
|
shifts: effectiveShiftOptions.map((s) => s.id),
|
|
74394
74478
|
// Fetch all configured shifts
|
|
@@ -74533,7 +74617,7 @@ var TargetsView = ({
|
|
|
74533
74617
|
});
|
|
74534
74618
|
});
|
|
74535
74619
|
effectiveShiftOptions.forEach(({ id: shiftId }) => {
|
|
74536
|
-
|
|
74620
|
+
stableLineIds.forEach((lineId) => {
|
|
74537
74621
|
if (!newAllShiftsData[shiftId][lineId]) {
|
|
74538
74622
|
const lineData = data.lines[lineId];
|
|
74539
74623
|
const shift0Data = newAllShiftsData[0]?.[lineId];
|
|
@@ -74603,7 +74687,7 @@ var TargetsView = ({
|
|
|
74603
74687
|
});
|
|
74604
74688
|
effectiveShiftOptions.forEach(({ id: shiftId }) => {
|
|
74605
74689
|
const orderedLineWorkspaces = {};
|
|
74606
|
-
|
|
74690
|
+
stableLineIds.forEach((lineId) => {
|
|
74607
74691
|
if (newAllShiftsData[shiftId][lineId]) {
|
|
74608
74692
|
orderedLineWorkspaces[lineId] = newAllShiftsData[shiftId][lineId];
|
|
74609
74693
|
}
|
|
@@ -74625,7 +74709,7 @@ var TargetsView = ({
|
|
|
74625
74709
|
}
|
|
74626
74710
|
};
|
|
74627
74711
|
fetchInitialData();
|
|
74628
|
-
}, [
|
|
74712
|
+
}, [stableLineIds, companyId, timezone, skuEnabled, skuCatalogLoading]);
|
|
74629
74713
|
const toggleLineDropdown = React144.useCallback((lineId) => {
|
|
74630
74714
|
setDropdownStates((prev) => {
|
|
74631
74715
|
const newIsOpen = !prev[lineId];
|
|
@@ -74800,6 +74884,7 @@ var TargetsView = ({
|
|
|
74800
74884
|
};
|
|
74801
74885
|
const handleActionTypeChange = React144.useCallback((lineId, workspaceId, newActionType) => {
|
|
74802
74886
|
if (!actionIds) return;
|
|
74887
|
+
setUserEditedFields((prev) => new Set(prev).add(`${lineId}-${workspaceId}-actionType`));
|
|
74803
74888
|
setLineWorkspaces((prev) => {
|
|
74804
74889
|
const currentLineData = prev?.[lineId];
|
|
74805
74890
|
if (!currentLineData?.workspaces) {
|
|
@@ -74997,10 +75082,10 @@ var TargetsView = ({
|
|
|
74997
75082
|
console.log(`[handleSaveLine] Updated dbValues for line ${lineId}, shift ${selectedShift}`);
|
|
74998
75083
|
setUserEditedFields((prev) => {
|
|
74999
75084
|
const newSet = new Set(prev);
|
|
75000
|
-
|
|
75001
|
-
|
|
75002
|
-
|
|
75003
|
-
|
|
75085
|
+
Array.from(newSet).forEach((fieldKey) => {
|
|
75086
|
+
if (fieldKey.startsWith(`${lineId}-`)) {
|
|
75087
|
+
newSet.delete(fieldKey);
|
|
75088
|
+
}
|
|
75004
75089
|
});
|
|
75005
75090
|
return newSet;
|
|
75006
75091
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -19887,6 +19887,9 @@ function useNavigation(customNavigate) {
|
|
|
19887
19887
|
await router.push(path, void 0, { shallow: options?.shallow ?? false });
|
|
19888
19888
|
}
|
|
19889
19889
|
} catch (error) {
|
|
19890
|
+
if (error?.cancelled || error?.message?.includes("Route change aborted")) {
|
|
19891
|
+
return;
|
|
19892
|
+
}
|
|
19890
19893
|
if (error.message?.includes("Page not compiled") && retryCount < MAX_RETRIES) {
|
|
19891
19894
|
setTimeout(() => attemptNavigation(retryCount + 1), RETRY_DELAY);
|
|
19892
19895
|
} else if (retryCount >= MAX_RETRIES) {
|
|
@@ -54878,27 +54881,34 @@ var WorkspaceGrid = React144__default.memo(({
|
|
|
54878
54881
|
[viewMode, workspaces]
|
|
54879
54882
|
);
|
|
54880
54883
|
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col w-full h-full overflow-hidden bg-slate-50/50 ${className}`, children: [
|
|
54881
|
-
/* @__PURE__ */ jsxs(
|
|
54882
|
-
|
|
54883
|
-
|
|
54884
|
-
|
|
54885
|
-
|
|
54886
|
-
|
|
54887
|
-
{
|
|
54888
|
-
|
|
54889
|
-
|
|
54890
|
-
|
|
54891
|
-
|
|
54892
|
-
|
|
54893
|
-
|
|
54894
|
-
|
|
54895
|
-
|
|
54896
|
-
|
|
54897
|
-
|
|
54898
|
-
|
|
54899
|
-
|
|
54900
|
-
|
|
54901
|
-
|
|
54884
|
+
/* @__PURE__ */ jsxs(
|
|
54885
|
+
"div",
|
|
54886
|
+
{
|
|
54887
|
+
"data-testid": "workspace-grid-toolbar",
|
|
54888
|
+
className: "relative z-[100] flex-none px-4 py-3 flex flex-row items-center justify-between gap-4",
|
|
54889
|
+
children: [
|
|
54890
|
+
/* @__PURE__ */ jsx("div", { className: "hidden sm:block", children: /* @__PURE__ */ jsx("div", { className: "inline-flex bg-white/95 rounded-lg shadow-sm px-4 py-2 border border-slate-200/60 backdrop-blur-sm", children: /* @__PURE__ */ jsx(Legend5, { legend, metricLabel: legendMetricLabel }) }) }),
|
|
54891
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-3 shrink-0", children: [
|
|
54892
|
+
toolbarRightContent,
|
|
54893
|
+
mapViewEnabled && /* @__PURE__ */ jsx(
|
|
54894
|
+
"button",
|
|
54895
|
+
{
|
|
54896
|
+
onClick: handleViewModeToggle,
|
|
54897
|
+
className: "flex items-center gap-2 px-3 py-1.5 bg-white border border-slate-200 rounded-md shadow-sm hover:bg-slate-50 transition-colors duration-200 text-slate-700",
|
|
54898
|
+
title: viewMode === "video" ? "Switch to Map View" : "Switch to Video View",
|
|
54899
|
+
children: viewMode === "video" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
54900
|
+
/* @__PURE__ */ jsx(Map$1, { className: "w-4 h-4 text-slate-500" }),
|
|
54901
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Map View" })
|
|
54902
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
54903
|
+
/* @__PURE__ */ jsx(Video, { className: "w-4 h-4 text-slate-500" }),
|
|
54904
|
+
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline text-sm font-medium", children: "Video View" })
|
|
54905
|
+
] })
|
|
54906
|
+
}
|
|
54907
|
+
)
|
|
54908
|
+
] })
|
|
54909
|
+
]
|
|
54910
|
+
}
|
|
54911
|
+
),
|
|
54902
54912
|
/* @__PURE__ */ jsx("div", { className: "sm:hidden px-3 py-2 bg-white border-b border-slate-200/60 z-10", children: /* @__PURE__ */ jsx(Legend5, { legend, metricLabel: legendMetricLabel }) }),
|
|
54903
54913
|
/* @__PURE__ */ jsx("div", { className: "flex-1 relative overflow-hidden", children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: viewMode === "video" ? /* @__PURE__ */ jsx(
|
|
54904
54914
|
motion.div,
|
|
@@ -72311,6 +72321,46 @@ var ClipsCostView = () => {
|
|
|
72311
72321
|
] });
|
|
72312
72322
|
};
|
|
72313
72323
|
var ClipsCostView_default = ClipsCostView;
|
|
72324
|
+
var DEFAULT_UNSAVED_CHANGES_MESSAGE = "You have unsaved changes. Leave this page and lose them?";
|
|
72325
|
+
var useUnsavedChangesPrompt = (shouldBlock, message = DEFAULT_UNSAVED_CHANGES_MESSAGE) => {
|
|
72326
|
+
const router = useRouter();
|
|
72327
|
+
useEffect(() => {
|
|
72328
|
+
if (!shouldBlock || typeof window === "undefined") {
|
|
72329
|
+
return;
|
|
72330
|
+
}
|
|
72331
|
+
const handleBeforeUnload = (event) => {
|
|
72332
|
+
event.preventDefault();
|
|
72333
|
+
event.returnValue = message;
|
|
72334
|
+
return message;
|
|
72335
|
+
};
|
|
72336
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
72337
|
+
return () => {
|
|
72338
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
72339
|
+
};
|
|
72340
|
+
}, [message, shouldBlock]);
|
|
72341
|
+
useEffect(() => {
|
|
72342
|
+
if (!shouldBlock || !router?.events || typeof window === "undefined") {
|
|
72343
|
+
return;
|
|
72344
|
+
}
|
|
72345
|
+
const handleRouteChangeStart = (url) => {
|
|
72346
|
+
const currentUrl = router.asPath || window.location.pathname;
|
|
72347
|
+
if (url === currentUrl) {
|
|
72348
|
+
return;
|
|
72349
|
+
}
|
|
72350
|
+
if (window.confirm(message)) {
|
|
72351
|
+
return;
|
|
72352
|
+
}
|
|
72353
|
+
const routeChangeError = new Error("Route change aborted due to unsaved changes");
|
|
72354
|
+
routeChangeError.cancelled = true;
|
|
72355
|
+
router.events.emit("routeChangeError", routeChangeError, url, { shallow: false });
|
|
72356
|
+
throw routeChangeError;
|
|
72357
|
+
};
|
|
72358
|
+
router.events.on("routeChangeStart", handleRouteChangeStart);
|
|
72359
|
+
return () => {
|
|
72360
|
+
router.events.off("routeChangeStart", handleRouteChangeStart);
|
|
72361
|
+
};
|
|
72362
|
+
}, [message, router, shouldBlock]);
|
|
72363
|
+
};
|
|
72314
72364
|
var calculateShiftHours = (startTime, endTime, breaks = []) => {
|
|
72315
72365
|
if (!startTime || !endTime) return 8;
|
|
72316
72366
|
const [startHour, startMinute] = startTime.split(":").map(Number);
|
|
@@ -72640,6 +72690,11 @@ var ShiftsView = ({
|
|
|
72640
72690
|
className = ""
|
|
72641
72691
|
}) => {
|
|
72642
72692
|
const supabase = useSupabase();
|
|
72693
|
+
const lineIdsKey = useMemo(() => lineIds.join("|"), [lineIds]);
|
|
72694
|
+
const stableLineIds = useMemo(
|
|
72695
|
+
() => lineIdsKey.split("|").filter(Boolean),
|
|
72696
|
+
[lineIdsKey]
|
|
72697
|
+
);
|
|
72643
72698
|
const { lines: dbLines } = useLines();
|
|
72644
72699
|
const mergedLineNames = useMemo(() => {
|
|
72645
72700
|
const merged = { ...lineNames };
|
|
@@ -72653,14 +72708,14 @@ var ShiftsView = ({
|
|
|
72653
72708
|
useEffect(() => {
|
|
72654
72709
|
console.log("[ShiftsView] Component mounted/re-rendered", {
|
|
72655
72710
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
72656
|
-
lineIds:
|
|
72711
|
+
lineIds: stableLineIds.length
|
|
72657
72712
|
});
|
|
72658
72713
|
return () => {
|
|
72659
72714
|
console.log("[ShiftsView] Component unmounting");
|
|
72660
72715
|
};
|
|
72661
|
-
}, []);
|
|
72716
|
+
}, [stableLineIds.length]);
|
|
72662
72717
|
const [lineConfigs, setLineConfigs] = useState(
|
|
72663
|
-
() =>
|
|
72718
|
+
() => stableLineIds.map((id3) => ({
|
|
72664
72719
|
id: id3,
|
|
72665
72720
|
name: lineNames[id3] || `Line ${id3.substring(0, 4)}`,
|
|
72666
72721
|
timezone: "Asia/Kolkata",
|
|
@@ -72674,8 +72729,18 @@ var ShiftsView = ({
|
|
|
72674
72729
|
const [loading, setLoading] = useState(true);
|
|
72675
72730
|
const [error, setError] = useState(null);
|
|
72676
72731
|
const [saveStatusMessages, setSaveStatusMessages] = useState(
|
|
72677
|
-
() =>
|
|
72732
|
+
() => stableLineIds.reduce((acc, id3) => ({ ...acc, [id3]: null }), {})
|
|
72678
72733
|
);
|
|
72734
|
+
const [dirtyLineIds, setDirtyLineIds] = useState(/* @__PURE__ */ new Set());
|
|
72735
|
+
useUnsavedChangesPrompt(dirtyLineIds.size > 0);
|
|
72736
|
+
const markLineDirty = useCallback((lineId) => {
|
|
72737
|
+
setDirtyLineIds((prev) => {
|
|
72738
|
+
if (prev.has(lineId)) return prev;
|
|
72739
|
+
const next = new Set(prev);
|
|
72740
|
+
next.add(lineId);
|
|
72741
|
+
return next;
|
|
72742
|
+
});
|
|
72743
|
+
}, []);
|
|
72679
72744
|
const showToast = useCallback((type, message) => {
|
|
72680
72745
|
if (onToast) {
|
|
72681
72746
|
try {
|
|
@@ -72695,7 +72760,7 @@ var ShiftsView = ({
|
|
|
72695
72760
|
try {
|
|
72696
72761
|
setLoading(true);
|
|
72697
72762
|
setError(null);
|
|
72698
|
-
const { data: enabledLines, error: linesError } = await supabase.from("lines").select("id, enable").in("id",
|
|
72763
|
+
const { data: enabledLines, error: linesError } = await supabase.from("lines").select("id, enable").in("id", stableLineIds).eq("enable", true);
|
|
72699
72764
|
if (linesError) {
|
|
72700
72765
|
console.error("Error fetching enabled lines:", linesError);
|
|
72701
72766
|
showToast("error", "Error loading lines");
|
|
@@ -72727,18 +72792,21 @@ var ShiftsView = ({
|
|
|
72727
72792
|
return acc;
|
|
72728
72793
|
}, {});
|
|
72729
72794
|
setLineConfigs((prev) => {
|
|
72730
|
-
const
|
|
72731
|
-
return
|
|
72732
|
-
const
|
|
72795
|
+
const previousByLineId = new Map(prev.map((config) => [config.id, config]));
|
|
72796
|
+
return enabledLineIds.map((lineId) => {
|
|
72797
|
+
const existingConfig = previousByLineId.get(lineId);
|
|
72798
|
+
const rows = shiftsByLine[lineId] || [];
|
|
72733
72799
|
const builtConfig = buildShiftConfigFromOperatingHoursRows(rows);
|
|
72734
|
-
const lineName = lineNameMap[
|
|
72800
|
+
const lineName = lineNameMap[lineId] || mergedLineNames[lineId] || `Line ${lineId.substring(0, 4)}`;
|
|
72735
72801
|
const sortedShifts = [...builtConfig.shifts || []].sort((a, b) => a.shiftId - b.shiftId);
|
|
72736
72802
|
return {
|
|
72737
|
-
|
|
72803
|
+
id: lineId,
|
|
72738
72804
|
name: lineName,
|
|
72805
|
+
timezone: builtConfig.timezone || existingConfig?.timezone || "Asia/Kolkata",
|
|
72739
72806
|
shifts: sortedShifts,
|
|
72740
|
-
|
|
72741
|
-
|
|
72807
|
+
isSaving: existingConfig?.isSaving ?? false,
|
|
72808
|
+
saveSuccess: existingConfig?.saveSuccess ?? false,
|
|
72809
|
+
isOpen: existingConfig?.isOpen ?? getStoredLineState(lineId)
|
|
72742
72810
|
};
|
|
72743
72811
|
});
|
|
72744
72812
|
});
|
|
@@ -72751,7 +72819,7 @@ var ShiftsView = ({
|
|
|
72751
72819
|
}
|
|
72752
72820
|
};
|
|
72753
72821
|
fetchShiftConfigs();
|
|
72754
|
-
}, [
|
|
72822
|
+
}, [stableLineIds, showToast]);
|
|
72755
72823
|
useCallback((lineId) => {
|
|
72756
72824
|
setLineConfigs((prev) => {
|
|
72757
72825
|
const typedPrev = prev;
|
|
@@ -72763,6 +72831,7 @@ var ShiftsView = ({
|
|
|
72763
72831
|
});
|
|
72764
72832
|
}, []);
|
|
72765
72833
|
const updateShiftTime = useCallback((lineId, shiftIndex, field, value) => {
|
|
72834
|
+
markLineDirty(lineId);
|
|
72766
72835
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72767
72836
|
if (config.id === lineId && config.shifts) {
|
|
72768
72837
|
const newShifts = [...config.shifts];
|
|
@@ -72773,8 +72842,9 @@ var ShiftsView = ({
|
|
|
72773
72842
|
}
|
|
72774
72843
|
return config;
|
|
72775
72844
|
}));
|
|
72776
|
-
}, []);
|
|
72845
|
+
}, [markLineDirty]);
|
|
72777
72846
|
const addShiftBreak = useCallback((lineId, shiftIndex) => {
|
|
72847
|
+
markLineDirty(lineId);
|
|
72778
72848
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72779
72849
|
if (config.id === lineId && config.shifts) {
|
|
72780
72850
|
const newShifts = [...config.shifts];
|
|
@@ -72795,8 +72865,9 @@ var ShiftsView = ({
|
|
|
72795
72865
|
}
|
|
72796
72866
|
return config;
|
|
72797
72867
|
}));
|
|
72798
|
-
}, []);
|
|
72868
|
+
}, [markLineDirty]);
|
|
72799
72869
|
const updateShiftBreak = useCallback((lineId, shiftIndex, breakIndex, field, value) => {
|
|
72870
|
+
markLineDirty(lineId);
|
|
72800
72871
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72801
72872
|
if (config.id === lineId && config.shifts) {
|
|
72802
72873
|
const newShifts = [...config.shifts];
|
|
@@ -72822,8 +72893,9 @@ var ShiftsView = ({
|
|
|
72822
72893
|
}
|
|
72823
72894
|
return config;
|
|
72824
72895
|
}));
|
|
72825
|
-
}, []);
|
|
72896
|
+
}, [markLineDirty]);
|
|
72826
72897
|
const removeShiftBreak = useCallback((lineId, shiftIndex, breakIndex) => {
|
|
72898
|
+
markLineDirty(lineId);
|
|
72827
72899
|
setLineConfigs((prev) => prev.map((config) => {
|
|
72828
72900
|
if (config.id === lineId && config.shifts) {
|
|
72829
72901
|
const newShifts = [...config.shifts];
|
|
@@ -72838,7 +72910,7 @@ var ShiftsView = ({
|
|
|
72838
72910
|
}
|
|
72839
72911
|
return config;
|
|
72840
72912
|
}));
|
|
72841
|
-
}, []);
|
|
72913
|
+
}, [markLineDirty]);
|
|
72842
72914
|
const getOperationalDateForLine = useCallback((lineConfig) => {
|
|
72843
72915
|
const sortedShifts = [...lineConfig.shifts || []].sort((a, b) => a.shiftId - b.shiftId);
|
|
72844
72916
|
const dayBoundaryStart = sortedShifts[0]?.startTime || "06:00";
|
|
@@ -73123,6 +73195,11 @@ var ShiftsView = ({
|
|
|
73123
73195
|
setLineConfigs((prev) => prev.map(
|
|
73124
73196
|
(config) => config.id === lineId ? { ...config, isSaving: false, saveSuccess: true } : config
|
|
73125
73197
|
));
|
|
73198
|
+
setDirtyLineIds((prev) => {
|
|
73199
|
+
const next = new Set(prev);
|
|
73200
|
+
next.delete(lineId);
|
|
73201
|
+
return next;
|
|
73202
|
+
});
|
|
73126
73203
|
let successMessage = "Shift configurations saved successfully.";
|
|
73127
73204
|
if (changedShiftCount > 0 && recalculatedTargetsCount > 0) {
|
|
73128
73205
|
successMessage = `Shift configurations saved. Targets updated successfully for ${recalculatedTargetsCount} workspace${recalculatedTargetsCount === 1 ? "" : "s"}.`;
|
|
@@ -74207,8 +74284,13 @@ var TargetsView = ({
|
|
|
74207
74284
|
onSaveChanges
|
|
74208
74285
|
}) => {
|
|
74209
74286
|
const timezone = useAppTimezone();
|
|
74287
|
+
const lineIdsKey = useMemo(() => lineIds.join("|"), [lineIds]);
|
|
74288
|
+
const stableLineIds = useMemo(
|
|
74289
|
+
() => lineIdsKey.split("|").filter(Boolean),
|
|
74290
|
+
[lineIdsKey]
|
|
74291
|
+
);
|
|
74210
74292
|
useMemo(() => {
|
|
74211
|
-
return
|
|
74293
|
+
return stableLineIds.reduce((acc, lineId) => ({
|
|
74212
74294
|
...acc,
|
|
74213
74295
|
[lineId]: {
|
|
74214
74296
|
productId: "",
|
|
@@ -74222,9 +74304,9 @@ var TargetsView = ({
|
|
|
74222
74304
|
// Initialize factoryId
|
|
74223
74305
|
}
|
|
74224
74306
|
}), {});
|
|
74225
|
-
}, [
|
|
74307
|
+
}, [stableLineIds]);
|
|
74226
74308
|
const [dropdownStates, setDropdownStates] = useState(() => {
|
|
74227
|
-
return
|
|
74309
|
+
return stableLineIds.reduce((acc, lineId) => ({
|
|
74228
74310
|
...acc,
|
|
74229
74311
|
[lineId]: getStoredLineState2(lineId)
|
|
74230
74312
|
}), {});
|
|
@@ -74232,10 +74314,10 @@ var TargetsView = ({
|
|
|
74232
74314
|
const [allShiftsData, setAllShiftsData] = useState({});
|
|
74233
74315
|
const [actionIds, setActionIds] = useState(null);
|
|
74234
74316
|
const [savingLines, setSavingLines] = useState(
|
|
74235
|
-
() =>
|
|
74317
|
+
() => stableLineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
|
|
74236
74318
|
);
|
|
74237
74319
|
const [saveSuccess, setSaveSuccess] = useState(
|
|
74238
|
-
() =>
|
|
74320
|
+
() => stableLineIds.reduce((acc, id3) => ({ ...acc, [id3]: false }), {})
|
|
74239
74321
|
);
|
|
74240
74322
|
const [isLoading, setIsLoading] = useState(true);
|
|
74241
74323
|
const [isConfigureLegendOpen, setIsConfigureLegendOpen] = useState(false);
|
|
@@ -74245,6 +74327,8 @@ var TargetsView = ({
|
|
|
74245
74327
|
const canSaveTargets = useCanSaveTargets();
|
|
74246
74328
|
const [dbValues, setDbValues] = useState({ 0: {}, 1: {} });
|
|
74247
74329
|
const [userEditedFields, setUserEditedFields] = useState(/* @__PURE__ */ new Set());
|
|
74330
|
+
const hasUnsavedChanges = userEditedFields.size > 0;
|
|
74331
|
+
useUnsavedChangesPrompt(hasUnsavedChanges);
|
|
74248
74332
|
const lineWorkspaces = allShiftsData[selectedShift] || {};
|
|
74249
74333
|
const setLineWorkspaces = useCallback((updater) => {
|
|
74250
74334
|
setAllShiftsData((prev) => ({
|
|
@@ -74261,13 +74345,13 @@ var TargetsView = ({
|
|
|
74261
74345
|
dbLines.forEach((line) => {
|
|
74262
74346
|
merged[line.id] = line.line_name;
|
|
74263
74347
|
});
|
|
74264
|
-
|
|
74348
|
+
stableLineIds.forEach((lineId) => {
|
|
74265
74349
|
if (!merged[lineId]) {
|
|
74266
74350
|
merged[lineId] = `Line ${lineId.substring(0, 4)}`;
|
|
74267
74351
|
}
|
|
74268
74352
|
});
|
|
74269
74353
|
return merged;
|
|
74270
|
-
}, [lineNames, dbLines,
|
|
74354
|
+
}, [lineNames, dbLines, stableLineIds]);
|
|
74271
74355
|
const { legend, updateLegend } = useEfficiencyLegend(companyId);
|
|
74272
74356
|
const { skus, isLoading: skusLoading } = useSKUs(companyId);
|
|
74273
74357
|
const { skus: skuCatalog, isLoading: skuCatalogLoading } = useSKUs(companyId, {
|
|
@@ -74326,22 +74410,22 @@ var TargetsView = ({
|
|
|
74326
74410
|
useEffect(() => {
|
|
74327
74411
|
console.log("[TargetsView] Component mounted/re-rendered", {
|
|
74328
74412
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
74329
|
-
lineIds:
|
|
74413
|
+
lineIds: stableLineIds.length,
|
|
74330
74414
|
effectiveUserId
|
|
74331
74415
|
});
|
|
74332
74416
|
return () => {
|
|
74333
74417
|
console.log("[TargetsView] Component unmounting");
|
|
74334
74418
|
};
|
|
74335
|
-
}, []);
|
|
74419
|
+
}, [effectiveUserId, stableLineIds.length]);
|
|
74336
74420
|
useEffect(() => {
|
|
74337
74421
|
const fetchInitialData = async () => {
|
|
74338
|
-
if (
|
|
74422
|
+
if (stableLineIds.length === 0 || !companyId) return;
|
|
74339
74423
|
if (skuCatalogLoading) return;
|
|
74340
74424
|
console.log("[TargetsView] Starting optimized fetchInitialData with bulk endpoint");
|
|
74341
74425
|
setIsLoading(true);
|
|
74342
74426
|
try {
|
|
74343
74427
|
const currentDate = getOperationalDate(timezone);
|
|
74344
|
-
const { data: shiftsData, error: shiftsError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name").in("line_id",
|
|
74428
|
+
const { data: shiftsData, error: shiftsError } = await supabase.from("line_operating_hours").select("line_id, shift_id, shift_name").in("line_id", stableLineIds);
|
|
74345
74429
|
if (shiftsError) {
|
|
74346
74430
|
console.warn("[TargetsView] Error fetching shift definitions, falling back to defaults", shiftsError);
|
|
74347
74431
|
}
|
|
@@ -74359,7 +74443,7 @@ var TargetsView = ({
|
|
|
74359
74443
|
setSelectedShift(defaultShiftId);
|
|
74360
74444
|
const bulkResponse = await workspaceService.fetchBulkTargets({
|
|
74361
74445
|
companyId,
|
|
74362
|
-
lineIds,
|
|
74446
|
+
lineIds: stableLineIds,
|
|
74363
74447
|
date: currentDate,
|
|
74364
74448
|
shifts: effectiveShiftOptions.map((s) => s.id),
|
|
74365
74449
|
// Fetch all configured shifts
|
|
@@ -74504,7 +74588,7 @@ var TargetsView = ({
|
|
|
74504
74588
|
});
|
|
74505
74589
|
});
|
|
74506
74590
|
effectiveShiftOptions.forEach(({ id: shiftId }) => {
|
|
74507
|
-
|
|
74591
|
+
stableLineIds.forEach((lineId) => {
|
|
74508
74592
|
if (!newAllShiftsData[shiftId][lineId]) {
|
|
74509
74593
|
const lineData = data.lines[lineId];
|
|
74510
74594
|
const shift0Data = newAllShiftsData[0]?.[lineId];
|
|
@@ -74574,7 +74658,7 @@ var TargetsView = ({
|
|
|
74574
74658
|
});
|
|
74575
74659
|
effectiveShiftOptions.forEach(({ id: shiftId }) => {
|
|
74576
74660
|
const orderedLineWorkspaces = {};
|
|
74577
|
-
|
|
74661
|
+
stableLineIds.forEach((lineId) => {
|
|
74578
74662
|
if (newAllShiftsData[shiftId][lineId]) {
|
|
74579
74663
|
orderedLineWorkspaces[lineId] = newAllShiftsData[shiftId][lineId];
|
|
74580
74664
|
}
|
|
@@ -74596,7 +74680,7 @@ var TargetsView = ({
|
|
|
74596
74680
|
}
|
|
74597
74681
|
};
|
|
74598
74682
|
fetchInitialData();
|
|
74599
|
-
}, [
|
|
74683
|
+
}, [stableLineIds, companyId, timezone, skuEnabled, skuCatalogLoading]);
|
|
74600
74684
|
const toggleLineDropdown = useCallback((lineId) => {
|
|
74601
74685
|
setDropdownStates((prev) => {
|
|
74602
74686
|
const newIsOpen = !prev[lineId];
|
|
@@ -74771,6 +74855,7 @@ var TargetsView = ({
|
|
|
74771
74855
|
};
|
|
74772
74856
|
const handleActionTypeChange = useCallback((lineId, workspaceId, newActionType) => {
|
|
74773
74857
|
if (!actionIds) return;
|
|
74858
|
+
setUserEditedFields((prev) => new Set(prev).add(`${lineId}-${workspaceId}-actionType`));
|
|
74774
74859
|
setLineWorkspaces((prev) => {
|
|
74775
74860
|
const currentLineData = prev?.[lineId];
|
|
74776
74861
|
if (!currentLineData?.workspaces) {
|
|
@@ -74968,10 +75053,10 @@ var TargetsView = ({
|
|
|
74968
75053
|
console.log(`[handleSaveLine] Updated dbValues for line ${lineId}, shift ${selectedShift}`);
|
|
74969
75054
|
setUserEditedFields((prev) => {
|
|
74970
75055
|
const newSet = new Set(prev);
|
|
74971
|
-
|
|
74972
|
-
|
|
74973
|
-
|
|
74974
|
-
|
|
75056
|
+
Array.from(newSet).forEach((fieldKey) => {
|
|
75057
|
+
if (fieldKey.startsWith(`${lineId}-`)) {
|
|
75058
|
+
newSet.delete(fieldKey);
|
|
75059
|
+
}
|
|
74975
75060
|
});
|
|
74976
75061
|
return newSet;
|
|
74977
75062
|
});
|