@optifye/dashboard-core 6.10.11 → 6.10.13
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 +38 -0
- package/dist/index.d.mts +59 -2
- package/dist/index.d.ts +59 -2
- package/dist/index.js +975 -184
- package/dist/index.mjs +967 -186
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -558,6 +558,84 @@ function getCurrentTimeInZone(timezone, formatString) {
|
|
|
558
558
|
}
|
|
559
559
|
return now2;
|
|
560
560
|
}
|
|
561
|
+
var pad2 = (value) => String(value).padStart(2, "0");
|
|
562
|
+
var buildDateKey = (year, monthIndex, day) => {
|
|
563
|
+
return `${year}-${pad2(monthIndex + 1)}-${pad2(day)}`;
|
|
564
|
+
};
|
|
565
|
+
var getDateKeyFromDate = (date) => {
|
|
566
|
+
return date.toISOString().split("T")[0];
|
|
567
|
+
};
|
|
568
|
+
var parseDateKeyToDate = (dateKey) => {
|
|
569
|
+
const [year, month, day] = dateKey.split("-").map(Number);
|
|
570
|
+
return new Date(year, month - 1, day);
|
|
571
|
+
};
|
|
572
|
+
var formatDateKeyForDisplay = (dateKey, formatStr = "MMM d, yyyy") => {
|
|
573
|
+
return dateFns.format(parseDateKeyToDate(dateKey), formatStr);
|
|
574
|
+
};
|
|
575
|
+
var getMonthKeyBounds = (year, monthIndex) => {
|
|
576
|
+
const startKey = buildDateKey(year, monthIndex, 1);
|
|
577
|
+
const lastDay = new Date(year, monthIndex + 1, 0).getDate();
|
|
578
|
+
const endKey = buildDateKey(year, monthIndex, lastDay);
|
|
579
|
+
return { startKey, endKey };
|
|
580
|
+
};
|
|
581
|
+
var normalizeDateKeyRange = (startKey, endKey, minKey, maxKey) => {
|
|
582
|
+
const clampedStart = startKey < minKey ? minKey : startKey > maxKey ? maxKey : startKey;
|
|
583
|
+
const clampedEnd = endKey < minKey ? minKey : endKey > maxKey ? maxKey : endKey;
|
|
584
|
+
if (clampedStart <= clampedEnd) {
|
|
585
|
+
return { startKey: clampedStart, endKey: clampedEnd };
|
|
586
|
+
}
|
|
587
|
+
return { startKey: clampedEnd, endKey: clampedStart };
|
|
588
|
+
};
|
|
589
|
+
var isFullMonthRange = (range, year, monthIndex) => {
|
|
590
|
+
const bounds = getMonthKeyBounds(year, monthIndex);
|
|
591
|
+
return range.startKey === bounds.startKey && range.endKey === bounds.endKey;
|
|
592
|
+
};
|
|
593
|
+
var getMonthWeekRanges = (year, monthIndex, timezone, maxKey) => {
|
|
594
|
+
const totalDays = new Date(year, monthIndex + 1, 0).getDate();
|
|
595
|
+
const ranges = [];
|
|
596
|
+
let currentStartDay = 1;
|
|
597
|
+
for (let day = 1; day <= totalDays; day += 1) {
|
|
598
|
+
const zonedDate = dateFnsTz.toZonedTime(new Date(year, monthIndex, day), timezone);
|
|
599
|
+
const dayOfWeek = zonedDate.getDay();
|
|
600
|
+
const isEndOfWeek = dayOfWeek === 0 || day === totalDays;
|
|
601
|
+
if (isEndOfWeek) {
|
|
602
|
+
const startKey = buildDateKey(year, monthIndex, currentStartDay);
|
|
603
|
+
const endKey = buildDateKey(year, monthIndex, day);
|
|
604
|
+
if (maxKey && startKey > maxKey) {
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
const clampedEndKey = maxKey && endKey > maxKey ? maxKey : endKey;
|
|
608
|
+
if (clampedEndKey < startKey) {
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
611
|
+
const labelStart = formatDateKeyForDisplay(startKey, "MMM d");
|
|
612
|
+
const labelEnd = formatDateKeyForDisplay(clampedEndKey, "MMM d");
|
|
613
|
+
ranges.push({
|
|
614
|
+
startKey,
|
|
615
|
+
endKey: clampedEndKey,
|
|
616
|
+
label: `Week of ${labelStart} - ${labelEnd}`
|
|
617
|
+
});
|
|
618
|
+
currentStartDay = day + 1;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
return ranges;
|
|
622
|
+
};
|
|
623
|
+
var formatRangeLabel = (range, fullMonthLabel) => {
|
|
624
|
+
if (!range.startKey || !range.endKey) return fullMonthLabel;
|
|
625
|
+
if (range.startKey === range.endKey) {
|
|
626
|
+
return formatDateKeyForDisplay(range.startKey, "MMM d, yyyy");
|
|
627
|
+
}
|
|
628
|
+
const startLabel = formatDateKeyForDisplay(range.startKey, "MMM d");
|
|
629
|
+
const endLabel = formatDateKeyForDisplay(range.endKey, "MMM d, yyyy");
|
|
630
|
+
return `${startLabel} - ${endLabel}`;
|
|
631
|
+
};
|
|
632
|
+
var filterDataByDateKeyRange = (data, range) => {
|
|
633
|
+
if (!range.startKey || !range.endKey) return data;
|
|
634
|
+
return (data || []).filter((item) => {
|
|
635
|
+
const dateKey = typeof item.date === "string" ? item.date : getDateKeyFromDate(item.date);
|
|
636
|
+
return dateKey >= range.startKey && dateKey <= range.endKey;
|
|
637
|
+
});
|
|
638
|
+
};
|
|
561
639
|
|
|
562
640
|
// src/lib/utils/shifts.ts
|
|
563
641
|
var DEFAULT_DAY_SHIFT_START = "06:00";
|
|
@@ -1530,7 +1608,7 @@ var dashboardService = {
|
|
|
1530
1608
|
throw err;
|
|
1531
1609
|
}
|
|
1532
1610
|
},
|
|
1533
|
-
async getUnderperformingWorkspaces(lineIdInput, monthInput, yearInput, shiftIds) {
|
|
1611
|
+
async getUnderperformingWorkspaces(lineIdInput, monthInput, yearInput, shiftIds, startDate, endDate) {
|
|
1534
1612
|
_getSupabaseInstance();
|
|
1535
1613
|
const config = _getDashboardConfigInstance();
|
|
1536
1614
|
const entityConfig = config.entityConfig ?? DEFAULT_ENTITY_CONFIG;
|
|
@@ -1557,7 +1635,9 @@ var dashboardService = {
|
|
|
1557
1635
|
year: currentYear,
|
|
1558
1636
|
companyId,
|
|
1559
1637
|
metricsTable,
|
|
1560
|
-
shifts: dynamicShiftIds
|
|
1638
|
+
shifts: dynamicShiftIds,
|
|
1639
|
+
...startDate ? { start_date: startDate } : {},
|
|
1640
|
+
...endDate ? { end_date: endDate } : {}
|
|
1561
1641
|
};
|
|
1562
1642
|
const response = await fetch(fullFunctionUrl, {
|
|
1563
1643
|
method: "POST",
|
|
@@ -29146,6 +29226,8 @@ var ERROR_MAPPING = {
|
|
|
29146
29226
|
};
|
|
29147
29227
|
var CLIP_ID_COMMENT_REGEX = /#\s*Clip ID:\s*([a-f0-9-]+)/i;
|
|
29148
29228
|
var PLAYLIST_PROXY_REGEX = /\/api\/clips\/playlist\/([a-f0-9-]+)/i;
|
|
29229
|
+
var REMUX_URL_COMMENT_REGEX = /#\s*Remux URL:\s*([^\s]+)/i;
|
|
29230
|
+
var REMUXING_ENABLED_REGEX = /#\s*Remuxing:\s*enabled/i;
|
|
29149
29231
|
var R2_FALLBACK_DETAILS = /* @__PURE__ */ new Set([
|
|
29150
29232
|
"fragLoadError",
|
|
29151
29233
|
"fragLoadHTTPError",
|
|
@@ -29161,6 +29243,13 @@ var extractClipIdFromSource = (source) => {
|
|
|
29161
29243
|
if (urlMatch) return urlMatch[1];
|
|
29162
29244
|
return null;
|
|
29163
29245
|
};
|
|
29246
|
+
var extractRemuxUrl = (source) => {
|
|
29247
|
+
if (!source) return null;
|
|
29248
|
+
if (!REMUXING_ENABLED_REGEX.test(source)) return null;
|
|
29249
|
+
const remuxMatch = source.match(REMUX_URL_COMMENT_REGEX);
|
|
29250
|
+
if (remuxMatch) return remuxMatch[1];
|
|
29251
|
+
return null;
|
|
29252
|
+
};
|
|
29164
29253
|
var ensureClipIdComment = (playlist, clipId) => {
|
|
29165
29254
|
if (!playlist || playlist.includes(`# Clip ID: ${clipId}`) || CLIP_ID_COMMENT_REGEX.test(playlist)) {
|
|
29166
29255
|
return playlist;
|
|
@@ -29489,7 +29578,50 @@ var HlsVideoPlayer = React24.forwardRef(({
|
|
|
29489
29578
|
if (effectiveSrc.startsWith("#EXTM3U")) {
|
|
29490
29579
|
const safariMode = isSafari();
|
|
29491
29580
|
const browserName = getBrowserName();
|
|
29492
|
-
|
|
29581
|
+
const remuxUrl = extractRemuxUrl(effectiveSrc);
|
|
29582
|
+
if (remuxUrl) {
|
|
29583
|
+
console.log(`[HlsVideoPlayer] Remuxing enabled - using remux playlist URL: ${remuxUrl}`);
|
|
29584
|
+
if (safariMode) {
|
|
29585
|
+
video.src = remuxUrl;
|
|
29586
|
+
} else if (Hls3__default.default.isSupported()) {
|
|
29587
|
+
const hls = new Hls3__default.default(mergedHlsConfig);
|
|
29588
|
+
hlsRef.current = hls;
|
|
29589
|
+
hls.on(Hls3.Events.MANIFEST_PARSED, () => {
|
|
29590
|
+
console.log("[HlsVideoPlayer] Remuxed manifest parsed, ready to play");
|
|
29591
|
+
setIsReady(true);
|
|
29592
|
+
eventCallbacksRef.current.onReady?.(player);
|
|
29593
|
+
});
|
|
29594
|
+
hls.on(Hls3.Events.ERROR, (_event, data) => {
|
|
29595
|
+
console.error("[HlsVideoPlayer] HLS.js error (remuxing):", data);
|
|
29596
|
+
if (data.fatal) {
|
|
29597
|
+
let errorInfo;
|
|
29598
|
+
switch (data.type) {
|
|
29599
|
+
case Hls3.ErrorTypes.NETWORK_ERROR:
|
|
29600
|
+
errorInfo = ERROR_MAPPING.networkError;
|
|
29601
|
+
hls.startLoad();
|
|
29602
|
+
break;
|
|
29603
|
+
case Hls3.ErrorTypes.MEDIA_ERROR:
|
|
29604
|
+
errorInfo = ERROR_MAPPING.mediaError;
|
|
29605
|
+
hls.recoverMediaError();
|
|
29606
|
+
break;
|
|
29607
|
+
default:
|
|
29608
|
+
errorInfo = ERROR_MAPPING.otherError;
|
|
29609
|
+
break;
|
|
29610
|
+
}
|
|
29611
|
+
errorInfo.details = data.details;
|
|
29612
|
+
eventCallbacksRef.current.onError?.(player, errorInfo);
|
|
29613
|
+
}
|
|
29614
|
+
});
|
|
29615
|
+
hls.on(Hls3.Events.FRAG_LOADED, () => {
|
|
29616
|
+
setIsLoading(false);
|
|
29617
|
+
eventCallbacksRef.current.onLoadingChange?.(false);
|
|
29618
|
+
});
|
|
29619
|
+
hls.loadSource(remuxUrl);
|
|
29620
|
+
hls.attachMedia(video);
|
|
29621
|
+
} else {
|
|
29622
|
+
video.src = remuxUrl;
|
|
29623
|
+
}
|
|
29624
|
+
} else if (safariMode) {
|
|
29493
29625
|
const clipIdMatch = effectiveSrc.match(/# Clip ID: ([a-f0-9-]+)/i);
|
|
29494
29626
|
if (clipIdMatch) {
|
|
29495
29627
|
const proxyUrl = `/api/clips/playlist/${clipIdMatch[1]}`;
|
|
@@ -36428,6 +36560,8 @@ var LineHistoryCalendar = ({
|
|
|
36428
36560
|
year,
|
|
36429
36561
|
lineId,
|
|
36430
36562
|
selectedShiftId,
|
|
36563
|
+
rangeStart,
|
|
36564
|
+
rangeEnd,
|
|
36431
36565
|
onDateSelect,
|
|
36432
36566
|
className = ""
|
|
36433
36567
|
}) => {
|
|
@@ -36438,6 +36572,7 @@ var LineHistoryCalendar = ({
|
|
|
36438
36572
|
const currentTimeInZone = getCurrentTimeInZone(configuredTimezone);
|
|
36439
36573
|
return typeof currentTimeInZone === "string" ? new Date(currentTimeInZone) : currentTimeInZone;
|
|
36440
36574
|
}, [configuredTimezone]);
|
|
36575
|
+
const monthBounds = React24.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
36441
36576
|
const calendarData = React24.useMemo(() => {
|
|
36442
36577
|
const startOfMonth = dateFnsTz.toZonedTime(new Date(year, month, 1), configuredTimezone);
|
|
36443
36578
|
const endOfMonth = dateFnsTz.toZonedTime(new Date(year, month + 1, 0), configuredTimezone);
|
|
@@ -36519,6 +36654,10 @@ var LineHistoryCalendar = ({
|
|
|
36519
36654
|
const isFuture = isFutureDate(day.date instanceof Date ? day.date : new Date(day.date));
|
|
36520
36655
|
const hasData = hasRealData(shiftData);
|
|
36521
36656
|
const dateObj = day.date instanceof Date ? day.date : new Date(day.date);
|
|
36657
|
+
const dateKey = `${dateObj.getFullYear()}-${String(dateObj.getMonth() + 1).padStart(2, "0")}-${String(dateObj.getDate()).padStart(2, "0")}`;
|
|
36658
|
+
const showRange = rangeStart && rangeEnd ? !(rangeStart === monthBounds.startKey && rangeEnd === monthBounds.endKey) : false;
|
|
36659
|
+
const inRange = showRange ? dateKey >= rangeStart && dateKey <= rangeEnd : false;
|
|
36660
|
+
const isRangeEdge = inRange && (dateKey === rangeStart || dateKey === rangeEnd);
|
|
36522
36661
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
36523
36662
|
"div",
|
|
36524
36663
|
{
|
|
@@ -36539,7 +36678,15 @@ var LineHistoryCalendar = ({
|
|
|
36539
36678
|
underperforming_workspaces: shiftData.underperforming_workspaces || 0,
|
|
36540
36679
|
total_workspaces: shiftData.total_workspaces || 0
|
|
36541
36680
|
});
|
|
36542
|
-
const
|
|
36681
|
+
const params = new URLSearchParams();
|
|
36682
|
+
params.set("tab", "monthly_history");
|
|
36683
|
+
params.set("month", month2.toString());
|
|
36684
|
+
params.set("year", year2.toString());
|
|
36685
|
+
if (rangeStart && rangeEnd && !(rangeStart === monthBounds.startKey && rangeEnd === monthBounds.endKey)) {
|
|
36686
|
+
params.set("rangeStart", rangeStart);
|
|
36687
|
+
params.set("rangeEnd", rangeEnd);
|
|
36688
|
+
}
|
|
36689
|
+
const returnTo = `/kpis/${lineId}?${params.toString()}`;
|
|
36543
36690
|
if (onDateSelect) {
|
|
36544
36691
|
onDateSelect(date, selectedShiftId);
|
|
36545
36692
|
} else {
|
|
@@ -36552,8 +36699,14 @@ var LineHistoryCalendar = ({
|
|
|
36552
36699
|
rounded-lg h-full p-2 relative
|
|
36553
36700
|
${isToday2 ? "ring-2 ring-blue-500 dark:ring-blue-400 ring-offset-2 dark:ring-offset-gray-800 shadow-md" : ""}
|
|
36554
36701
|
`, children: [
|
|
36702
|
+
inRange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
36703
|
+
"div",
|
|
36704
|
+
{
|
|
36705
|
+
className: `absolute inset-0 rounded-lg pointer-events-none ${isRangeEdge ? "ring-2 ring-blue-500" : "ring-2 ring-blue-200"}`
|
|
36706
|
+
}
|
|
36707
|
+
),
|
|
36555
36708
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
36556
|
-
text-base font-medium ${hasData ? "text-white" : "text-gray-500"} flex items-center
|
|
36709
|
+
text-base font-medium ${hasData ? "text-white" : "text-gray-500"} flex items-center relative z-10
|
|
36557
36710
|
${isToday2 ? "bg-blue-500 dark:bg-blue-600 rounded-full w-7 h-7 justify-center" : ""}
|
|
36558
36711
|
`, children: dateObj.getDate() }),
|
|
36559
36712
|
!isFuture && hasData && renderStats(shiftData, dateObj)
|
|
@@ -36731,6 +36884,183 @@ var IdleTimeReasonChart = ({
|
|
|
36731
36884
|
] });
|
|
36732
36885
|
};
|
|
36733
36886
|
var IdleTimeReasonChart_default = IdleTimeReasonChart;
|
|
36887
|
+
var MonthlyRangeFilter = ({
|
|
36888
|
+
month,
|
|
36889
|
+
year,
|
|
36890
|
+
timezone,
|
|
36891
|
+
value,
|
|
36892
|
+
onChange,
|
|
36893
|
+
className
|
|
36894
|
+
}) => {
|
|
36895
|
+
const monthBounds = React24.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
36896
|
+
const weekRanges = React24.useMemo(() => getMonthWeekRanges(year, month, timezone), [year, month, timezone]);
|
|
36897
|
+
const normalizedRange = React24.useMemo(() => {
|
|
36898
|
+
return normalizeDateKeyRange(value.startKey, value.endKey, monthBounds.startKey, monthBounds.endKey);
|
|
36899
|
+
}, [value.startKey, value.endKey, monthBounds.startKey, monthBounds.endKey]);
|
|
36900
|
+
const monthLabel = React24.useMemo(() => {
|
|
36901
|
+
return new Date(year, month).toLocaleString("default", { month: "long", year: "numeric" });
|
|
36902
|
+
}, [year, month]);
|
|
36903
|
+
const presetOptions = React24.useMemo(() => {
|
|
36904
|
+
const fullMonthRangeLabel = `${formatDateKeyForDisplay(monthBounds.startKey, "MMM d")} - ${formatDateKeyForDisplay(monthBounds.endKey, "MMM d")}`;
|
|
36905
|
+
const presets = [
|
|
36906
|
+
{
|
|
36907
|
+
id: "full-month",
|
|
36908
|
+
label: "Full month",
|
|
36909
|
+
rangeLabel: fullMonthRangeLabel,
|
|
36910
|
+
startKey: monthBounds.startKey,
|
|
36911
|
+
endKey: monthBounds.endKey
|
|
36912
|
+
}
|
|
36913
|
+
];
|
|
36914
|
+
weekRanges.forEach((range, index) => {
|
|
36915
|
+
const rangeLabel = `${formatDateKeyForDisplay(range.startKey, "MMM d")} - ${formatDateKeyForDisplay(range.endKey, "MMM d")}`;
|
|
36916
|
+
presets.push({
|
|
36917
|
+
id: `week-${index + 1}`,
|
|
36918
|
+
label: `Week ${index + 1}`,
|
|
36919
|
+
rangeLabel,
|
|
36920
|
+
startKey: range.startKey,
|
|
36921
|
+
endKey: range.endKey
|
|
36922
|
+
});
|
|
36923
|
+
});
|
|
36924
|
+
return presets;
|
|
36925
|
+
}, [monthBounds.startKey, monthBounds.endKey, weekRanges]);
|
|
36926
|
+
const activePreset = React24.useMemo(() => {
|
|
36927
|
+
return presetOptions.find(
|
|
36928
|
+
(preset) => preset.startKey === normalizedRange.startKey && preset.endKey === normalizedRange.endKey
|
|
36929
|
+
);
|
|
36930
|
+
}, [presetOptions, normalizedRange.startKey, normalizedRange.endKey]);
|
|
36931
|
+
const displayLabel = React24.useMemo(() => {
|
|
36932
|
+
if (activePreset) return activePreset.label;
|
|
36933
|
+
return "Custom range";
|
|
36934
|
+
}, [activePreset]);
|
|
36935
|
+
const fullMonthLabel = React24.useMemo(() => {
|
|
36936
|
+
const startLabel = formatDateKeyForDisplay(monthBounds.startKey, "MMM d");
|
|
36937
|
+
const endLabel = formatDateKeyForDisplay(monthBounds.endKey, "MMM d, yyyy");
|
|
36938
|
+
return `${startLabel} - ${endLabel}`;
|
|
36939
|
+
}, [monthBounds.startKey, monthBounds.endKey]);
|
|
36940
|
+
const displayRange = React24.useMemo(() => {
|
|
36941
|
+
return formatRangeLabel(normalizedRange, fullMonthLabel);
|
|
36942
|
+
}, [normalizedRange, fullMonthLabel]);
|
|
36943
|
+
const [customStart, setCustomStart] = React24.useState(normalizedRange.startKey);
|
|
36944
|
+
const [customEnd, setCustomEnd] = React24.useState(normalizedRange.endKey);
|
|
36945
|
+
const [isOpen, setIsOpen] = React24.useState(false);
|
|
36946
|
+
const dropdownRef = React24.useRef(null);
|
|
36947
|
+
React24.useEffect(() => {
|
|
36948
|
+
setCustomStart(normalizedRange.startKey);
|
|
36949
|
+
setCustomEnd(normalizedRange.endKey);
|
|
36950
|
+
}, [normalizedRange.startKey, normalizedRange.endKey]);
|
|
36951
|
+
React24.useEffect(() => {
|
|
36952
|
+
const handleClickOutside = (event) => {
|
|
36953
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
|
36954
|
+
setIsOpen(false);
|
|
36955
|
+
}
|
|
36956
|
+
};
|
|
36957
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
36958
|
+
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
36959
|
+
}, []);
|
|
36960
|
+
const handlePresetSelect = (startKey, endKey) => {
|
|
36961
|
+
const normalized = normalizeDateKeyRange(startKey, endKey, monthBounds.startKey, monthBounds.endKey);
|
|
36962
|
+
onChange(normalized);
|
|
36963
|
+
setIsOpen(false);
|
|
36964
|
+
};
|
|
36965
|
+
const handleCustomApply = () => {
|
|
36966
|
+
if (!customStart || !customEnd) return;
|
|
36967
|
+
const normalized = normalizeDateKeyRange(customStart, customEnd, monthBounds.startKey, monthBounds.endKey);
|
|
36968
|
+
onChange(normalized);
|
|
36969
|
+
setIsOpen(false);
|
|
36970
|
+
};
|
|
36971
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative ${className ?? ""}`, ref: dropdownRef, children: [
|
|
36972
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
36973
|
+
"button",
|
|
36974
|
+
{
|
|
36975
|
+
type: "button",
|
|
36976
|
+
onClick: () => setIsOpen((prev) => !prev),
|
|
36977
|
+
className: "flex items-center gap-3 rounded-lg border border-slate-200 bg-white px-3 py-2 text-left shadow-sm transition-colors hover:border-slate-300 focus:outline-none focus:ring-2 focus:ring-blue-500",
|
|
36978
|
+
children: [
|
|
36979
|
+
/* @__PURE__ */ jsxRuntime.jsx(outline.CalendarIcon, { className: "h-4 w-4 text-slate-500" }),
|
|
36980
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col", children: [
|
|
36981
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] uppercase tracking-[0.2em] text-slate-500", children: displayLabel }),
|
|
36982
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-semibold text-slate-900", children: displayRange })
|
|
36983
|
+
] }),
|
|
36984
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
36985
|
+
outline.ChevronDownIcon,
|
|
36986
|
+
{
|
|
36987
|
+
className: `ml-2 h-4 w-4 text-slate-400 transition-transform ${isOpen ? "rotate-180" : ""}`
|
|
36988
|
+
}
|
|
36989
|
+
)
|
|
36990
|
+
]
|
|
36991
|
+
}
|
|
36992
|
+
),
|
|
36993
|
+
isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-0 z-50 mt-2 w-80 rounded-lg border border-slate-200 bg-white shadow-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-3", children: [
|
|
36994
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] uppercase tracking-[0.18em] text-slate-500", children: "Weeks" }),
|
|
36995
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 space-y-1", children: presetOptions.map((preset) => {
|
|
36996
|
+
const isActive = preset.startKey === normalizedRange.startKey && preset.endKey === normalizedRange.endKey;
|
|
36997
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
36998
|
+
"button",
|
|
36999
|
+
{
|
|
37000
|
+
type: "button",
|
|
37001
|
+
onClick: () => handlePresetSelect(preset.startKey, preset.endKey),
|
|
37002
|
+
className: `flex w-full items-center justify-between rounded-md px-2 py-2 text-left text-sm transition-colors ${isActive ? "bg-blue-50 text-blue-700" : "text-slate-700 hover:bg-slate-50"}`,
|
|
37003
|
+
children: [
|
|
37004
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: preset.label }),
|
|
37005
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-slate-500", children: preset.rangeLabel })
|
|
37006
|
+
]
|
|
37007
|
+
},
|
|
37008
|
+
preset.id
|
|
37009
|
+
);
|
|
37010
|
+
}) }),
|
|
37011
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 border-t border-slate-200 pt-3", children: [
|
|
37012
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
37013
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[11px] uppercase tracking-[0.18em] text-slate-500", children: "Custom range" }),
|
|
37014
|
+
!activePreset && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded-full border border-blue-100 bg-blue-50 px-2 py-0.5 text-[10px] uppercase tracking-wide text-blue-700", children: "Selected" })
|
|
37015
|
+
] }),
|
|
37016
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2 grid grid-cols-1 gap-2 sm:grid-cols-2", children: [
|
|
37017
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
37018
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-[11px] font-medium text-slate-600", children: "Start" }),
|
|
37019
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
37020
|
+
"input",
|
|
37021
|
+
{
|
|
37022
|
+
type: "date",
|
|
37023
|
+
value: customStart,
|
|
37024
|
+
onChange: (event) => setCustomStart(event.target.value),
|
|
37025
|
+
min: monthBounds.startKey,
|
|
37026
|
+
max: monthBounds.endKey,
|
|
37027
|
+
className: "mt-1 w-full rounded-md border border-slate-200 bg-white px-2 py-2 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200"
|
|
37028
|
+
}
|
|
37029
|
+
)
|
|
37030
|
+
] }),
|
|
37031
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
37032
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "block text-[11px] font-medium text-slate-600", children: "End" }),
|
|
37033
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
37034
|
+
"input",
|
|
37035
|
+
{
|
|
37036
|
+
type: "date",
|
|
37037
|
+
value: customEnd,
|
|
37038
|
+
onChange: (event) => setCustomEnd(event.target.value),
|
|
37039
|
+
min: monthBounds.startKey,
|
|
37040
|
+
max: monthBounds.endKey,
|
|
37041
|
+
className: "mt-1 w-full rounded-md border border-slate-200 bg-white px-2 py-2 text-sm text-slate-700 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-200"
|
|
37042
|
+
}
|
|
37043
|
+
)
|
|
37044
|
+
] })
|
|
37045
|
+
] }),
|
|
37046
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
37047
|
+
"button",
|
|
37048
|
+
{
|
|
37049
|
+
type: "button",
|
|
37050
|
+
onClick: handleCustomApply,
|
|
37051
|
+
className: "mt-3 w-full rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white transition-colors hover:bg-blue-700",
|
|
37052
|
+
children: "Apply range"
|
|
37053
|
+
}
|
|
37054
|
+
)
|
|
37055
|
+
] }),
|
|
37056
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-3 text-xs text-slate-400", children: [
|
|
37057
|
+
"Month: ",
|
|
37058
|
+
monthLabel
|
|
37059
|
+
] })
|
|
37060
|
+
] }) })
|
|
37061
|
+
] });
|
|
37062
|
+
};
|
|
37063
|
+
var MonthlyRangeFilter_default = MonthlyRangeFilter;
|
|
36734
37064
|
var DEFAULT_PERFORMANCE_DATA = {
|
|
36735
37065
|
avg_efficiency: 0,
|
|
36736
37066
|
underperforming_workspaces: 0,
|
|
@@ -36748,10 +37078,15 @@ var LineMonthlyHistory = ({
|
|
|
36748
37078
|
month,
|
|
36749
37079
|
year,
|
|
36750
37080
|
monthlyData = [],
|
|
37081
|
+
analysisData,
|
|
37082
|
+
rangeStart,
|
|
37083
|
+
rangeEnd,
|
|
37084
|
+
timezone,
|
|
36751
37085
|
underperformingWorkspaces = {},
|
|
36752
37086
|
lineId,
|
|
36753
37087
|
selectedShiftId = 0,
|
|
36754
37088
|
onShiftChange,
|
|
37089
|
+
onRangeChange,
|
|
36755
37090
|
availableShifts,
|
|
36756
37091
|
onWorkspaceSelect,
|
|
36757
37092
|
onCalendarDateSelect,
|
|
@@ -36760,17 +37095,26 @@ var LineMonthlyHistory = ({
|
|
|
36760
37095
|
className
|
|
36761
37096
|
}) => {
|
|
36762
37097
|
const navigation = useNavigation();
|
|
36763
|
-
const chartKey = React24.useMemo(() => `${lineId}-${month}-${year}-${selectedShiftId}`, [lineId, month, year, selectedShiftId]);
|
|
36764
|
-
const
|
|
36765
|
-
|
|
36766
|
-
|
|
36767
|
-
|
|
36768
|
-
|
|
36769
|
-
|
|
36770
|
-
|
|
36771
|
-
|
|
36772
|
-
|
|
36773
|
-
|
|
37098
|
+
const chartKey = React24.useMemo(() => `${lineId}-${month}-${year}-${selectedShiftId}-${rangeStart}-${rangeEnd}`, [lineId, month, year, selectedShiftId, rangeStart, rangeEnd]);
|
|
37099
|
+
const monthBounds = React24.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
37100
|
+
const normalizedRange = React24.useMemo(() => {
|
|
37101
|
+
const startKey = rangeStart || monthBounds.startKey;
|
|
37102
|
+
const endKey = rangeEnd || monthBounds.endKey;
|
|
37103
|
+
return normalizeDateKeyRange(startKey, endKey, monthBounds.startKey, monthBounds.endKey);
|
|
37104
|
+
}, [rangeStart, rangeEnd, monthBounds.startKey, monthBounds.endKey]);
|
|
37105
|
+
const isFullRange = React24.useMemo(() => isFullMonthRange(normalizedRange, year, month), [normalizedRange, year, month]);
|
|
37106
|
+
const monthLabel = React24.useMemo(() => new Date(year, month).toLocaleString("default", { month: "long" }), [year, month]);
|
|
37107
|
+
const rangeLabel = React24.useMemo(() => {
|
|
37108
|
+
return isFullRange ? monthLabel : formatRangeLabel(normalizedRange, monthLabel);
|
|
37109
|
+
}, [isFullRange, normalizedRange, monthLabel]);
|
|
37110
|
+
const analysisMonthlyData = React24.useMemo(() => {
|
|
37111
|
+
if (analysisData) {
|
|
37112
|
+
return analysisData;
|
|
37113
|
+
}
|
|
37114
|
+
return filterDataByDateKeyRange(monthlyData, normalizedRange);
|
|
37115
|
+
}, [analysisData, monthlyData, normalizedRange]);
|
|
37116
|
+
const startDate = normalizedRange.startKey;
|
|
37117
|
+
const endDate = normalizedRange.endKey;
|
|
36774
37118
|
const {
|
|
36775
37119
|
chartData: idleReasonsChartData,
|
|
36776
37120
|
isLoading: idleReasonsLoading,
|
|
@@ -36791,7 +37135,7 @@ var LineMonthlyHistory = ({
|
|
|
36791
37135
|
}
|
|
36792
37136
|
) });
|
|
36793
37137
|
}
|
|
36794
|
-
const averages = (
|
|
37138
|
+
const averages = (analysisMonthlyData || []).reduce(
|
|
36795
37139
|
(acc, day) => {
|
|
36796
37140
|
const shiftData = getShiftData2(day, selectedShiftId);
|
|
36797
37141
|
if (!shiftData || shiftData?.avg_efficiency < 10) {
|
|
@@ -36851,7 +37195,15 @@ var LineMonthlyHistory = ({
|
|
|
36851
37195
|
)) });
|
|
36852
37196
|
};
|
|
36853
37197
|
const handleWorkspaceClick = (workspace) => {
|
|
36854
|
-
const
|
|
37198
|
+
const params = new URLSearchParams();
|
|
37199
|
+
params.set("tab", "monthly_history");
|
|
37200
|
+
params.set("month", month.toString());
|
|
37201
|
+
params.set("year", year.toString());
|
|
37202
|
+
if (!isFullRange) {
|
|
37203
|
+
params.set("rangeStart", normalizedRange.startKey);
|
|
37204
|
+
params.set("rangeEnd", normalizedRange.endKey);
|
|
37205
|
+
}
|
|
37206
|
+
const returnToUrl = `/kpis/${lineId}?${params.toString()}`;
|
|
36855
37207
|
if (onWorkspaceSelect) {
|
|
36856
37208
|
onWorkspaceSelect(workspace.workspace_uuid, {
|
|
36857
37209
|
sourceType: "lineMonthlyHistory",
|
|
@@ -36871,18 +37223,31 @@ var LineMonthlyHistory = ({
|
|
|
36871
37223
|
});
|
|
36872
37224
|
};
|
|
36873
37225
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("flex flex-col gap-2 min-h-0 overflow-y-auto pb-6", className), children: [
|
|
36874
|
-
/* @__PURE__ */ jsxRuntime.
|
|
36875
|
-
|
|
36876
|
-
{
|
|
36877
|
-
|
|
36878
|
-
|
|
36879
|
-
|
|
36880
|
-
|
|
36881
|
-
|
|
36882
|
-
|
|
36883
|
-
|
|
36884
|
-
|
|
36885
|
-
|
|
37226
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-3 sm:items-center mb-4", children: [
|
|
37227
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block" }),
|
|
37228
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: (availableShifts && availableShifts.length > 0 ? availableShifts : [
|
|
37229
|
+
{ id: 0, name: "Day Shift" },
|
|
37230
|
+
{ id: 1, name: "Night Shift" }
|
|
37231
|
+
]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
37232
|
+
"button",
|
|
37233
|
+
{
|
|
37234
|
+
onClick: () => onShiftChange?.(shift.id),
|
|
37235
|
+
className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShiftId === shift.id ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
|
|
37236
|
+
children: shift.name
|
|
37237
|
+
},
|
|
37238
|
+
shift.id
|
|
37239
|
+
)) }) }),
|
|
37240
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center sm:justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
37241
|
+
MonthlyRangeFilter_default,
|
|
37242
|
+
{
|
|
37243
|
+
month,
|
|
37244
|
+
year,
|
|
37245
|
+
timezone,
|
|
37246
|
+
value: normalizedRange,
|
|
37247
|
+
onChange: (nextRange) => onRangeChange?.(nextRange)
|
|
37248
|
+
}
|
|
37249
|
+
) })
|
|
37250
|
+
] }),
|
|
36886
37251
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6", children: [
|
|
36887
37252
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
|
|
36888
37253
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-center items-center mb-6 space-x-4", children: [
|
|
@@ -36945,6 +37310,8 @@ var LineMonthlyHistory = ({
|
|
|
36945
37310
|
year,
|
|
36946
37311
|
lineId,
|
|
36947
37312
|
selectedShiftId,
|
|
37313
|
+
rangeStart: normalizedRange.startKey,
|
|
37314
|
+
rangeEnd: normalizedRange.endKey,
|
|
36948
37315
|
onDateSelect: onCalendarDateSelect
|
|
36949
37316
|
}
|
|
36950
37317
|
)
|
|
@@ -36955,7 +37322,7 @@ var LineMonthlyHistory = ({
|
|
|
36955
37322
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-700 mb-1 text-center", children: "Efficiency" }),
|
|
36956
37323
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mb-4 text-center", children: [
|
|
36957
37324
|
"Cumulative for ",
|
|
36958
|
-
|
|
37325
|
+
rangeLabel
|
|
36959
37326
|
] }),
|
|
36960
37327
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-4xl font-bold text-center text-gray-900", children: [
|
|
36961
37328
|
avgEfficiency.toFixed(1),
|
|
@@ -36966,7 +37333,7 @@ var LineMonthlyHistory = ({
|
|
|
36966
37333
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-base font-semibold text-gray-700 mb-1 text-center", children: "Avg. Underperforming" }),
|
|
36967
37334
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-500 mb-4 text-center", children: [
|
|
36968
37335
|
"Cumulative for ",
|
|
36969
|
-
|
|
37336
|
+
rangeLabel
|
|
36970
37337
|
] }),
|
|
36971
37338
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-4xl font-bold text-center text-gray-900", children: [
|
|
36972
37339
|
avgUnderperforming.toFixed(1),
|
|
@@ -37045,9 +37412,12 @@ var LineMonthlyPdfGenerator = ({
|
|
|
37045
37412
|
lineId,
|
|
37046
37413
|
lineName,
|
|
37047
37414
|
monthlyData,
|
|
37415
|
+
analysisData,
|
|
37048
37416
|
underperformingWorkspaces,
|
|
37049
37417
|
selectedMonth,
|
|
37050
37418
|
selectedYear,
|
|
37419
|
+
rangeStart,
|
|
37420
|
+
rangeEnd,
|
|
37051
37421
|
selectedShiftId,
|
|
37052
37422
|
availableShifts,
|
|
37053
37423
|
className
|
|
@@ -37056,12 +37426,41 @@ var LineMonthlyPdfGenerator = ({
|
|
|
37056
37426
|
const generatePDF = async () => {
|
|
37057
37427
|
setIsGenerating(true);
|
|
37058
37428
|
try {
|
|
37429
|
+
const monthBounds = getMonthKeyBounds(selectedYear, selectedMonth);
|
|
37430
|
+
const requestedRange = {
|
|
37431
|
+
startKey: rangeStart || monthBounds.startKey,
|
|
37432
|
+
endKey: rangeEnd || monthBounds.endKey
|
|
37433
|
+
};
|
|
37434
|
+
const normalizedRange = normalizeDateKeyRange(
|
|
37435
|
+
requestedRange.startKey,
|
|
37436
|
+
requestedRange.endKey,
|
|
37437
|
+
monthBounds.startKey,
|
|
37438
|
+
monthBounds.endKey
|
|
37439
|
+
);
|
|
37440
|
+
const fullRange = isFullMonthRange(normalizedRange, selectedYear, selectedMonth);
|
|
37441
|
+
const reportStartDate = parseDateKeyToDate(normalizedRange.startKey);
|
|
37442
|
+
const reportEndDate = parseDateKeyToDate(normalizedRange.endKey);
|
|
37443
|
+
const reportStartStr = reportStartDate.toLocaleDateString("en-IN", {
|
|
37444
|
+
day: "2-digit",
|
|
37445
|
+
month: "short",
|
|
37446
|
+
year: "numeric",
|
|
37447
|
+
timeZone: "Asia/Kolkata"
|
|
37448
|
+
});
|
|
37449
|
+
const reportEndStr = reportEndDate.toLocaleDateString("en-IN", {
|
|
37450
|
+
day: "2-digit",
|
|
37451
|
+
month: "short",
|
|
37452
|
+
year: "numeric",
|
|
37453
|
+
timeZone: "Asia/Kolkata"
|
|
37454
|
+
});
|
|
37059
37455
|
trackCoreEvent("Line Monthly PDF Export Clicked", {
|
|
37060
37456
|
line_id: lineId,
|
|
37061
37457
|
line_name: lineName,
|
|
37062
37458
|
month: selectedMonth,
|
|
37063
37459
|
year: selectedYear,
|
|
37064
|
-
shift_id: selectedShiftId
|
|
37460
|
+
shift_id: selectedShiftId,
|
|
37461
|
+
range_start: normalizedRange.startKey,
|
|
37462
|
+
range_end: normalizedRange.endKey,
|
|
37463
|
+
is_full_month: fullRange
|
|
37065
37464
|
});
|
|
37066
37465
|
const doc = new jsPDF.jsPDF();
|
|
37067
37466
|
doc.setFontSize(14);
|
|
@@ -37094,28 +37493,15 @@ var LineMonthlyPdfGenerator = ({
|
|
|
37094
37493
|
const shiftType = getShiftDisplayName(selectedShiftId, availableShifts);
|
|
37095
37494
|
doc.text(`${monthName}`, 20, 55);
|
|
37096
37495
|
doc.text(`${shiftType}`, 20, 63);
|
|
37097
|
-
const startDate = new Date(selectedYear, selectedMonth, 1);
|
|
37098
|
-
const endDate = new Date(selectedYear, selectedMonth + 1, 0);
|
|
37099
|
-
const startDateStr = startDate.toLocaleDateString("en-IN", {
|
|
37100
|
-
day: "2-digit",
|
|
37101
|
-
month: "short",
|
|
37102
|
-
year: "numeric",
|
|
37103
|
-
timeZone: "Asia/Kolkata"
|
|
37104
|
-
});
|
|
37105
|
-
const endDateStr = endDate.toLocaleDateString("en-IN", {
|
|
37106
|
-
day: "2-digit",
|
|
37107
|
-
month: "short",
|
|
37108
|
-
year: "numeric",
|
|
37109
|
-
timeZone: "Asia/Kolkata"
|
|
37110
|
-
});
|
|
37111
37496
|
doc.setFontSize(12);
|
|
37112
37497
|
doc.setTextColor(80, 80, 80);
|
|
37113
|
-
doc.text(`Report Period: ${
|
|
37498
|
+
doc.text(`Report Period: ${reportStartStr} - ${reportEndStr}`, 20, 71);
|
|
37114
37499
|
doc.setTextColor(0, 0, 0);
|
|
37115
37500
|
doc.setDrawColor(180, 180, 180);
|
|
37116
37501
|
doc.setLineWidth(0.8);
|
|
37117
37502
|
doc.line(20, 85, 190, 85);
|
|
37118
|
-
const
|
|
37503
|
+
const reportData = analysisData ? analysisData : filterDataByDateKeyRange(monthlyData, normalizedRange);
|
|
37504
|
+
const validDays = reportData.filter((day) => {
|
|
37119
37505
|
const date = new Date(day.date);
|
|
37120
37506
|
return date.getMonth() === selectedMonth && date.getFullYear() === selectedYear;
|
|
37121
37507
|
});
|
|
@@ -38464,27 +38850,36 @@ var CustomTooltip2 = ({ active, payload, label }) => {
|
|
|
38464
38850
|
};
|
|
38465
38851
|
var WorkspaceMonthlyHistory = ({
|
|
38466
38852
|
data,
|
|
38853
|
+
analysisData,
|
|
38467
38854
|
month,
|
|
38468
38855
|
year,
|
|
38469
38856
|
workspaceId,
|
|
38857
|
+
rangeStart,
|
|
38858
|
+
rangeEnd,
|
|
38859
|
+
timezone,
|
|
38470
38860
|
selectedShiftId = 0,
|
|
38471
38861
|
onDateSelect,
|
|
38472
38862
|
onMonthNavigate,
|
|
38473
38863
|
onShiftChange,
|
|
38864
|
+
onRangeChange,
|
|
38474
38865
|
availableShifts,
|
|
38475
38866
|
monthlyDataLoading = false,
|
|
38476
38867
|
className = ""
|
|
38477
38868
|
}) => {
|
|
38478
|
-
const
|
|
38479
|
-
|
|
38480
|
-
|
|
38481
|
-
|
|
38482
|
-
|
|
38483
|
-
|
|
38484
|
-
|
|
38485
|
-
|
|
38486
|
-
|
|
38487
|
-
|
|
38869
|
+
const monthBounds = React24.useMemo(() => getMonthKeyBounds(year, month), [year, month]);
|
|
38870
|
+
const normalizedRange = React24.useMemo(() => {
|
|
38871
|
+
const startKey = rangeStart || monthBounds.startKey;
|
|
38872
|
+
const endKey = rangeEnd || monthBounds.endKey;
|
|
38873
|
+
return normalizeDateKeyRange(startKey, endKey, monthBounds.startKey, monthBounds.endKey);
|
|
38874
|
+
}, [rangeStart, rangeEnd, monthBounds.startKey, monthBounds.endKey]);
|
|
38875
|
+
const analysisMonthlyData = React24.useMemo(() => {
|
|
38876
|
+
if (analysisData) {
|
|
38877
|
+
return analysisData;
|
|
38878
|
+
}
|
|
38879
|
+
return filterDataByDateKeyRange(data, normalizedRange);
|
|
38880
|
+
}, [analysisData, data, normalizedRange]);
|
|
38881
|
+
const startDate = normalizedRange.startKey;
|
|
38882
|
+
const endDate = normalizedRange.endKey;
|
|
38488
38883
|
const {
|
|
38489
38884
|
chartData: idleReasonsChartData,
|
|
38490
38885
|
isLoading: idleReasonsLoading,
|
|
@@ -38494,19 +38889,25 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38494
38889
|
startDate,
|
|
38495
38890
|
endDate,
|
|
38496
38891
|
shiftId: selectedShiftId,
|
|
38497
|
-
enabled:
|
|
38892
|
+
enabled: analysisMonthlyData.length > 0
|
|
38498
38893
|
});
|
|
38499
38894
|
const hasRealData = (shift) => {
|
|
38500
38895
|
if (shift.hasData !== void 0) return shift.hasData;
|
|
38501
38896
|
return shift.efficiency > 0 || shift.output > 0 || shift.cycleTime > 0 || shift.pph > 0 || shift.idealOutput > 0 || shift.idleTime > 0;
|
|
38502
38897
|
};
|
|
38503
38898
|
const chartData = React24.useMemo(() => {
|
|
38504
|
-
const
|
|
38899
|
+
const rangeStartDate = parseDateKeyToDate(normalizedRange.startKey);
|
|
38900
|
+
const rangeEndDate = parseDateKeyToDate(normalizedRange.endKey);
|
|
38901
|
+
const dayNumbers = [];
|
|
38902
|
+
for (let d = new Date(rangeStartDate); d <= rangeEndDate; d.setDate(d.getDate() + 1)) {
|
|
38903
|
+
dayNumbers.push(d.getDate());
|
|
38904
|
+
}
|
|
38505
38905
|
const dailyData = [];
|
|
38506
38906
|
let maxOutput = 0;
|
|
38507
38907
|
let lastSetTarget = 0;
|
|
38508
|
-
for (let
|
|
38509
|
-
const
|
|
38908
|
+
for (let i = dayNumbers.length - 1; i >= 0; i--) {
|
|
38909
|
+
const day = dayNumbers[i];
|
|
38910
|
+
const dayData = analysisMonthlyData.find((d) => {
|
|
38510
38911
|
const date = new Date(d.date);
|
|
38511
38912
|
return date.getDate() === day;
|
|
38512
38913
|
});
|
|
@@ -38517,8 +38918,8 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38517
38918
|
break;
|
|
38518
38919
|
}
|
|
38519
38920
|
}
|
|
38520
|
-
for (
|
|
38521
|
-
const dayData =
|
|
38921
|
+
for (const day of dayNumbers) {
|
|
38922
|
+
const dayData = analysisMonthlyData.find((d) => {
|
|
38522
38923
|
const date = new Date(d.date);
|
|
38523
38924
|
return date.getDate() === day;
|
|
38524
38925
|
});
|
|
@@ -38544,7 +38945,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38544
38945
|
const calculatedMax = Math.max(maxOutput, lastSetTarget);
|
|
38545
38946
|
const yAxisMax = calculatedMax > 0 ? calculatedMax * 1.1 : 100;
|
|
38546
38947
|
return { data: dailyData, maxOutput, lastSetTarget, yAxisMax };
|
|
38547
|
-
}, [
|
|
38948
|
+
}, [analysisMonthlyData, normalizedRange.startKey, normalizedRange.endKey, selectedShiftId]);
|
|
38548
38949
|
const yAxisTicks = React24.useMemo(() => {
|
|
38549
38950
|
const max = chartData.yAxisMax;
|
|
38550
38951
|
const target = chartData.lastSetTarget;
|
|
@@ -38567,7 +38968,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38567
38968
|
return Array.from(new Set(ticks)).filter((v) => v >= 0 && v <= max).sort((a, b) => a - b);
|
|
38568
38969
|
}, [chartData.yAxisMax, chartData.lastSetTarget]);
|
|
38569
38970
|
const pieChartData = React24.useMemo(() => {
|
|
38570
|
-
const validShifts =
|
|
38971
|
+
const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
|
|
38571
38972
|
if (validShifts.length === 0) return [];
|
|
38572
38973
|
const totalIdleTime = validShifts.reduce((sum, shift) => sum + shift.idleTime, 0);
|
|
38573
38974
|
const totalShiftTime = validShifts.length * 8 * 3600;
|
|
@@ -38576,9 +38977,9 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38576
38977
|
{ name: "Productive", value: Math.round(activeTime / totalShiftTime * 100) },
|
|
38577
38978
|
{ name: "Idle", value: Math.round(totalIdleTime / totalShiftTime * 100) }
|
|
38578
38979
|
];
|
|
38579
|
-
}, [
|
|
38980
|
+
}, [analysisMonthlyData, selectedShiftId]);
|
|
38580
38981
|
const metrics2 = React24.useMemo(() => {
|
|
38581
|
-
const validShifts =
|
|
38982
|
+
const validShifts = analysisMonthlyData.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
|
|
38582
38983
|
if (validShifts.length === 0) return null;
|
|
38583
38984
|
const totalEfficiency = validShifts.reduce((sum, shift) => sum + shift.efficiency, 0);
|
|
38584
38985
|
const totalCycleTime = validShifts.reduce((sum, shift) => sum + shift.cycleTime, 0);
|
|
@@ -38598,7 +38999,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38598
38999
|
totalOutput,
|
|
38599
39000
|
avgIdleTime: Math.round(totalIdleTime / validShifts.length)
|
|
38600
39001
|
};
|
|
38601
|
-
}, [
|
|
39002
|
+
}, [analysisMonthlyData, selectedShiftId]);
|
|
38602
39003
|
const calendarData = React24.useMemo(() => {
|
|
38603
39004
|
const startOfMonth = new Date(year, month, 1);
|
|
38604
39005
|
const endOfMonth = new Date(year, month + 1, 0);
|
|
@@ -38638,7 +39039,7 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38638
39039
|
onShiftChange(shiftId);
|
|
38639
39040
|
}
|
|
38640
39041
|
}, [workspaceId, onShiftChange]);
|
|
38641
|
-
const chartKey = React24.useMemo(() => `${workspaceId}-${month}-${year}-${selectedShiftId}`, [workspaceId, month, year, selectedShiftId]);
|
|
39042
|
+
const chartKey = React24.useMemo(() => `${workspaceId}-${month}-${year}-${selectedShiftId}-${normalizedRange.startKey}-${normalizedRange.endKey}`, [workspaceId, month, year, selectedShiftId, normalizedRange.startKey, normalizedRange.endKey]);
|
|
38642
39043
|
if (monthlyDataLoading) {
|
|
38643
39044
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[calc(100vh-10rem)]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
38644
39045
|
OptifyeLogoLoader_default,
|
|
@@ -38649,18 +39050,31 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38649
39050
|
) });
|
|
38650
39051
|
}
|
|
38651
39052
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col gap-2 min-h-0 overflow-y-auto pb-6 ${className}`, children: [
|
|
38652
|
-
/* @__PURE__ */ jsxRuntime.
|
|
38653
|
-
|
|
38654
|
-
{
|
|
38655
|
-
|
|
38656
|
-
|
|
38657
|
-
|
|
38658
|
-
|
|
38659
|
-
|
|
38660
|
-
|
|
38661
|
-
|
|
38662
|
-
|
|
38663
|
-
|
|
39053
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-3 sm:items-center mb-4", children: [
|
|
39054
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "hidden sm:block" }),
|
|
39055
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-1 border border-gray-200 rounded-lg p-1 bg-gray-50", children: (availableShifts && availableShifts.length > 0 ? availableShifts : [
|
|
39056
|
+
{ id: 0, name: "Day Shift" },
|
|
39057
|
+
{ id: 1, name: "Night Shift" }
|
|
39058
|
+
]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
39059
|
+
"button",
|
|
39060
|
+
{
|
|
39061
|
+
onClick: () => handleShiftChange(shift.id),
|
|
39062
|
+
className: `px-4 py-2 text-sm font-medium rounded-md transition-all duration-200 ${selectedShiftId === shift.id ? "bg-white text-blue-600 shadow-sm ring-1 ring-gray-200" : "text-gray-600 hover:text-gray-900 hover:bg-gray-100"}`,
|
|
39063
|
+
children: shift.name
|
|
39064
|
+
},
|
|
39065
|
+
shift.id
|
|
39066
|
+
)) }) }),
|
|
39067
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center sm:justify-end", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
39068
|
+
MonthlyRangeFilter_default,
|
|
39069
|
+
{
|
|
39070
|
+
month,
|
|
39071
|
+
year,
|
|
39072
|
+
timezone,
|
|
39073
|
+
value: normalizedRange,
|
|
39074
|
+
onChange: (nextRange) => onRangeChange?.(nextRange)
|
|
39075
|
+
}
|
|
39076
|
+
) })
|
|
39077
|
+
] }),
|
|
38664
39078
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 lg:grid-cols-2 gap-6 mt-6", children: [
|
|
38665
39079
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-white rounded-xl shadow-sm border border-gray-100 p-6", children: [
|
|
38666
39080
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-center items-center mb-6 space-x-4", children: [
|
|
@@ -38728,6 +39142,10 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38728
39142
|
const hasData = shiftData ? hasRealData(shiftData) : false;
|
|
38729
39143
|
const isToday2 = (/* @__PURE__ */ new Date()).getDate() === dayNumber && (/* @__PURE__ */ new Date()).getMonth() === month && (/* @__PURE__ */ new Date()).getFullYear() === year;
|
|
38730
39144
|
const isFuture = new Date(year, month, dayNumber) > /* @__PURE__ */ new Date();
|
|
39145
|
+
const dateKey = `${year}-${String(month + 1).padStart(2, "0")}-${String(dayNumber).padStart(2, "0")}`;
|
|
39146
|
+
const showRange = normalizedRange.startKey && normalizedRange.endKey ? !(normalizedRange.startKey === monthBounds.startKey && normalizedRange.endKey === monthBounds.endKey) : false;
|
|
39147
|
+
const inRange = showRange ? dateKey >= normalizedRange.startKey && dateKey <= normalizedRange.endKey : false;
|
|
39148
|
+
const isRangeEdge = inRange && (dateKey === normalizedRange.startKey || dateKey === normalizedRange.endKey);
|
|
38731
39149
|
const getPerformanceColor = () => {
|
|
38732
39150
|
if (isFuture) return "bg-gray-200 dark:bg-gray-700";
|
|
38733
39151
|
if (!hasData || !shiftData) return "bg-gray-300 dark:bg-gray-600";
|
|
@@ -38743,8 +39161,14 @@ var WorkspaceMonthlyHistory = ({
|
|
|
38743
39161
|
rounded-lg h-full p-2 relative
|
|
38744
39162
|
${isToday2 ? "ring-2 ring-blue-500 dark:ring-blue-400 ring-offset-2 dark:ring-offset-gray-800 shadow-md" : ""}
|
|
38745
39163
|
`, children: [
|
|
39164
|
+
inRange && /* @__PURE__ */ jsxRuntime.jsx(
|
|
39165
|
+
"div",
|
|
39166
|
+
{
|
|
39167
|
+
className: `absolute inset-0 rounded-lg pointer-events-none ${isRangeEdge ? "ring-2 ring-blue-500" : "ring-2 ring-blue-200"}`
|
|
39168
|
+
}
|
|
39169
|
+
),
|
|
38746
39170
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `
|
|
38747
|
-
text-base font-medium ${hasData && !isFuture ? "text-white" : "text-gray-500"} flex items-center
|
|
39171
|
+
text-base font-medium ${hasData && !isFuture ? "text-white" : "text-gray-500"} flex items-center relative z-10
|
|
38748
39172
|
${isToday2 ? "bg-blue-500 dark:bg-blue-600 rounded-full w-7 h-7 justify-center" : ""}
|
|
38749
39173
|
`, children: dayNumber }),
|
|
38750
39174
|
!isFuture && hasData && shiftData && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 bg-black/80 rounded-lg p-2 text-white opacity-0 group-hover:opacity-100 transition-opacity", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs space-y-1", children: [
|
|
@@ -39288,8 +39712,11 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
39288
39712
|
workspaceId,
|
|
39289
39713
|
workspaceName,
|
|
39290
39714
|
monthlyData,
|
|
39715
|
+
analysisData,
|
|
39291
39716
|
selectedMonth,
|
|
39292
39717
|
selectedYear,
|
|
39718
|
+
rangeStart,
|
|
39719
|
+
rangeEnd,
|
|
39293
39720
|
selectedShiftId,
|
|
39294
39721
|
availableShifts,
|
|
39295
39722
|
className
|
|
@@ -39298,12 +39725,41 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
39298
39725
|
const generatePDF = async () => {
|
|
39299
39726
|
setIsGenerating(true);
|
|
39300
39727
|
try {
|
|
39728
|
+
const monthBounds = getMonthKeyBounds(selectedYear, selectedMonth);
|
|
39729
|
+
const requestedRange = {
|
|
39730
|
+
startKey: rangeStart || monthBounds.startKey,
|
|
39731
|
+
endKey: rangeEnd || monthBounds.endKey
|
|
39732
|
+
};
|
|
39733
|
+
const normalizedRange = normalizeDateKeyRange(
|
|
39734
|
+
requestedRange.startKey,
|
|
39735
|
+
requestedRange.endKey,
|
|
39736
|
+
monthBounds.startKey,
|
|
39737
|
+
monthBounds.endKey
|
|
39738
|
+
);
|
|
39739
|
+
const fullRange = isFullMonthRange(normalizedRange, selectedYear, selectedMonth);
|
|
39740
|
+
const reportStartDate = parseDateKeyToDate(normalizedRange.startKey);
|
|
39741
|
+
const reportEndDate = parseDateKeyToDate(normalizedRange.endKey);
|
|
39742
|
+
const reportStartStr = reportStartDate.toLocaleDateString("en-IN", {
|
|
39743
|
+
day: "2-digit",
|
|
39744
|
+
month: "short",
|
|
39745
|
+
year: "numeric",
|
|
39746
|
+
timeZone: "Asia/Kolkata"
|
|
39747
|
+
});
|
|
39748
|
+
const reportEndStr = reportEndDate.toLocaleDateString("en-IN", {
|
|
39749
|
+
day: "2-digit",
|
|
39750
|
+
month: "short",
|
|
39751
|
+
year: "numeric",
|
|
39752
|
+
timeZone: "Asia/Kolkata"
|
|
39753
|
+
});
|
|
39301
39754
|
trackCoreEvent("Workspace Monthly PDF Export Clicked", {
|
|
39302
39755
|
workspace_id: workspaceId,
|
|
39303
39756
|
workspace_name: workspaceName,
|
|
39304
39757
|
month: selectedMonth,
|
|
39305
39758
|
year: selectedYear,
|
|
39306
|
-
shift_id: selectedShiftId
|
|
39759
|
+
shift_id: selectedShiftId,
|
|
39760
|
+
range_start: normalizedRange.startKey,
|
|
39761
|
+
range_end: normalizedRange.endKey,
|
|
39762
|
+
is_full_month: fullRange
|
|
39307
39763
|
});
|
|
39308
39764
|
const doc = new jsPDF.jsPDF();
|
|
39309
39765
|
doc.setFontSize(14);
|
|
@@ -39340,28 +39796,15 @@ var WorkspaceMonthlyPdfGenerator = ({
|
|
|
39340
39796
|
const shiftType = getShiftDisplayName2(selectedShiftId, availableShifts);
|
|
39341
39797
|
doc.text(`${monthName}`, 20, 65);
|
|
39342
39798
|
doc.text(`${shiftType}`, 20, 73);
|
|
39343
|
-
const startDate = new Date(selectedYear, selectedMonth, 1);
|
|
39344
|
-
const endDate = new Date(selectedYear, selectedMonth + 1, 0);
|
|
39345
|
-
const startDateStr = startDate.toLocaleDateString("en-IN", {
|
|
39346
|
-
day: "2-digit",
|
|
39347
|
-
month: "short",
|
|
39348
|
-
year: "numeric",
|
|
39349
|
-
timeZone: "Asia/Kolkata"
|
|
39350
|
-
});
|
|
39351
|
-
const endDateStr = endDate.toLocaleDateString("en-IN", {
|
|
39352
|
-
day: "2-digit",
|
|
39353
|
-
month: "short",
|
|
39354
|
-
year: "numeric",
|
|
39355
|
-
timeZone: "Asia/Kolkata"
|
|
39356
|
-
});
|
|
39357
39799
|
doc.setFontSize(12);
|
|
39358
39800
|
doc.setTextColor(80, 80, 80);
|
|
39359
|
-
doc.text(`Report Period: ${
|
|
39801
|
+
doc.text(`Report Period: ${reportStartStr} - ${reportEndStr}`, 20, 81);
|
|
39360
39802
|
doc.setTextColor(0, 0, 0);
|
|
39361
39803
|
doc.setDrawColor(180, 180, 180);
|
|
39362
39804
|
doc.setLineWidth(0.8);
|
|
39363
39805
|
doc.line(20, 90, 190, 90);
|
|
39364
|
-
const
|
|
39806
|
+
const reportData = analysisData ? analysisData : filterDataByDateKeyRange(monthlyData, normalizedRange);
|
|
39807
|
+
const validDays = reportData.filter((day) => {
|
|
39365
39808
|
const date = new Date(day.date);
|
|
39366
39809
|
return date.getMonth() === selectedMonth && date.getFullYear() === selectedYear;
|
|
39367
39810
|
});
|
|
@@ -50130,6 +50573,8 @@ var KPIDetailView = ({
|
|
|
50130
50573
|
tab: urlTab,
|
|
50131
50574
|
month: urlMonth,
|
|
50132
50575
|
year: urlYear,
|
|
50576
|
+
rangeStart: urlRangeStart,
|
|
50577
|
+
rangeEnd: urlRangeEnd,
|
|
50133
50578
|
companyId,
|
|
50134
50579
|
navigate,
|
|
50135
50580
|
className,
|
|
@@ -50156,6 +50601,9 @@ var KPIDetailView = ({
|
|
|
50156
50601
|
}
|
|
50157
50602
|
return (/* @__PURE__ */ new Date()).getFullYear();
|
|
50158
50603
|
});
|
|
50604
|
+
const monthBounds = React24.useMemo(() => getMonthKeyBounds(currentYear, currentMonth), [currentYear, currentMonth]);
|
|
50605
|
+
const [rangeStart, setRangeStart] = React24.useState(monthBounds.startKey);
|
|
50606
|
+
const [rangeEnd, setRangeEnd] = React24.useState(monthBounds.endKey);
|
|
50159
50607
|
const [monthlyData, setMonthlyData] = React24.useState([]);
|
|
50160
50608
|
const [underperformingWorkspaces, setUnderperformingWorkspaces] = React24.useState({});
|
|
50161
50609
|
const [selectedShiftId, setSelectedShiftId] = React24.useState(0);
|
|
@@ -50172,6 +50620,18 @@ var KPIDetailView = ({
|
|
|
50172
50620
|
}
|
|
50173
50621
|
return void 0;
|
|
50174
50622
|
}, [urlShift]);
|
|
50623
|
+
const range = React24.useMemo(() => ({ startKey: rangeStart, endKey: rangeEnd }), [rangeStart, rangeEnd]);
|
|
50624
|
+
const isFullRange = React24.useMemo(() => isFullMonthRange(range, currentYear, currentMonth), [range, currentYear, currentMonth]);
|
|
50625
|
+
React24.useEffect(() => {
|
|
50626
|
+
const normalized = normalizeDateKeyRange(
|
|
50627
|
+
typeof urlRangeStart === "string" ? urlRangeStart : monthBounds.startKey,
|
|
50628
|
+
typeof urlRangeEnd === "string" ? urlRangeEnd : monthBounds.endKey,
|
|
50629
|
+
monthBounds.startKey,
|
|
50630
|
+
monthBounds.endKey
|
|
50631
|
+
);
|
|
50632
|
+
setRangeStart(normalized.startKey);
|
|
50633
|
+
setRangeEnd(normalized.endKey);
|
|
50634
|
+
}, [urlRangeStart, urlRangeEnd, monthBounds.startKey, monthBounds.endKey]);
|
|
50175
50635
|
const supabase = useSupabase();
|
|
50176
50636
|
const dashboardConfig = useDashboardConfig();
|
|
50177
50637
|
const configuredTimezone = timezone || dashboardConfig.dateTimeConfig?.defaultTimezone || "UTC";
|
|
@@ -50271,8 +50731,10 @@ var KPIDetailView = ({
|
|
|
50271
50731
|
lineId,
|
|
50272
50732
|
currentMonth,
|
|
50273
50733
|
currentYear,
|
|
50274
|
-
shiftConfig?.shifts?.map((s) => s.shiftId)
|
|
50734
|
+
shiftConfig?.shifts?.map((s) => s.shiftId),
|
|
50275
50735
|
// Pass dynamic shift IDs
|
|
50736
|
+
isFullRange ? void 0 : range.startKey,
|
|
50737
|
+
isFullRange ? void 0 : range.endKey
|
|
50276
50738
|
)
|
|
50277
50739
|
]).then(([monthlyMetrics, underperformingData]) => {
|
|
50278
50740
|
console.log("Fetched monthly metrics data:", monthlyMetrics);
|
|
@@ -50334,7 +50796,10 @@ var KPIDetailView = ({
|
|
|
50334
50796
|
setMonthlyDataLoading(false);
|
|
50335
50797
|
});
|
|
50336
50798
|
}
|
|
50337
|
-
}, [activeTab, lineId, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig]);
|
|
50799
|
+
}, [activeTab, lineId, currentMonth, currentYear, supabase, dashboardConfig, shiftConfig, range.startKey, range.endKey, isFullRange]);
|
|
50800
|
+
const analysisMonthlyData = React24.useMemo(() => {
|
|
50801
|
+
return filterDataByDateKeyRange(monthlyData, range);
|
|
50802
|
+
}, [monthlyData, range]);
|
|
50338
50803
|
const lineInfo = React24.useMemo(() => {
|
|
50339
50804
|
if (!metrics2 || !lineDetails || !lineDetails.factory) {
|
|
50340
50805
|
return null;
|
|
@@ -50561,6 +51026,21 @@ var KPIDetailView = ({
|
|
|
50561
51026
|
const url = `/kpis/${lineId}?tab=overview&month=${currentMonth}&year=${currentYear}`;
|
|
50562
51027
|
handleNavigate(url, { shallow: true });
|
|
50563
51028
|
}, [lineId, currentMonth, currentYear, handleNavigate]);
|
|
51029
|
+
const buildMonthlyHistoryUrl = React24.useCallback((month, year, rangeOverride) => {
|
|
51030
|
+
const bounds = getMonthKeyBounds(year, month);
|
|
51031
|
+
const activeRange = rangeOverride || range;
|
|
51032
|
+
const normalized = normalizeDateKeyRange(activeRange.startKey, activeRange.endKey, bounds.startKey, bounds.endKey);
|
|
51033
|
+
const fullRange = isFullMonthRange(normalized, year, month);
|
|
51034
|
+
const params = new URLSearchParams();
|
|
51035
|
+
params.set("tab", "monthly_history");
|
|
51036
|
+
params.set("month", month.toString());
|
|
51037
|
+
params.set("year", year.toString());
|
|
51038
|
+
if (!fullRange) {
|
|
51039
|
+
params.set("rangeStart", normalized.startKey);
|
|
51040
|
+
params.set("rangeEnd", normalized.endKey);
|
|
51041
|
+
}
|
|
51042
|
+
return `/kpis/${lineId}?${params.toString()}`;
|
|
51043
|
+
}, [lineId, range]);
|
|
50564
51044
|
const handleMonthlyHistoryClick = React24.useCallback(() => {
|
|
50565
51045
|
trackCoreEvent("Monthly History Viewed", {
|
|
50566
51046
|
source: "line_kpi",
|
|
@@ -50568,9 +51048,9 @@ var KPIDetailView = ({
|
|
|
50568
51048
|
line_name: lineInfo?.line_name
|
|
50569
51049
|
});
|
|
50570
51050
|
setActiveTab("monthly_history");
|
|
50571
|
-
const url =
|
|
51051
|
+
const url = buildMonthlyHistoryUrl(currentMonth, currentYear);
|
|
50572
51052
|
handleNavigate(url, { shallow: true });
|
|
50573
|
-
}, [lineInfo,
|
|
51053
|
+
}, [lineInfo, currentMonth, currentYear, handleNavigate, buildMonthlyHistoryUrl]);
|
|
50574
51054
|
const handleBackClick = React24.useCallback(() => {
|
|
50575
51055
|
if (!urlDate && !urlShift) {
|
|
50576
51056
|
trackCoreEvent("Dashboard Viewed", {
|
|
@@ -50584,10 +51064,16 @@ var KPIDetailView = ({
|
|
|
50584
51064
|
} else if (backLinkUrl) {
|
|
50585
51065
|
handleNavigate(backLinkUrl);
|
|
50586
51066
|
} else {
|
|
50587
|
-
const
|
|
51067
|
+
const targetMonth = urlMonth && typeof urlMonth === "string" ? parseInt(urlMonth, 10) : currentMonth;
|
|
51068
|
+
const targetYear = urlYear && typeof urlYear === "string" ? parseInt(urlYear, 10) : currentYear;
|
|
51069
|
+
const backRange = {
|
|
51070
|
+
startKey: typeof urlRangeStart === "string" ? urlRangeStart : range.startKey,
|
|
51071
|
+
endKey: typeof urlRangeEnd === "string" ? urlRangeEnd : range.endKey
|
|
51072
|
+
};
|
|
51073
|
+
const backUrl = urlDate || urlShift ? buildMonthlyHistoryUrl(targetMonth, targetYear, backRange) : "/kpis";
|
|
50588
51074
|
handleNavigate(backUrl);
|
|
50589
51075
|
}
|
|
50590
|
-
}, [urlDate, urlShift, lineInfo, onBackClick, backLinkUrl, handleNavigate, urlMonth, urlYear,
|
|
51076
|
+
}, [urlDate, urlShift, lineInfo, onBackClick, backLinkUrl, handleNavigate, urlMonth, urlYear, currentMonth, currentYear, urlRangeStart, urlRangeEnd, range, buildMonthlyHistoryUrl]);
|
|
50591
51077
|
const handleCalendarMonthChange = React24.useCallback((newMonth, newYear) => {
|
|
50592
51078
|
let validMonth = newMonth;
|
|
50593
51079
|
let validYear = newYear;
|
|
@@ -50608,10 +51094,18 @@ var KPIDetailView = ({
|
|
|
50608
51094
|
if (validYear > istYear || validYear === istYear && validMonth > istMonth) {
|
|
50609
51095
|
return;
|
|
50610
51096
|
}
|
|
51097
|
+
const nextBounds = getMonthKeyBounds(validYear, validMonth);
|
|
50611
51098
|
setCurrentMonth(validMonth);
|
|
50612
51099
|
setCurrentYear(validYear);
|
|
50613
|
-
|
|
50614
|
-
|
|
51100
|
+
setRangeStart(nextBounds.startKey);
|
|
51101
|
+
setRangeEnd(nextBounds.endKey);
|
|
51102
|
+
handleNavigate(buildMonthlyHistoryUrl(validMonth, validYear, nextBounds), { shallow: true });
|
|
51103
|
+
}, [configuredTimezone, handleNavigate, lineId, buildMonthlyHistoryUrl]);
|
|
51104
|
+
const handleRangeChange = React24.useCallback((nextRange) => {
|
|
51105
|
+
setRangeStart(nextRange.startKey);
|
|
51106
|
+
setRangeEnd(nextRange.endKey);
|
|
51107
|
+
handleNavigate(buildMonthlyHistoryUrl(currentMonth, currentYear, nextRange), { shallow: true });
|
|
51108
|
+
}, [currentMonth, currentYear, handleNavigate, buildMonthlyHistoryUrl]);
|
|
50615
51109
|
if ((lineMetricsLoading || workspacesLoading || isShiftConfigLoading) && !lineInfo && !metrics2) {
|
|
50616
51110
|
return /* @__PURE__ */ jsxRuntime.jsx(LoadingPage, { message: "Loading line metrics..." });
|
|
50617
51111
|
}
|
|
@@ -50792,9 +51286,12 @@ var KPIDetailView = ({
|
|
|
50792
51286
|
lineId,
|
|
50793
51287
|
lineName: lineInfo?.line_name || "Line",
|
|
50794
51288
|
monthlyData,
|
|
51289
|
+
analysisData: analysisMonthlyData,
|
|
50795
51290
|
underperformingWorkspaces,
|
|
50796
51291
|
selectedMonth: currentMonth,
|
|
50797
51292
|
selectedYear: currentYear,
|
|
51293
|
+
rangeStart,
|
|
51294
|
+
rangeEnd,
|
|
50798
51295
|
selectedShiftId
|
|
50799
51296
|
}
|
|
50800
51297
|
)
|
|
@@ -50843,10 +51340,15 @@ var KPIDetailView = ({
|
|
|
50843
51340
|
lineId,
|
|
50844
51341
|
underperformingWorkspaces,
|
|
50845
51342
|
monthlyData,
|
|
51343
|
+
analysisData: analysisMonthlyData,
|
|
50846
51344
|
month: currentMonth,
|
|
50847
51345
|
year: currentYear,
|
|
51346
|
+
rangeStart,
|
|
51347
|
+
rangeEnd,
|
|
51348
|
+
timezone: configuredTimezone,
|
|
50848
51349
|
selectedShiftId,
|
|
50849
51350
|
onShiftChange: setSelectedShiftId,
|
|
51351
|
+
onRangeChange: handleRangeChange,
|
|
50850
51352
|
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
50851
51353
|
onCalendarMonthChange: (date) => handleCalendarMonthChange(date.getMonth(), date.getFullYear()),
|
|
50852
51354
|
isLoading: monthlyDataLoading
|
|
@@ -54555,6 +55057,8 @@ var WorkspaceDetailView = ({
|
|
|
54555
55057
|
lineId,
|
|
54556
55058
|
defaultTab,
|
|
54557
55059
|
returnUrl,
|
|
55060
|
+
rangeStart: urlRangeStart,
|
|
55061
|
+
rangeEnd: urlRangeEnd,
|
|
54558
55062
|
lineIds = { line1: "", line2: "" },
|
|
54559
55063
|
selectedLineId,
|
|
54560
55064
|
onNavigate,
|
|
@@ -54581,12 +55085,27 @@ var WorkspaceDetailView = ({
|
|
|
54581
55085
|
const today = new Date((/* @__PURE__ */ new Date()).toLocaleString("en-US", { timeZone: timezone }));
|
|
54582
55086
|
const [selectedMonth, setSelectedMonth] = React24.useState(today.getMonth());
|
|
54583
55087
|
const [selectedYear, setSelectedYear] = React24.useState(today.getFullYear());
|
|
55088
|
+
const monthBounds = React24.useMemo(() => getMonthKeyBounds(selectedYear, selectedMonth), [selectedYear, selectedMonth]);
|
|
55089
|
+
const [rangeStart, setRangeStart] = React24.useState(monthBounds.startKey);
|
|
55090
|
+
const [rangeEnd, setRangeEnd] = React24.useState(monthBounds.endKey);
|
|
54584
55091
|
const [selectedShift, setSelectedShift] = React24.useState(0);
|
|
54585
55092
|
React24.useEffect(() => {
|
|
54586
55093
|
if (parsedShiftId !== void 0) {
|
|
54587
55094
|
setSelectedShift(parsedShiftId);
|
|
54588
55095
|
}
|
|
54589
55096
|
}, [parsedShiftId]);
|
|
55097
|
+
const range = React24.useMemo(() => ({ startKey: rangeStart, endKey: rangeEnd }), [rangeStart, rangeEnd]);
|
|
55098
|
+
const isFullRange = React24.useMemo(() => isFullMonthRange(range, selectedYear, selectedMonth), [range, selectedYear, selectedMonth]);
|
|
55099
|
+
React24.useEffect(() => {
|
|
55100
|
+
const normalized = normalizeDateKeyRange(
|
|
55101
|
+
typeof urlRangeStart === "string" ? urlRangeStart : monthBounds.startKey,
|
|
55102
|
+
typeof urlRangeEnd === "string" ? urlRangeEnd : monthBounds.endKey,
|
|
55103
|
+
monthBounds.startKey,
|
|
55104
|
+
monthBounds.endKey
|
|
55105
|
+
);
|
|
55106
|
+
setRangeStart(normalized.startKey);
|
|
55107
|
+
setRangeEnd(normalized.endKey);
|
|
55108
|
+
}, [urlRangeStart, urlRangeEnd, monthBounds.startKey, monthBounds.endKey]);
|
|
54590
55109
|
const isHistoricView = Boolean(date && parsedShiftId !== void 0);
|
|
54591
55110
|
const initialTab = getInitialTab(sourceType, defaultTab, fromMonthly, date);
|
|
54592
55111
|
const [activeTab, setActiveTab] = React24.useState(initialTab);
|
|
@@ -54809,6 +55328,9 @@ var WorkspaceDetailView = ({
|
|
|
54809
55328
|
});
|
|
54810
55329
|
}
|
|
54811
55330
|
}, [activeTab, workspaceId, selectedMonth, selectedYear, supabase, dashboardConfig, handleMonthlyDataLoaded]);
|
|
55331
|
+
const analysisMonthlyData = React24.useMemo(() => {
|
|
55332
|
+
return filterDataByDateKeyRange(monthlyData, range);
|
|
55333
|
+
}, [monthlyData, range]);
|
|
54812
55334
|
const formattedWorkspaceName = displayName || formatWorkspaceName3(workspace?.workspace_name || "", effectiveLineId);
|
|
54813
55335
|
const shouldShowCycleTimeChart = showCycleTimeChart ?? formattedWorkspaceName.startsWith("FINAL ASSY");
|
|
54814
55336
|
const handleBackNavigation = () => {
|
|
@@ -54830,6 +55352,10 @@ var WorkspaceDetailView = ({
|
|
|
54830
55352
|
const params = new URLSearchParams();
|
|
54831
55353
|
params.set("fromMonthly", "true");
|
|
54832
55354
|
params.set("shift", selectedShift.toString());
|
|
55355
|
+
if (!isFullRange) {
|
|
55356
|
+
params.set("rangeStart", range.startKey);
|
|
55357
|
+
params.set("rangeEnd", range.endKey);
|
|
55358
|
+
}
|
|
54833
55359
|
if (effectiveLineId) {
|
|
54834
55360
|
params.set("lineId", effectiveLineId);
|
|
54835
55361
|
}
|
|
@@ -54842,6 +55368,10 @@ var WorkspaceDetailView = ({
|
|
|
54842
55368
|
const params = new URLSearchParams();
|
|
54843
55369
|
params.set("fromMonthly", "true");
|
|
54844
55370
|
params.set("shift", selectedShift.toString());
|
|
55371
|
+
if (!isFullRange) {
|
|
55372
|
+
params.set("rangeStart", range.startKey);
|
|
55373
|
+
params.set("rangeEnd", range.endKey);
|
|
55374
|
+
}
|
|
54845
55375
|
if (effectiveLineId) {
|
|
54846
55376
|
params.set("lineId", effectiveLineId);
|
|
54847
55377
|
}
|
|
@@ -55111,8 +55641,11 @@ var WorkspaceDetailView = ({
|
|
|
55111
55641
|
workspaceId,
|
|
55112
55642
|
workspaceName: workspace?.workspace_name || "",
|
|
55113
55643
|
monthlyData,
|
|
55644
|
+
analysisData: analysisMonthlyData,
|
|
55114
55645
|
selectedMonth,
|
|
55115
55646
|
selectedYear,
|
|
55647
|
+
rangeStart,
|
|
55648
|
+
rangeEnd,
|
|
55116
55649
|
selectedShiftId: selectedShift
|
|
55117
55650
|
}
|
|
55118
55651
|
) })
|
|
@@ -55385,10 +55918,14 @@ var WorkspaceDetailView = ({
|
|
|
55385
55918
|
WorkspaceMonthlyHistory,
|
|
55386
55919
|
{
|
|
55387
55920
|
data: monthlyData,
|
|
55921
|
+
analysisData: analysisMonthlyData,
|
|
55388
55922
|
month: selectedMonth,
|
|
55389
55923
|
year: selectedYear,
|
|
55390
55924
|
workspaceId,
|
|
55391
55925
|
selectedShiftId: selectedShift,
|
|
55926
|
+
rangeStart,
|
|
55927
|
+
rangeEnd,
|
|
55928
|
+
timezone,
|
|
55392
55929
|
monthlyDataLoading,
|
|
55393
55930
|
availableShifts: shiftConfig?.shifts?.map((s) => ({ id: s.shiftId, name: s.shiftName })),
|
|
55394
55931
|
onDateSelect: (selectedDate, shiftId) => {
|
|
@@ -55399,6 +55936,10 @@ var WorkspaceDetailView = ({
|
|
|
55399
55936
|
params.set("date", selectedDate);
|
|
55400
55937
|
params.set("shift", shiftId.toString());
|
|
55401
55938
|
params.set("fromMonthly", "true");
|
|
55939
|
+
if (!isFullRange) {
|
|
55940
|
+
params.set("rangeStart", range.startKey);
|
|
55941
|
+
params.set("rangeEnd", range.endKey);
|
|
55942
|
+
}
|
|
55402
55943
|
if (effectiveLineId) {
|
|
55403
55944
|
params.set("lineId", effectiveLineId);
|
|
55404
55945
|
}
|
|
@@ -55408,8 +55949,15 @@ var WorkspaceDetailView = ({
|
|
|
55408
55949
|
onMonthNavigate: (newMonth, newYear) => {
|
|
55409
55950
|
setSelectedMonth(newMonth);
|
|
55410
55951
|
setSelectedYear(newYear);
|
|
55952
|
+
const nextBounds = getMonthKeyBounds(newYear, newMonth);
|
|
55953
|
+
setRangeStart(nextBounds.startKey);
|
|
55954
|
+
setRangeEnd(nextBounds.endKey);
|
|
55411
55955
|
},
|
|
55412
55956
|
onShiftChange: setSelectedShift,
|
|
55957
|
+
onRangeChange: (nextRange) => {
|
|
55958
|
+
setRangeStart(nextRange.startKey);
|
|
55959
|
+
setRangeEnd(nextRange.endKey);
|
|
55960
|
+
},
|
|
55413
55961
|
className: "w-full"
|
|
55414
55962
|
}
|
|
55415
55963
|
)
|
|
@@ -58099,12 +58647,13 @@ function shuffleArray(array) {
|
|
|
58099
58647
|
}
|
|
58100
58648
|
return shuffled;
|
|
58101
58649
|
}
|
|
58102
|
-
var
|
|
58103
|
-
|
|
58104
|
-
|
|
58105
|
-
|
|
58106
|
-
|
|
58107
|
-
|
|
58650
|
+
var buildInitials = (name) => {
|
|
58651
|
+
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
58652
|
+
if (parts.length === 0) return "NA";
|
|
58653
|
+
const first = parts[0]?.[0] || "";
|
|
58654
|
+
const second = parts.length > 1 ? parts[1]?.[0] || "" : "";
|
|
58655
|
+
return `${first}${second}`.toUpperCase();
|
|
58656
|
+
};
|
|
58108
58657
|
var ClipVideoCarousel = ({ clips, clipsService }) => {
|
|
58109
58658
|
const [currentIndex, setCurrentIndex] = React24.useState(0);
|
|
58110
58659
|
const [videos, setVideos] = React24.useState([]);
|
|
@@ -58353,6 +58902,77 @@ var TableEvidence = ({ columns, rows }) => {
|
|
|
58353
58902
|
/* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rows.map((row, idx) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "border-b border-gray-100 last:border-b-0", children: columns.map((col) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-gray-700 whitespace-nowrap", children: formatValue(row[col]) }, col)) }, idx)) })
|
|
58354
58903
|
] }) }) });
|
|
58355
58904
|
};
|
|
58905
|
+
var EvidenceCarousel = ({ evidence, clipsService }) => {
|
|
58906
|
+
const [currentIndex, setCurrentIndex] = React24.useState(0);
|
|
58907
|
+
const nextEvidence = () => {
|
|
58908
|
+
setCurrentIndex((prev) => (prev + 1) % evidence.length);
|
|
58909
|
+
};
|
|
58910
|
+
const prevEvidence = () => {
|
|
58911
|
+
setCurrentIndex((prev) => (prev - 1 + evidence.length) % evidence.length);
|
|
58912
|
+
};
|
|
58913
|
+
const ev = evidence[currentIndex];
|
|
58914
|
+
const isVideo = ev.type === "video_gallery";
|
|
58915
|
+
const isChart = ev.type === "bar_chart" || ev.type === "timeseries" || ev.type === "pie_chart";
|
|
58916
|
+
const title = ev.title || "Evidence";
|
|
58917
|
+
const clips = Array.isArray(ev.clips) ? ev.clips : [];
|
|
58918
|
+
const clipCount = clips.length;
|
|
58919
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
58920
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-2", children: [
|
|
58921
|
+
/* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "text-xs font-semibold text-gray-500 uppercase tracking-wider flex items-center gap-2", children: [
|
|
58922
|
+
isVideo ? /* @__PURE__ */ jsxRuntime.jsx(outline.PlayCircleIcon, { className: "w-4 h-4" }) : isChart ? /* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: "w-4 h-4" }),
|
|
58923
|
+
title
|
|
58924
|
+
] }),
|
|
58925
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
58926
|
+
isVideo && clipCount > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-medium text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded", children: [
|
|
58927
|
+
clipCount,
|
|
58928
|
+
" clips"
|
|
58929
|
+
] }),
|
|
58930
|
+
evidence.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-medium text-gray-500 bg-gray-200 px-1.5 py-0.5 rounded", children: [
|
|
58931
|
+
currentIndex + 1,
|
|
58932
|
+
" / ",
|
|
58933
|
+
evidence.length
|
|
58934
|
+
] })
|
|
58935
|
+
] })
|
|
58936
|
+
] }),
|
|
58937
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
58938
|
+
ev.type === "video_gallery" && /* @__PURE__ */ jsxRuntime.jsx(ClipVideoCarousel, { clips, clipsService }),
|
|
58939
|
+
ev.type === "bar_chart" && (Array.isArray(ev.x) && Array.isArray(ev.y) || Array.isArray(ev.data) && Array.isArray(ev.series)) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
58940
|
+
BarChartEvidence,
|
|
58941
|
+
{
|
|
58942
|
+
x: ev.x,
|
|
58943
|
+
y: ev.y,
|
|
58944
|
+
data: ev.data,
|
|
58945
|
+
series: ev.series,
|
|
58946
|
+
unit: ev.unit,
|
|
58947
|
+
referenceLines: Array.isArray(ev.reference_lines) ? ev.reference_lines : void 0
|
|
58948
|
+
}
|
|
58949
|
+
),
|
|
58950
|
+
ev.type === "pie_chart" && Array.isArray(ev.data) && /* @__PURE__ */ jsxRuntime.jsx(PieChartEvidence, { data: ev.data }),
|
|
58951
|
+
ev.type === "timeseries" && Array.isArray(ev.x) && Array.isArray(ev.y) && /* @__PURE__ */ jsxRuntime.jsx(LineChartEvidence, { x: ev.x, y: ev.y, unit: ev.unit }),
|
|
58952
|
+
ev.type === "table" && Array.isArray(ev.columns) && Array.isArray(ev.rows) && /* @__PURE__ */ jsxRuntime.jsx(TableEvidence, { columns: ev.columns, rows: ev.rows })
|
|
58953
|
+
] }),
|
|
58954
|
+
evidence.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
58955
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
58956
|
+
"button",
|
|
58957
|
+
{
|
|
58958
|
+
onClick: prevEvidence,
|
|
58959
|
+
className: "absolute left-0 top-1/2 -translate-y-1/2 -translate-x-3 p-1.5 rounded-full bg-white border border-gray-200 shadow-sm hover:bg-gray-50 text-gray-600 transition-all z-10",
|
|
58960
|
+
"aria-label": "Previous evidence",
|
|
58961
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronLeftIcon, { className: "w-4 h-4" })
|
|
58962
|
+
}
|
|
58963
|
+
),
|
|
58964
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
58965
|
+
"button",
|
|
58966
|
+
{
|
|
58967
|
+
onClick: nextEvidence,
|
|
58968
|
+
className: "absolute right-0 top-1/2 -translate-y-1/2 translate-x-3 p-1.5 rounded-full bg-white border border-gray-200 shadow-sm hover:bg-gray-50 text-gray-600 transition-all z-10",
|
|
58969
|
+
"aria-label": "Next evidence",
|
|
58970
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(outline.ChevronRightIcon, { className: "w-4 h-4" })
|
|
58971
|
+
}
|
|
58972
|
+
)
|
|
58973
|
+
] })
|
|
58974
|
+
] });
|
|
58975
|
+
};
|
|
58356
58976
|
var ImprovementCenterView = () => {
|
|
58357
58977
|
const { navigate } = useNavigation();
|
|
58358
58978
|
const supabase = useSupabase();
|
|
@@ -58360,12 +58980,16 @@ var ImprovementCenterView = () => {
|
|
|
58360
58980
|
const dashboardConfig = useDashboardConfig();
|
|
58361
58981
|
const entityConfig = useEntityConfig();
|
|
58362
58982
|
const [currentDate, setCurrentDate] = React24.useState(/* @__PURE__ */ new Date());
|
|
58363
|
-
const [selectedCategory, setSelectedCategory] = React24.useState("all");
|
|
58364
58983
|
const [selectedLineId, setSelectedLineId] = React24.useState("all");
|
|
58365
58984
|
const [selectedStatus, setSelectedStatus] = React24.useState("all");
|
|
58985
|
+
const [selectedShift, setSelectedShift] = React24.useState("all");
|
|
58986
|
+
const [selectedWeeksRange, setSelectedWeeksRange] = React24.useState("all");
|
|
58987
|
+
const [selectedMemberId, setSelectedMemberId] = React24.useState("all");
|
|
58366
58988
|
const [recommendations, setRecommendations] = React24.useState([]);
|
|
58367
58989
|
const [isLoading, setIsLoading] = React24.useState(false);
|
|
58368
58990
|
const [loadError, setLoadError] = React24.useState(null);
|
|
58991
|
+
const [teamMembers, setTeamMembers] = React24.useState([]);
|
|
58992
|
+
const [companyLines, setCompanyLines] = React24.useState([]);
|
|
58369
58993
|
const computeWeeksOpen = (firstSeenAt) => {
|
|
58370
58994
|
if (!firstSeenAt) return void 0;
|
|
58371
58995
|
const firstSeen = new Date(firstSeenAt);
|
|
@@ -58378,11 +59002,50 @@ var ImprovementCenterView = () => {
|
|
|
58378
59002
|
return entityConfig.lines || entityConfig.lineNames || {};
|
|
58379
59003
|
}, [entityConfig.lines, entityConfig.lineNames]);
|
|
58380
59004
|
const configuredLineIds = React24.useMemo(() => Object.keys(configuredLines), [configuredLines]);
|
|
58381
|
-
const
|
|
59005
|
+
const companyLineIds = React24.useMemo(() => companyLines.map((line) => line.id), [companyLines]);
|
|
59006
|
+
const assignedLineIds = React24.useMemo(() => {
|
|
59007
|
+
if (!user) return [];
|
|
59008
|
+
if (user.role_level !== "supervisor") return [];
|
|
59009
|
+
const lines = user.properties?.line_id || user.properties?.line_ids || [];
|
|
59010
|
+
return Array.isArray(lines) ? lines : [];
|
|
59011
|
+
}, [user]);
|
|
59012
|
+
const assignedFactoryIds = React24.useMemo(() => {
|
|
59013
|
+
if (!user) return [];
|
|
59014
|
+
if (user.role_level !== "plant_head") return [];
|
|
59015
|
+
const factories = user.properties?.factory_id || user.properties?.factory_ids || [];
|
|
59016
|
+
return Array.isArray(factories) ? factories : [];
|
|
59017
|
+
}, [user]);
|
|
59018
|
+
const plantHeadLineIds = React24.useMemo(() => {
|
|
59019
|
+
if (user?.role_level !== "plant_head" || companyLines.length === 0) return [];
|
|
59020
|
+
const factorySet = new Set(assignedFactoryIds);
|
|
59021
|
+
return companyLines.filter((line) => line.factoryId === void 0 || line.factoryId === null || factorySet.has(line.factoryId)).map((line) => line.id);
|
|
59022
|
+
}, [assignedFactoryIds, companyLines, user?.role_level]);
|
|
58382
59023
|
const scopeLineIds = React24.useMemo(() => {
|
|
58383
|
-
|
|
58384
|
-
|
|
59024
|
+
if (user?.role_level === "supervisor") {
|
|
59025
|
+
return assignedLineIds;
|
|
59026
|
+
}
|
|
59027
|
+
if (user?.role_level === "plant_head") {
|
|
59028
|
+
if (plantHeadLineIds.length > 0) return plantHeadLineIds;
|
|
59029
|
+
return companyLineIds.length > 0 ? companyLineIds : configuredLineIds;
|
|
59030
|
+
}
|
|
59031
|
+
if (companyLineIds.length > 0) return companyLineIds;
|
|
59032
|
+
return configuredLineIds;
|
|
59033
|
+
}, [
|
|
59034
|
+
assignedLineIds,
|
|
59035
|
+
companyLineIds,
|
|
59036
|
+
configuredLineIds,
|
|
59037
|
+
plantHeadLineIds,
|
|
59038
|
+
user?.role_level
|
|
59039
|
+
]);
|
|
58385
59040
|
const scopeLineIdsKey = React24.useMemo(() => scopeLineIds.join(","), [scopeLineIds]);
|
|
59041
|
+
const lineNameById = React24.useMemo(() => {
|
|
59042
|
+
const map = /* @__PURE__ */ new Map();
|
|
59043
|
+
companyLines.forEach((line) => map.set(line.id, line.name));
|
|
59044
|
+
Object.entries(configuredLines).forEach(([id3, name]) => {
|
|
59045
|
+
if (!map.has(id3)) map.set(id3, name);
|
|
59046
|
+
});
|
|
59047
|
+
return map;
|
|
59048
|
+
}, [companyLines, configuredLines]);
|
|
58386
59049
|
const companyId = user?.company_id || entityConfig.companyId;
|
|
58387
59050
|
const clipsService = React24.useMemo(() => {
|
|
58388
59051
|
try {
|
|
@@ -58391,6 +59054,58 @@ var ImprovementCenterView = () => {
|
|
|
58391
59054
|
return null;
|
|
58392
59055
|
}
|
|
58393
59056
|
}, [dashboardConfig]);
|
|
59057
|
+
React24.useEffect(() => {
|
|
59058
|
+
let cancelled = false;
|
|
59059
|
+
const loadTeamMembers = async () => {
|
|
59060
|
+
if (!supabase || !companyId) return;
|
|
59061
|
+
try {
|
|
59062
|
+
const userService2 = createUserManagementService(supabase);
|
|
59063
|
+
const supervisors = await userService2.getCompanyUsers(companyId, "supervisor");
|
|
59064
|
+
if (cancelled) return;
|
|
59065
|
+
const members = supervisors.map((user2) => {
|
|
59066
|
+
const rawName = user2.properties?.full_name || user2.email?.split("@")[0] || "Unknown";
|
|
59067
|
+
return {
|
|
59068
|
+
id: user2.user_id,
|
|
59069
|
+
name: rawName,
|
|
59070
|
+
role: user2.role_level,
|
|
59071
|
+
initials: buildInitials(rawName),
|
|
59072
|
+
email: user2.email
|
|
59073
|
+
};
|
|
59074
|
+
});
|
|
59075
|
+
members.sort((a, b) => a.name.localeCompare(b.name));
|
|
59076
|
+
setTeamMembers(members);
|
|
59077
|
+
} catch (error) {
|
|
59078
|
+
if (!cancelled) {
|
|
59079
|
+
console.error("[ImprovementCenterView] Failed to load supervisors", error);
|
|
59080
|
+
setTeamMembers([]);
|
|
59081
|
+
}
|
|
59082
|
+
}
|
|
59083
|
+
};
|
|
59084
|
+
loadTeamMembers();
|
|
59085
|
+
return () => {
|
|
59086
|
+
cancelled = true;
|
|
59087
|
+
};
|
|
59088
|
+
}, [supabase, companyId]);
|
|
59089
|
+
React24.useEffect(() => {
|
|
59090
|
+
let cancelled = false;
|
|
59091
|
+
const loadLines = async () => {
|
|
59092
|
+
if (!supabase || !companyId) return;
|
|
59093
|
+
try {
|
|
59094
|
+
const linesService2 = new LinesService(supabase);
|
|
59095
|
+
const lines = await linesService2.getLinesByCompanyId(companyId);
|
|
59096
|
+
if (!cancelled) setCompanyLines(lines);
|
|
59097
|
+
} catch (error) {
|
|
59098
|
+
if (!cancelled) {
|
|
59099
|
+
console.error("[ImprovementCenterView] Failed to load lines", error);
|
|
59100
|
+
setCompanyLines([]);
|
|
59101
|
+
}
|
|
59102
|
+
}
|
|
59103
|
+
};
|
|
59104
|
+
loadLines();
|
|
59105
|
+
return () => {
|
|
59106
|
+
cancelled = true;
|
|
59107
|
+
};
|
|
59108
|
+
}, [supabase, companyId]);
|
|
58394
59109
|
const nextMonth = () => {
|
|
58395
59110
|
setCurrentDate(new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, 1));
|
|
58396
59111
|
};
|
|
@@ -58423,11 +59138,16 @@ var ImprovementCenterView = () => {
|
|
|
58423
59138
|
const res = await fetchBackendJson(supabase, `/api/improvement-center/recommendations?${params.toString()}`);
|
|
58424
59139
|
if (cancelled) return;
|
|
58425
59140
|
let recs = res.recommendations || [];
|
|
58426
|
-
recs = recs.map((r2) =>
|
|
58427
|
-
|
|
58428
|
-
|
|
58429
|
-
|
|
58430
|
-
|
|
59141
|
+
recs = recs.map((r2) => {
|
|
59142
|
+
const assignedUserIds = Array.isArray(r2.assigned_user_ids) ? r2.assigned_user_ids : r2.assigned_to_user_id ? [r2.assigned_to_user_id] : [];
|
|
59143
|
+
return {
|
|
59144
|
+
...r2,
|
|
59145
|
+
ticket_status: r2.issue_status === "resolved" ? "solved" : "active",
|
|
59146
|
+
weeks_open: typeof r2.weeks_open === "number" ? r2.weeks_open : computeWeeksOpen(r2.first_seen_at) ?? 1,
|
|
59147
|
+
assigned_to_user_id: assignedUserIds[0],
|
|
59148
|
+
assigned_user_ids: assignedUserIds
|
|
59149
|
+
};
|
|
59150
|
+
});
|
|
58431
59151
|
const allowed = new Set(scopeLineIds);
|
|
58432
59152
|
setRecommendations(recs.filter((r2) => !r2.line_id || allowed.has(r2.line_id)));
|
|
58433
59153
|
} catch (err) {
|
|
@@ -58443,37 +59163,80 @@ var ImprovementCenterView = () => {
|
|
|
58443
59163
|
cancelled = true;
|
|
58444
59164
|
};
|
|
58445
59165
|
}, [supabase, companyId, scopeLineIdsKey, currentDate]);
|
|
59166
|
+
const teamMembersById = React24.useMemo(() => {
|
|
59167
|
+
return new Map(teamMembers.map((member) => [member.id, member]));
|
|
59168
|
+
}, [teamMembers]);
|
|
58446
59169
|
const filteredRecommendations = React24.useMemo(() => {
|
|
58447
59170
|
return recommendations.filter((rec) => {
|
|
58448
|
-
if (selectedCategory !== "all" && rec.type !== selectedCategory) return false;
|
|
58449
59171
|
if (selectedLineId !== "all" && rec.line_id !== selectedLineId) return false;
|
|
58450
59172
|
if (selectedStatus === "resolved" && rec.ticket_status !== "solved") return false;
|
|
58451
59173
|
if (selectedStatus === "unresolved" && rec.ticket_status === "solved") return false;
|
|
59174
|
+
if (selectedShift !== "all" && (rec.shift_label || `Shift ${rec.shift_id}`) !== selectedShift) return false;
|
|
59175
|
+
if (selectedWeeksRange !== "all") {
|
|
59176
|
+
const weeks = rec.weeks_open || 0;
|
|
59177
|
+
if (selectedWeeksRange === "1" && weeks !== 1) return false;
|
|
59178
|
+
if (selectedWeeksRange === "2" && weeks !== 2) return false;
|
|
59179
|
+
if (selectedWeeksRange === "3+" && weeks < 3) return false;
|
|
59180
|
+
}
|
|
59181
|
+
if (selectedMemberId !== "all" && !(rec.assigned_user_ids?.includes(selectedMemberId) || rec.assigned_to_user_id === selectedMemberId)) return false;
|
|
58452
59182
|
return true;
|
|
58453
59183
|
}).sort((a, b) => (b.weeks_open || 0) - (a.weeks_open || 0));
|
|
58454
|
-
}, [recommendations,
|
|
59184
|
+
}, [recommendations, selectedLineId, selectedStatus, selectedShift, selectedWeeksRange, selectedMemberId]);
|
|
58455
59185
|
const stats = React24.useMemo(() => {
|
|
58456
|
-
const
|
|
58457
|
-
|
|
59186
|
+
const baseFiltered = recommendations.filter((rec) => {
|
|
59187
|
+
if (selectedLineId !== "all" && rec.line_id !== selectedLineId) return false;
|
|
59188
|
+
if (selectedShift !== "all" && (rec.shift_label || `Shift ${rec.shift_id}`) !== selectedShift) return false;
|
|
59189
|
+
if (selectedWeeksRange !== "all") {
|
|
59190
|
+
const weeks = rec.weeks_open || 0;
|
|
59191
|
+
if (selectedWeeksRange === "1" && weeks !== 1) return false;
|
|
59192
|
+
if (selectedWeeksRange === "2" && weeks !== 2) return false;
|
|
59193
|
+
if (selectedWeeksRange === "3+" && weeks < 3) return false;
|
|
59194
|
+
}
|
|
59195
|
+
if (selectedMemberId !== "all" && !(rec.assigned_user_ids?.includes(selectedMemberId) || rec.assigned_to_user_id === selectedMemberId)) return false;
|
|
59196
|
+
return true;
|
|
59197
|
+
});
|
|
59198
|
+
const total = baseFiltered.length;
|
|
59199
|
+
const resolved = baseFiltered.filter((r2) => r2.ticket_status === "solved").length;
|
|
58458
59200
|
return {
|
|
58459
59201
|
all: total,
|
|
58460
59202
|
resolved,
|
|
58461
59203
|
unresolved: total - resolved
|
|
58462
59204
|
};
|
|
58463
|
-
}, [recommendations]);
|
|
59205
|
+
}, [recommendations, selectedLineId, selectedShift, selectedWeeksRange, selectedMemberId]);
|
|
58464
59206
|
const clearFilters = () => {
|
|
58465
|
-
setSelectedCategory("all");
|
|
58466
59207
|
setSelectedLineId("all");
|
|
58467
59208
|
setSelectedStatus("all");
|
|
58468
|
-
|
|
59209
|
+
setSelectedShift("all");
|
|
59210
|
+
setSelectedWeeksRange("all");
|
|
59211
|
+
setSelectedMemberId("all");
|
|
59212
|
+
};
|
|
59213
|
+
const shiftOptions = React24.useMemo(() => {
|
|
59214
|
+
const shifts = /* @__PURE__ */ new Set();
|
|
59215
|
+
recommendations.forEach((r2) => {
|
|
59216
|
+
const label = r2.shift_label || (r2.shift_id !== void 0 ? `Shift ${r2.shift_id}` : null);
|
|
59217
|
+
if (label) shifts.add(label);
|
|
59218
|
+
});
|
|
59219
|
+
return ["all", ...Array.from(shifts)];
|
|
59220
|
+
}, [recommendations]);
|
|
59221
|
+
const weekOptions = [
|
|
59222
|
+
{ id: "all", label: "Any Duration" },
|
|
59223
|
+
{ id: "1", label: "1 Week" },
|
|
59224
|
+
{ id: "2", label: "2 Weeks" },
|
|
59225
|
+
{ id: "3+", label: "3+ Weeks" }
|
|
59226
|
+
];
|
|
58469
59227
|
const lineOptions = React24.useMemo(() => {
|
|
58470
59228
|
const options = [{ id: "all", label: "All Lines" }];
|
|
58471
59229
|
scopeLineIds.forEach((lineId) => {
|
|
58472
|
-
const lineName =
|
|
59230
|
+
const lineName = lineNameById.get(lineId) || lineId;
|
|
58473
59231
|
options.push({ id: lineId, label: lineName });
|
|
58474
59232
|
});
|
|
58475
59233
|
return options;
|
|
58476
|
-
}, [scopeLineIds,
|
|
59234
|
+
}, [scopeLineIds, lineNameById]);
|
|
59235
|
+
React24.useEffect(() => {
|
|
59236
|
+
if (selectedLineId !== "all" && !scopeLineIds.includes(selectedLineId)) {
|
|
59237
|
+
setSelectedLineId("all");
|
|
59238
|
+
}
|
|
59239
|
+
}, [scopeLineIds, selectedLineId]);
|
|
58477
59240
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-h-screen bg-gray-50 flex flex-col", children: [
|
|
58478
59241
|
/* @__PURE__ */ jsxRuntime.jsx("header", { className: "sticky top-0 z-10 bg-white border-b border-gray-200 flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 sm:px-6 lg:px-8 py-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
58479
59242
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4 min-w-[120px]", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -58548,15 +59311,41 @@ var ImprovementCenterView = () => {
|
|
|
58548
59311
|
}
|
|
58549
59312
|
)
|
|
58550
59313
|
] }),
|
|
58551
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-
|
|
59314
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 w-full md:w-auto", children: [
|
|
59315
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
59316
|
+
"select",
|
|
59317
|
+
{
|
|
59318
|
+
value: selectedShift,
|
|
59319
|
+
onChange: (e) => setSelectedShift(e.target.value),
|
|
59320
|
+
className: "flex-1 md:flex-none appearance-none pl-3 pr-8 py-1.5 text-sm border border-gray-300 rounded-lg bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 cursor-pointer text-gray-700 shadow-sm",
|
|
59321
|
+
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.5em 1.5em` },
|
|
59322
|
+
children: [
|
|
59323
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Shifts" }),
|
|
59324
|
+
shiftOptions.filter((s) => s !== "all").map((shift) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: shift, children: shift }, shift))
|
|
59325
|
+
]
|
|
59326
|
+
}
|
|
59327
|
+
),
|
|
58552
59328
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
58553
59329
|
"select",
|
|
58554
59330
|
{
|
|
58555
|
-
value:
|
|
58556
|
-
onChange: (e) =>
|
|
58557
|
-
className: "
|
|
59331
|
+
value: selectedWeeksRange,
|
|
59332
|
+
onChange: (e) => setSelectedWeeksRange(e.target.value),
|
|
59333
|
+
className: "flex-1 md:flex-none appearance-none pl-3 pr-8 py-1.5 text-sm border border-gray-300 rounded-lg bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 cursor-pointer text-gray-700 shadow-sm",
|
|
59334
|
+
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.5em 1.5em` },
|
|
59335
|
+
children: weekOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.id, children: opt.label }, opt.id))
|
|
59336
|
+
}
|
|
59337
|
+
),
|
|
59338
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
59339
|
+
"select",
|
|
59340
|
+
{
|
|
59341
|
+
value: selectedMemberId,
|
|
59342
|
+
onChange: (e) => setSelectedMemberId(e.target.value),
|
|
59343
|
+
className: "flex-1 md:flex-none appearance-none pl-3 pr-8 py-1.5 text-sm border border-gray-300 rounded-lg bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 cursor-pointer text-gray-700 shadow-sm",
|
|
58558
59344
|
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.5em 1.5em` },
|
|
58559
|
-
children:
|
|
59345
|
+
children: [
|
|
59346
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "all", children: "All Members" }),
|
|
59347
|
+
teamMembers.map((member) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: member.id, children: member.name }, member.id))
|
|
59348
|
+
]
|
|
58560
59349
|
}
|
|
58561
59350
|
),
|
|
58562
59351
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -58564,7 +59353,7 @@ var ImprovementCenterView = () => {
|
|
|
58564
59353
|
{
|
|
58565
59354
|
value: selectedLineId,
|
|
58566
59355
|
onChange: (e) => setSelectedLineId(e.target.value),
|
|
58567
|
-
className: "
|
|
59356
|
+
className: "flex-1 md:flex-none appearance-none pl-3 pr-8 py-1.5 text-sm border border-gray-300 rounded-lg bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500 cursor-pointer text-gray-700 shadow-sm",
|
|
58568
59357
|
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.5em 1.5em` },
|
|
58569
59358
|
children: lineOptions.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.id, children: opt.label }, opt.id))
|
|
58570
59359
|
}
|
|
@@ -58579,29 +59368,47 @@ var ImprovementCenterView = () => {
|
|
|
58579
59368
|
animate: { opacity: 1, y: 0 },
|
|
58580
59369
|
transition: { delay: index * 0.1 },
|
|
58581
59370
|
className: `bg-white rounded-xl shadow-sm border overflow-hidden ${rec.ticket_status === "solved" ? "border-green-200" : "border-gray-200"}`,
|
|
58582
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col md:flex-row gap-6", children: [
|
|
59371
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 relative", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col md:flex-row gap-6", children: [
|
|
58583
59372
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-4", children: [
|
|
58584
59373
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 w-full", children: [
|
|
58585
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
58586
|
-
/* @__PURE__ */ jsxRuntime.
|
|
58587
|
-
(rec.shift_label || rec.shift_id !== void 0) && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-700", children: rec.shift_label || `Shift ${rec.shift_id}` }),
|
|
58588
|
-
rec.ticket_status === "solved" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800", children: [
|
|
59374
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
59375
|
+
rec.ticket_status === "solved" ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium bg-emerald-50 text-emerald-700 border border-emerald-100", children: [
|
|
58589
59376
|
/* @__PURE__ */ jsxRuntime.jsx(outline.CheckCircleIcon, { className: "w-3.5 h-3.5" }),
|
|
58590
59377
|
"Resolved"
|
|
58591
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium border ${(rec.weeks_open || 0) > 2 ? "bg-red-50 text-red-700 border-red-
|
|
59378
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium border ${(rec.weeks_open || 0) > 2 ? "bg-red-50 text-red-700 border-red-100" : "bg-amber-50 text-amber-700 border-amber-100"}`, children: [
|
|
58592
59379
|
/* @__PURE__ */ jsxRuntime.jsx(outline.ClockIcon, { className: "w-3.5 h-3.5" }),
|
|
58593
59380
|
"Open for ",
|
|
58594
59381
|
rec.weeks_open || 1,
|
|
58595
59382
|
" week",
|
|
58596
59383
|
(rec.weeks_open || 1) !== 1 ? "s" : ""
|
|
59384
|
+
] }),
|
|
59385
|
+
rec.assigned_user_ids && rec.assigned_user_ids.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
59386
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-3 w-px bg-gray-200" }),
|
|
59387
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-3", children: rec.assigned_user_ids.map((uid) => {
|
|
59388
|
+
const user2 = teamMembersById.get(uid);
|
|
59389
|
+
if (!user2) {
|
|
59390
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
59391
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5 h-5 rounded-full bg-gray-100 text-gray-500 flex items-center justify-center text-[9px] font-bold border border-gray-200", children: "??" }),
|
|
59392
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-500", children: "Unknown" })
|
|
59393
|
+
] }, uid);
|
|
59394
|
+
}
|
|
59395
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
59396
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5 h-5 rounded-full bg-gray-100 text-gray-600 flex items-center justify-center text-[9px] font-bold border border-gray-200", children: user2.initials }),
|
|
59397
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium text-gray-600", children: user2.name })
|
|
59398
|
+
] }, user2.id);
|
|
59399
|
+
}) })
|
|
58597
59400
|
] })
|
|
58598
59401
|
] }),
|
|
58599
59402
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
58600
|
-
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: rec.title }),
|
|
58601
|
-
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-medium text-gray-500 mt-1", children: [
|
|
59403
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900 pr-12", children: rec.title }),
|
|
59404
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm font-medium text-gray-500 mt-1 flex items-center gap-2", children: [
|
|
58602
59405
|
rec.location,
|
|
58603
59406
|
" \u2022 ",
|
|
58604
|
-
rec.line
|
|
59407
|
+
rec.line,
|
|
59408
|
+
(rec.shift_label || rec.shift_id !== void 0) && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
59409
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2022" }),
|
|
59410
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "uppercase tracking-wide text-xs pt-0.5 text-gray-500 font-medium", children: rec.shift_label || `Shift ${rec.shift_id}` })
|
|
59411
|
+
] })
|
|
58605
59412
|
] })
|
|
58606
59413
|
] })
|
|
58607
59414
|
] }) }),
|
|
@@ -58612,40 +59419,14 @@ var ImprovementCenterView = () => {
|
|
|
58612
59419
|
rec.impact
|
|
58613
59420
|
] }) })
|
|
58614
59421
|
] }),
|
|
58615
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full md:w-1/2 lg:w-5/12 bg-gray-50 rounded-lg p-4 border border-gray-100", children: Array.isArray(rec.evidence) && rec.evidence.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
58616
|
-
|
|
58617
|
-
|
|
58618
|
-
|
|
58619
|
-
|
|
58620
|
-
|
|
58621
|
-
|
|
58622
|
-
|
|
58623
|
-
/* @__PURE__ */ jsxRuntime.jsxs("h4", { className: "text-xs font-semibold text-gray-500 uppercase tracking-wider flex items-center gap-2", children: [
|
|
58624
|
-
isVideo ? /* @__PURE__ */ jsxRuntime.jsx(outline.PlayCircleIcon, { className: "w-4 h-4" }) : isChart ? /* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: "w-4 h-4" }) : /* @__PURE__ */ jsxRuntime.jsx(outline.ChartBarIcon, { className: "w-4 h-4" }),
|
|
58625
|
-
title
|
|
58626
|
-
] }),
|
|
58627
|
-
isVideo && clipCount > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[10px] font-medium text-gray-500 bg-gray-100 px-1.5 py-0.5 rounded", children: [
|
|
58628
|
-
clipCount,
|
|
58629
|
-
" clips"
|
|
58630
|
-
] })
|
|
58631
|
-
] }),
|
|
58632
|
-
ev.type === "video_gallery" && /* @__PURE__ */ jsxRuntime.jsx(ClipVideoCarousel, { clips, clipsService }),
|
|
58633
|
-
ev.type === "bar_chart" && (Array.isArray(ev.x) && Array.isArray(ev.y) || Array.isArray(ev.data) && Array.isArray(ev.series)) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
58634
|
-
BarChartEvidence,
|
|
58635
|
-
{
|
|
58636
|
-
x: ev.x,
|
|
58637
|
-
y: ev.y,
|
|
58638
|
-
data: ev.data,
|
|
58639
|
-
series: ev.series,
|
|
58640
|
-
unit: ev.unit,
|
|
58641
|
-
referenceLines: Array.isArray(ev.reference_lines) ? ev.reference_lines : void 0
|
|
58642
|
-
}
|
|
58643
|
-
),
|
|
58644
|
-
ev.type === "pie_chart" && Array.isArray(ev.data) && /* @__PURE__ */ jsxRuntime.jsx(PieChartEvidence, { data: ev.data }),
|
|
58645
|
-
ev.type === "timeseries" && Array.isArray(ev.x) && Array.isArray(ev.y) && /* @__PURE__ */ jsxRuntime.jsx(LineChartEvidence, { x: ev.x, y: ev.y, unit: ev.unit }),
|
|
58646
|
-
ev.type === "table" && Array.isArray(ev.columns) && Array.isArray(ev.rows) && /* @__PURE__ */ jsxRuntime.jsx(TableEvidence, { columns: ev.columns, rows: ev.rows })
|
|
58647
|
-
] }, `${rec.id}-ev-${idx}`);
|
|
58648
|
-
}) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: isLoading ? "Loading evidence\u2026" : loadError ? loadError : "No evidence available" }) })
|
|
59422
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full md:w-1/2 lg:w-5/12 bg-gray-50 rounded-lg p-4 border border-gray-100", children: Array.isArray(rec.evidence) && rec.evidence.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
59423
|
+
EvidenceCarousel,
|
|
59424
|
+
{
|
|
59425
|
+
evidence: rec.evidence,
|
|
59426
|
+
recId: rec.id,
|
|
59427
|
+
clipsService
|
|
59428
|
+
}
|
|
59429
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-500", children: isLoading ? "Loading evidence\u2026" : loadError ? loadError : "No evidence available" }) })
|
|
58649
59430
|
] }) })
|
|
58650
59431
|
},
|
|
58651
59432
|
rec.id
|
|
@@ -58654,8 +59435,8 @@ var ImprovementCenterView = () => {
|
|
|
58654
59435
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center py-16 bg-white rounded-xl border border-gray-200 shadow-sm", children: [
|
|
58655
59436
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto flex items-center justify-center w-16 h-16 rounded-full bg-green-50 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(outline.CheckCircleIcon, { className: "w-8 h-8 text-green-500" }) }),
|
|
58656
59437
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "No tickets found" }),
|
|
58657
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-500 max-w-md mx-auto", children:
|
|
58658
|
-
(
|
|
59438
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-500 max-w-md mx-auto", children: selectedLineId !== "all" || selectedStatus !== "all" || selectedShift !== "all" || selectedWeeksRange !== "all" || selectedMemberId !== "all" ? "Try adjusting your filters to see more results." : "All monitored long-term patterns were evaluated and remained within limits. This is a success state!" }),
|
|
59439
|
+
(selectedLineId !== "all" || selectedStatus !== "all" || selectedShift !== "all" || selectedWeeksRange !== "all" || selectedMemberId !== "all") && /* @__PURE__ */ jsxRuntime.jsx(
|
|
58659
59440
|
"button",
|
|
58660
59441
|
{
|
|
58661
59442
|
onClick: clearFilters,
|
|
@@ -59352,6 +60133,7 @@ exports.areAllLinesOnSameShift = areAllLinesOnSameShift;
|
|
|
59352
60133
|
exports.authCoreService = authCoreService;
|
|
59353
60134
|
exports.authOTPService = authOTPService;
|
|
59354
60135
|
exports.authRateLimitService = authRateLimitService;
|
|
60136
|
+
exports.buildDateKey = buildDateKey;
|
|
59355
60137
|
exports.buildKPIsFromLineMetricsRow = buildKPIsFromLineMetricsRow;
|
|
59356
60138
|
exports.checkRateLimit = checkRateLimit2;
|
|
59357
60139
|
exports.clearAllRateLimits = clearAllRateLimits2;
|
|
@@ -59373,12 +60155,15 @@ exports.createUserService = createUserService;
|
|
|
59373
60155
|
exports.dashboardService = dashboardService;
|
|
59374
60156
|
exports.deleteThread = deleteThread;
|
|
59375
60157
|
exports.fetchIdleTimeReasons = fetchIdleTimeReasons;
|
|
60158
|
+
exports.filterDataByDateKeyRange = filterDataByDateKeyRange;
|
|
59376
60159
|
exports.forceRefreshWorkspaceDisplayNames = forceRefreshWorkspaceDisplayNames;
|
|
59377
60160
|
exports.formatDateInZone = formatDateInZone;
|
|
60161
|
+
exports.formatDateKeyForDisplay = formatDateKeyForDisplay;
|
|
59378
60162
|
exports.formatDateTimeInZone = formatDateTimeInZone;
|
|
59379
60163
|
exports.formatDuration = formatDuration;
|
|
59380
60164
|
exports.formatISTDate = formatISTDate;
|
|
59381
60165
|
exports.formatIdleTime = formatIdleTime;
|
|
60166
|
+
exports.formatRangeLabel = formatRangeLabel;
|
|
59382
60167
|
exports.formatReasonLabel = formatReasonLabel;
|
|
59383
60168
|
exports.formatRelativeTime = formatRelativeTime;
|
|
59384
60169
|
exports.formatTimeInZone = formatTimeInZone;
|
|
@@ -59401,6 +60186,7 @@ exports.getCurrentShift = getCurrentShift;
|
|
|
59401
60186
|
exports.getCurrentShiftForLine = getCurrentShiftForLine;
|
|
59402
60187
|
exports.getCurrentTimeInZone = getCurrentTimeInZone;
|
|
59403
60188
|
exports.getDashboardHeaderTimeInZone = getDashboardHeaderTimeInZone;
|
|
60189
|
+
exports.getDateKeyFromDate = getDateKeyFromDate;
|
|
59404
60190
|
exports.getDaysDifferenceInZone = getDaysDifferenceInZone;
|
|
59405
60191
|
exports.getDefaultCameraStreamUrl = getDefaultCameraStreamUrl;
|
|
59406
60192
|
exports.getDefaultLineId = getDefaultLineId;
|
|
@@ -59408,6 +60194,8 @@ exports.getDefaultTabForWorkspace = getDefaultTabForWorkspace;
|
|
|
59408
60194
|
exports.getLineDisplayName = getLineDisplayName;
|
|
59409
60195
|
exports.getManufacturingInsights = getManufacturingInsights;
|
|
59410
60196
|
exports.getMetricsTablePrefix = getMetricsTablePrefix;
|
|
60197
|
+
exports.getMonthKeyBounds = getMonthKeyBounds;
|
|
60198
|
+
exports.getMonthWeekRanges = getMonthWeekRanges;
|
|
59411
60199
|
exports.getNextUpdateInterval = getNextUpdateInterval;
|
|
59412
60200
|
exports.getOperationalDate = getOperationalDate;
|
|
59413
60201
|
exports.getReasonColor = getReasonColor;
|
|
@@ -59433,6 +60221,7 @@ exports.groupLinesByShift = groupLinesByShift;
|
|
|
59433
60221
|
exports.hasAnyShiftData = hasAnyShiftData;
|
|
59434
60222
|
exports.identifyCoreUser = identifyCoreUser;
|
|
59435
60223
|
exports.initializeCoreMixpanel = initializeCoreMixpanel;
|
|
60224
|
+
exports.isFullMonthRange = isFullMonthRange;
|
|
59436
60225
|
exports.isLegacyConfiguration = isLegacyConfiguration;
|
|
59437
60226
|
exports.isPrefetchError = isPrefetchError;
|
|
59438
60227
|
exports.isSafari = isSafari;
|
|
@@ -59449,7 +60238,9 @@ exports.isWorkspaceDisplayNamesLoading = isWorkspaceDisplayNamesLoading;
|
|
|
59449
60238
|
exports.linesService = linesService;
|
|
59450
60239
|
exports.mergeWithDefaultConfig = mergeWithDefaultConfig;
|
|
59451
60240
|
exports.migrateLegacyConfiguration = migrateLegacyConfiguration;
|
|
60241
|
+
exports.normalizeDateKeyRange = normalizeDateKeyRange;
|
|
59452
60242
|
exports.optifyeAgentClient = optifyeAgentClient;
|
|
60243
|
+
exports.parseDateKeyToDate = parseDateKeyToDate;
|
|
59453
60244
|
exports.parseS3Uri = parseS3Uri;
|
|
59454
60245
|
exports.preInitializeWorkspaceDisplayNames = preInitializeWorkspaceDisplayNames;
|
|
59455
60246
|
exports.preloadS3Video = preloadS3Video;
|