@optifye/dashboard-core 6.10.12 → 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.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
- if (safariMode) {
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 returnTo = `/kpis/${lineId}?tab=monthly_history&month=${month2}&year=${year2}`;
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 startDate = React24.useMemo(() => {
36765
- const m = String(month + 1).padStart(2, "0");
36766
- return `${year}-${m}-01`;
36767
- }, [month, year]);
36768
- const endDate = React24.useMemo(() => {
36769
- const lastDay = new Date(year, month + 1, 0).getDate();
36770
- const m = String(month + 1).padStart(2, "0");
36771
- const d = String(lastDay).padStart(2, "0");
36772
- return `${year}-${m}-${d}`;
36773
- }, [month, year]);
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 = (monthlyData || []).reduce(
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 returnToUrl = `/kpis/${lineId}?tab=monthly_history&month=${month}&year=${year}`;
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.jsx("div", { className: "flex justify-center mb-4", 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 : [
36875
- { id: 0, name: "Day Shift" },
36876
- { id: 1, name: "Night Shift" }
36877
- ]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsxRuntime.jsx(
36878
- "button",
36879
- {
36880
- onClick: () => onShiftChange?.(shift.id),
36881
- 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"}`,
36882
- children: shift.name
36883
- },
36884
- shift.id
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
- new Date(year, month).toLocaleString("default", { month: "long" })
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
- new Date(year, month).toLocaleString("default", { month: "long" })
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: ${startDateStr} - ${endDateStr}`, 20, 71);
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 validDays = monthlyData.filter((day) => {
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 startDate = React24.useMemo(() => {
38479
- const monthString = String(month + 1).padStart(2, "0");
38480
- return `${year}-${monthString}-01`;
38481
- }, [month, year]);
38482
- const endDate = React24.useMemo(() => {
38483
- const lastDay = new Date(year, month + 1, 0).getDate();
38484
- const monthString = String(month + 1).padStart(2, "0");
38485
- const dayString = String(lastDay).padStart(2, "0");
38486
- return `${year}-${monthString}-${dayString}`;
38487
- }, [month, year]);
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: data.length > 0
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 daysInMonth = new Date(year, month + 1, 0).getDate();
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 day = daysInMonth; day >= 1; day--) {
38509
- const dayData = data.find((d) => {
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 (let day = 1; day <= daysInMonth; day++) {
38521
- const dayData = data.find((d) => {
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
- }, [data, month, year, selectedShiftId]);
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 = data.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
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
- }, [data, selectedShiftId]);
38980
+ }, [analysisMonthlyData, selectedShiftId]);
38580
38981
  const metrics2 = React24.useMemo(() => {
38581
- const validShifts = data.map((d) => getShiftData(d, selectedShiftId)).filter(hasRealData);
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
- }, [data, selectedShiftId]);
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.jsx("div", { className: "flex justify-center mb-4", 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 : [
38653
- { id: 0, name: "Day Shift" },
38654
- { id: 1, name: "Night Shift" }
38655
- ]).sort((a, b) => a.id - b.id).map((shift) => /* @__PURE__ */ jsxRuntime.jsx(
38656
- "button",
38657
- {
38658
- onClick: () => handleShiftChange(shift.id),
38659
- 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"}`,
38660
- children: shift.name
38661
- },
38662
- shift.id
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: ${startDateStr} - ${endDateStr}`, 20, 81);
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 validDays = monthlyData.filter((day) => {
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 = `/kpis/${lineId}?tab=monthly_history&month=${currentMonth}&year=${currentYear}`;
51051
+ const url = buildMonthlyHistoryUrl(currentMonth, currentYear);
50572
51052
  handleNavigate(url, { shallow: true });
50573
- }, [lineInfo, lineId, currentMonth, currentYear, handleNavigate]);
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 backUrl = urlDate || urlShift ? urlMonth && urlYear ? `/kpis/${lineId}?tab=monthly_history&month=${urlMonth}&year=${urlYear}` : `/kpis/${lineId}?tab=monthly_history&month=${currentMonth}&year=${currentYear}` : "/kpis";
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, lineId, currentMonth, currentYear]);
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
- handleNavigate(`/kpis/${lineId}?tab=monthly_history&month=${validMonth}&year=${validYear}`, { shallow: true });
50614
- }, [currentMonth, currentYear, configuredTimezone, handleNavigate, lineId]);
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 CATEGORY_OPTIONS = [
58103
- { id: "all", label: "All" },
58104
- { id: "cycle_time", label: "Cycle Time" },
58105
- { id: "efficiency", label: "Efficiency" },
58106
- { id: "downtime", label: "Downtime" }
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 { accessibleLineIds } = useUserLineAccess(configuredLineIds);
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
- return accessibleLineIds.length > 0 ? accessibleLineIds : configuredLineIds;
58384
- }, [accessibleLineIds, configuredLineIds]);
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
- ...r2,
58428
- ticket_status: r2.issue_status === "resolved" ? "solved" : "active",
58429
- weeks_open: typeof r2.weeks_open === "number" ? r2.weeks_open : computeWeeksOpen(r2.first_seen_at) ?? 1
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, selectedCategory, selectedLineId, selectedStatus]);
59184
+ }, [recommendations, selectedLineId, selectedStatus, selectedShift, selectedWeeksRange, selectedMemberId]);
58455
59185
  const stats = React24.useMemo(() => {
58456
- const total = recommendations.length;
58457
- const resolved = recommendations.filter((r2) => r2.ticket_status === "solved").length;
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 = configuredLines[lineId] || lineId;
59230
+ const lineName = lineNameById.get(lineId) || lineId;
58473
59231
  options.push({ id: lineId, label: lineName });
58474
59232
  });
58475
59233
  return options;
58476
- }, [scopeLineIds, configuredLines]);
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-3 w-full md:w-auto", children: [
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: selectedCategory,
58556
- onChange: (e) => setSelectedCategory(e.target.value),
58557
- className: "w-full md:w-auto 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",
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: CATEGORY_OPTIONS.map((opt) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: opt.id, children: opt.label }, opt.id))
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: "w-full md:w-auto 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",
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.jsx("span", { className: `inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${rec.type === "cycle_time" ? "bg-blue-100 text-blue-800" : rec.type === "efficiency" ? "bg-orange-100 text-orange-800" : "bg-gray-100 text-gray-800"}`, children: rec.type.replace("_", " ").toUpperCase() }),
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-200" : "bg-amber-50 text-amber-700 border-amber-200"}`, children: [
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("div", { className: "space-y-4", children: rec.evidence.map((ev, idx) => {
58616
- const isVideo = ev.type === "video_gallery";
58617
- const isChart = ev.type === "bar_chart" || ev.type === "timeseries" || ev.type === "pie_chart";
58618
- const title = ev.title || "Evidence";
58619
- const clips = Array.isArray(ev.clips) ? ev.clips : [];
58620
- const clipCount = clips.length;
58621
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
58622
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
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: selectedCategory !== "all" || selectedLineId !== "all" || selectedStatus !== "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!" }),
58658
- (selectedCategory !== "all" || selectedLineId !== "all" || selectedStatus !== "all") && /* @__PURE__ */ jsxRuntime.jsx(
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;