@optifye/dashboard-core 6.10.14 → 6.10.16

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.mjs CHANGED
@@ -3,7 +3,7 @@ import React24__default, { createContext, useRef, useCallback, useState, useMemo
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { useRouter } from 'next/router';
5
5
  import { fromZonedTime, toZonedTime, formatInTimeZone } from 'date-fns-tz';
6
- import { addMinutes, subDays, format, parseISO, isValid, differenceInMinutes, formatDistanceToNow, isToday, isFuture, addDays, startOfDay, isBefore, startOfMonth, endOfMonth, eachDayOfInterval, getDay, isSameDay, isWithinInterval, subMonths, addMonths } from 'date-fns';
6
+ import { subDays, format, parseISO, isValid, addMinutes, differenceInMinutes, formatDistanceToNow, isToday, isFuture, addDays, startOfDay, isBefore, startOfMonth, endOfMonth, eachDayOfInterval, getDay, isSameDay, isWithinInterval, subMonths, addMonths } from 'date-fns';
7
7
  import mixpanel from 'mixpanel-browser';
8
8
  import { EventEmitter } from 'events';
9
9
  import { createClient, REALTIME_SUBSCRIBE_STATES } from '@supabase/supabase-js';
@@ -11,13 +11,13 @@ import Hls3, { Events, ErrorTypes } from 'hls.js';
11
11
  import useSWR from 'swr';
12
12
  import { noop, warning, invariant, progress, secondsToMilliseconds, millisecondsToSeconds, memo as memo$1 } from 'motion-utils';
13
13
  import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
14
- import { Camera, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ArrowDown, ArrowUp, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, Wrench, XCircle, Package, UserX, Zap, HelpCircle, AlertTriangle, Tag, Palette, CheckCircle2, RefreshCw, TrendingDown, FolderOpen, Folder, Sliders, Activity, Layers, Filter, Search, Edit2, ArrowRight, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, MessageSquare, Menu, Send, Copy, UserCheck, LogOut, Settings, LifeBuoy, EyeOff, UserCircle } from 'lucide-react';
14
+ import { Camera, ChevronDown, ChevronUp, Check, Map as Map$1, Video, ShieldCheck, Star, Award, ArrowLeft, X, Coffee, Plus, Clock, Calendar, Save, AlertCircle, Loader2, Minus, ArrowDown, ArrowUp, ChevronLeft, ChevronRight, TrendingUp, Sparkles, Pause, Play, Wrench, XCircle, Package, UserX, Zap, HelpCircle, AlertTriangle, Tag, Palette, CheckCircle2, RefreshCw, TrendingDown, FolderOpen, Folder, Sliders, Activity, Layers, Filter, Search, Edit2, ArrowRight, CheckCircle, User, Users, Shield, Building2, Mail, Lock, Info, Share2, Trophy, Target, Download, Sun, Moon, MousePointer, UserPlus, UserCog, Trash2, Eye, MoreVertical, BarChart3, UserCheck, LogOut, MessageSquare, Settings, LifeBuoy, EyeOff, UserCircle } from 'lucide-react';
15
15
  import { toast } from 'sonner';
16
- import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell, ComposedChart, Area, ScatterChart, Scatter } from 'recharts';
16
+ import { BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, ReferenceLine, Tooltip, Legend, Bar, LabelList, ResponsiveContainer, LineChart as LineChart$1, Line, PieChart, Pie, Cell } from 'recharts';
17
17
  import { Slot } from '@radix-ui/react-slot';
18
18
  import * as SelectPrimitive from '@radix-ui/react-select';
19
19
  import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
20
- import { XMarkIcon, ArrowRightIcon, HomeIcon, TrophyIcon, ChartBarIcon, LightBulbIcon, AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, TicketIcon, CubeIcon, SparklesIcon, QuestionMarkCircleIcon, HeartIcon, UserCircleIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ChevronDownIcon, Bars3Icon, CheckCircleIcon, ChatBubbleLeftRightIcon, ArrowLeftIcon, XCircleIcon, FunnelIcon, CalendarIcon, ChevronRightIcon, ChevronLeftIcon, InformationCircleIcon, PlayCircleIcon } from '@heroicons/react/24/outline';
20
+ import { XMarkIcon, ArrowRightIcon, HomeIcon, TrophyIcon, ChartBarIcon, LightBulbIcon, AdjustmentsHorizontalIcon, ClockIcon, UsersIcon, TicketIcon, CubeIcon, QuestionMarkCircleIcon, HeartIcon, UserCircleIcon, ExclamationCircleIcon, EnvelopeIcon, DocumentTextIcon, ChevronUpIcon, ChevronDownIcon, Bars3Icon, CheckCircleIcon, ChatBubbleLeftRightIcon, ArrowLeftIcon, XCircleIcon, FunnelIcon, CalendarIcon, ChevronRightIcon, ChevronLeftIcon, InformationCircleIcon, PlayCircleIcon } from '@heroicons/react/24/outline';
21
21
  import { CheckIcon } from '@heroicons/react/24/solid';
22
22
  import html2canvas from 'html2canvas';
23
23
  import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
@@ -13289,7 +13289,6 @@ function useAccessControl() {
13289
13289
  "/shifts",
13290
13290
  "/supervisor-management",
13291
13291
  "/skus",
13292
- "/ai-agent",
13293
13292
  "/help",
13294
13293
  "/health",
13295
13294
  "/profile",
@@ -13305,7 +13304,6 @@ function useAccessControl() {
13305
13304
  "/shifts",
13306
13305
  "/supervisor-management",
13307
13306
  "/skus",
13308
- "/ai-agent",
13309
13307
  "/help",
13310
13308
  "/health",
13311
13309
  "/profile",
@@ -13321,7 +13319,6 @@ function useAccessControl() {
13321
13319
  "/shifts",
13322
13320
  "/supervisor-management",
13323
13321
  "/skus",
13324
- "/ai-agent",
13325
13322
  "/help",
13326
13323
  "/health",
13327
13324
  "/profile",
@@ -13336,7 +13333,6 @@ function useAccessControl() {
13336
13333
  "/targets",
13337
13334
  "/shifts",
13338
13335
  "/skus",
13339
- "/ai-agent",
13340
13336
  "/help",
13341
13337
  "/health",
13342
13338
  "/profile",
@@ -26793,7 +26789,7 @@ var HourlyOutputChartComponent = ({
26793
26789
  return { hour, minute, decimalHour };
26794
26790
  };
26795
26791
  const shiftStartTime = getTimeFromTimeString(shiftStart);
26796
- const shiftStartDateTime = React24__default.useMemo(() => {
26792
+ React24__default.useMemo(() => {
26797
26793
  if (!shiftDate || !timezone) return null;
26798
26794
  const hour = shiftStartTime.hour.toString().padStart(2, "0");
26799
26795
  const minute = shiftStartTime.minute.toString().padStart(2, "0");
@@ -26807,7 +26803,7 @@ var HourlyOutputChartComponent = ({
26807
26803
  end: clip.idle_end_time ? new Date(clip.idle_end_time) : null
26808
26804
  })).filter((clip) => clip.start && clip.end);
26809
26805
  }, [idleTimeClips]);
26810
- const getIdleReasonForRange = React24__default.useCallback((rangeStart, rangeEnd) => {
26806
+ React24__default.useCallback((rangeStart, rangeEnd) => {
26811
26807
  if (!rangeStart || !rangeEnd || idleClipRanges.length === 0) {
26812
26808
  return "Reason unavailable";
26813
26809
  }
@@ -27300,22 +27296,22 @@ var HourlyOutputChartComponent = ({
27300
27296
  const startTime = formatIdleTimestamp(range.start);
27301
27297
  const endTime = formatIdleTimestamp(range.end + 1);
27302
27298
  const fallbackIndex = chartData.findIndex((item) => item.timeRange === data2.timeRange);
27303
- const hourOffset = Number.isFinite(data2.hourIndex) ? data2.hourIndex : fallbackIndex;
27304
- const safeHourOffset = hourOffset >= 0 ? hourOffset : 0;
27305
- const rangeStartDate = shiftStartDateTime ? addMinutes(shiftStartDateTime, safeHourOffset * 60 + range.start) : null;
27306
- const rangeEndDate = shiftStartDateTime ? addMinutes(shiftStartDateTime, safeHourOffset * 60 + range.end + 1) : null;
27307
- const reasonLabel = getIdleReasonForRange(rangeStartDate, rangeEndDate);
27299
+ Number.isFinite(data2.hourIndex) ? data2.hourIndex : fallbackIndex;
27308
27300
  return /* @__PURE__ */ jsxs("div", { className: "text-gray-600 flex items-center gap-2 text-xs", children: [
27309
27301
  /* @__PURE__ */ jsx("span", { className: "inline-block w-1.5 h-1.5 bg-orange-400 rounded-full flex-shrink-0" }),
27310
- /* @__PURE__ */ jsxs("span", { children: [
27311
- duration === 1 ? /* @__PURE__ */ jsx(Fragment, { children: startTime }) : /* @__PURE__ */ jsxs(Fragment, { children: [
27312
- startTime,
27313
- " - ",
27314
- endTime
27315
- ] }),
27316
- /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: " | " }),
27317
- /* @__PURE__ */ jsx("span", { className: "text-gray-600", children: reasonLabel })
27318
- ] })
27302
+ /* @__PURE__ */ jsx("span", { children: duration === 1 ? /* @__PURE__ */ jsxs(Fragment, { children: [
27303
+ startTime,
27304
+ " (",
27305
+ duration,
27306
+ " min)"
27307
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
27308
+ startTime,
27309
+ " - ",
27310
+ endTime,
27311
+ " (",
27312
+ duration,
27313
+ " mins)"
27314
+ ] }) })
27319
27315
  ] }, index);
27320
27316
  }) })
27321
27317
  ] })
@@ -42606,17 +42602,6 @@ var SideNavBar = memo(({
42606
42602
  });
42607
42603
  onMobileMenuClose?.();
42608
42604
  }, [navigate, onMobileMenuClose]);
42609
- const handleAIAgentClick = useCallback(() => {
42610
- navigate("/ai-agent", {
42611
- trackingEvent: {
42612
- name: "AI Agent Page Clicked",
42613
- properties: {
42614
- source: "side_nav"
42615
- }
42616
- }
42617
- });
42618
- onMobileMenuClose?.();
42619
- }, [navigate, onMobileMenuClose]);
42620
42605
  const handleProfileClick = useCallback(() => {
42621
42606
  navigate("/profile", {
42622
42607
  trackingEvent: {
@@ -42674,7 +42659,6 @@ var SideNavBar = memo(({
42674
42659
  const teamManagementButtonClasses = useMemo(() => getButtonClasses("/team-management"), [getButtonClasses, pathname]);
42675
42660
  const ticketsButtonClasses = useMemo(() => getButtonClasses("/tickets"), [getButtonClasses, pathname]);
42676
42661
  useMemo(() => getButtonClasses("/supervisor-management"), [getButtonClasses, pathname]);
42677
- const aiAgentButtonClasses = useMemo(() => getButtonClasses("/ai-agent"), [getButtonClasses, pathname]);
42678
42662
  const profileButtonClasses = useMemo(() => getButtonClasses("/profile"), [getButtonClasses, pathname]);
42679
42663
  const helpButtonClasses = useMemo(() => getButtonClasses("/help"), [getButtonClasses, pathname]);
42680
42664
  const skusButtonClasses = useMemo(() => getButtonClasses("/skus"), [getButtonClasses, pathname]);
@@ -42828,24 +42812,6 @@ var SideNavBar = memo(({
42828
42812
  ]
42829
42813
  }
42830
42814
  ),
42831
- /* @__PURE__ */ jsxs(
42832
- "button",
42833
- {
42834
- onClick: handleAIAgentClick,
42835
- className: aiAgentButtonClasses,
42836
- "aria-label": "AI Manufacturing Expert",
42837
- tabIndex: 0,
42838
- role: "tab",
42839
- "aria-selected": pathname === "/ai-agent" || pathname.startsWith("/ai-agent/"),
42840
- children: [
42841
- /* @__PURE__ */ jsx(SparklesIcon, { className: "w-5 h-5 mb-1" }),
42842
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
42843
- /* @__PURE__ */ jsx("span", { className: "text-xs sm:text-[10px] font-medium leading-tight", children: "Axel" }),
42844
- /* @__PURE__ */ jsx("span", { className: "text-[8px] px-1.5 py-0.5 bg-orange-100 text-orange-600 rounded-full font-medium leading-none mt-0.5", children: "BETA" })
42845
- ] })
42846
- ]
42847
- }
42848
- ),
42849
42815
  /* @__PURE__ */ jsxs(
42850
42816
  "button",
42851
42817
  {
@@ -43026,21 +42992,6 @@ var SideNavBar = memo(({
43026
42992
  ]
43027
42993
  }
43028
42994
  ),
43029
- /* @__PURE__ */ jsxs(
43030
- "button",
43031
- {
43032
- onClick: handleMobileNavClick(handleAIAgentClick),
43033
- className: getMobileButtonClass("/ai-agent"),
43034
- "aria-label": "AI Manufacturing Expert",
43035
- children: [
43036
- /* @__PURE__ */ jsx(SparklesIcon, { className: getIconClass("/ai-agent") }),
43037
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
43038
- /* @__PURE__ */ jsx("span", { className: "text-base font-medium", children: "Axel AI" }),
43039
- /* @__PURE__ */ jsx("span", { className: "text-xs px-2 py-0.5 bg-orange-100 text-orange-600 rounded-full font-medium leading-none mt-1 self-start", children: "BETA" })
43040
- ] })
43041
- ]
43042
- }
43043
- ),
43044
42995
  /* @__PURE__ */ jsxs(
43045
42996
  "button",
43046
42997
  {
@@ -43228,7 +43179,6 @@ var Header = ({
43228
43179
  if (pathname === "/") return "Factory View";
43229
43180
  if (pathname.startsWith("/workspace/")) return "Workspace Details";
43230
43181
  if (pathname.startsWith("/kpis/")) return "Line KPIs";
43231
- if (pathname.startsWith("/ai-agent")) return "Axel - AI Manufacturing Expert";
43232
43182
  return "Optifye";
43233
43183
  };
43234
43184
  const handleLogout = async () => {
@@ -47197,2056 +47147,6 @@ var AcceptInviteView = (props) => {
47197
47147
  return /* @__PURE__ */ jsx(AcceptInvite, { ...props });
47198
47148
  };
47199
47149
  var AcceptInviteView_default = AcceptInviteView;
47200
- var ThreadSidebar = ({
47201
- activeThreadId,
47202
- onSelectThread,
47203
- onNewThread,
47204
- className = ""
47205
- }) => {
47206
- const { threads, isLoading, error, deleteThread: deleteThread2 } = useThreads();
47207
- const [deletingId, setDeletingId] = useState(null);
47208
- const handleDelete = async (e, threadId) => {
47209
- e.stopPropagation();
47210
- if (confirm("Are you sure you want to delete this conversation?")) {
47211
- setDeletingId(threadId);
47212
- try {
47213
- await deleteThread2(threadId);
47214
- if (activeThreadId === threadId) {
47215
- onNewThread();
47216
- }
47217
- } catch (error2) {
47218
- console.error("Error deleting thread:", error2);
47219
- alert("Failed to delete conversation. Please try again.");
47220
- } finally {
47221
- setDeletingId(null);
47222
- }
47223
- }
47224
- };
47225
- const formatDate2 = (dateString) => {
47226
- const date = new Date(dateString);
47227
- const now2 = /* @__PURE__ */ new Date();
47228
- const diffMs = now2.getTime() - date.getTime();
47229
- const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
47230
- if (diffDays === 0) {
47231
- return "Today";
47232
- } else if (diffDays === 1) {
47233
- return "Yesterday";
47234
- } else if (diffDays < 7) {
47235
- return date.toLocaleDateString("en-US", { weekday: "short" });
47236
- } else {
47237
- return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
47238
- }
47239
- };
47240
- if (error) {
47241
- return /* @__PURE__ */ jsx("div", { className: `p-4 text-red-600 text-sm ${className}`, children: "Failed to load conversations" });
47242
- }
47243
- return /* @__PURE__ */ jsxs("div", { className: `flex flex-col h-screen bg-gray-50 border-r border-gray-200 ${className}`, children: [
47244
- /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 p-4 border-b border-gray-200", children: [
47245
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Chat History" }),
47246
- /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-1", children: "Your previous conversations" })
47247
- ] }),
47248
- /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto min-h-0", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center p-8", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "sm" }) }) : threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-gray-500 text-sm", children: "No conversations yet" }) : /* @__PURE__ */ jsx("div", { className: "py-2", children: threads.map((thread) => /* @__PURE__ */ jsxs(
47249
- "div",
47250
- {
47251
- onClick: () => onSelectThread(thread.id),
47252
- className: `group relative flex items-start gap-3 px-4 py-3 cursor-pointer transition-all ${activeThreadId === thread.id ? "bg-blue-50 border-l-4 border-blue-600 hover:bg-blue-100" : "hover:bg-gray-100 border-l-4 border-transparent"}`,
47253
- children: [
47254
- /* @__PURE__ */ jsx(MessageSquare, { className: `w-4 h-4 mt-0.5 flex-shrink-0 ${activeThreadId === thread.id ? "text-blue-600" : "text-gray-400"}` }),
47255
- /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
47256
- /* @__PURE__ */ jsx("h3", { className: `text-sm font-medium truncate ${activeThreadId === thread.id ? "text-blue-900" : "text-gray-900"}`, children: thread.title || "Untitled Chat" }),
47257
- /* @__PURE__ */ jsx("p", { className: `text-xs mt-0.5 ${activeThreadId === thread.id ? "text-blue-700" : "text-gray-500"}`, children: formatDate2(thread.created_at) })
47258
- ] }),
47259
- deletingId === thread.id ? /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(
47260
- "button",
47261
- {
47262
- onClick: (e) => handleDelete(e, thread.id),
47263
- className: "flex-shrink-0 opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-200 rounded transition-all",
47264
- title: "Delete conversation",
47265
- children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5 text-gray-500" })
47266
- }
47267
- )
47268
- ]
47269
- },
47270
- thread.id
47271
- )) }) }),
47272
- /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 p-4 border-t border-gray-200", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 text-center", children: [
47273
- threads.length,
47274
- " conversation",
47275
- threads.length !== 1 ? "s" : ""
47276
- ] }) })
47277
- ] });
47278
- };
47279
- var ProfilePicture = React24__default.memo(({
47280
- alt = "Axel",
47281
- className = "",
47282
- size = "md",
47283
- animate = false
47284
- }) => {
47285
- return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(AxelOrb, { size, animate }) });
47286
- });
47287
- ProfilePicture.displayName = "ProfilePicture";
47288
- var GREETING_MESSAGES = [
47289
- "How can I help you today?",
47290
- "What would you like to know?",
47291
- "Ready to optimize your operations?",
47292
- "How can I assist you today?"
47293
- ];
47294
- var getDailyGreeting = () => {
47295
- const now2 = /* @__PURE__ */ new Date();
47296
- const startOfYear = new Date(now2.getFullYear(), 0, 0);
47297
- const diff = now2.getTime() - startOfYear.getTime();
47298
- const oneDay = 1e3 * 60 * 60 * 24;
47299
- const dayOfYear = Math.floor(diff / oneDay);
47300
- const index = dayOfYear % GREETING_MESSAGES.length;
47301
- return GREETING_MESSAGES[index];
47302
- };
47303
- var AIAgentView = () => {
47304
- const { navigate, pathname } = useNavigation();
47305
- const config = useDashboardConfig();
47306
- const entityConfig = useEntityConfig();
47307
- const dateTimeConfig = useDateTimeConfig();
47308
- const shiftConfig = useShiftConfig();
47309
- const { formatNumber } = useFormatNumber();
47310
- const [inputValue, setInputValue] = useState("");
47311
- const [loadingThreads, setLoadingThreads] = useState(/* @__PURE__ */ new Set());
47312
- const [lastError, setLastError] = useState(null);
47313
- const [copiedMessageId, setCopiedMessageId] = useState(null);
47314
- const [activeThreadId, setActiveThreadId] = useState(void 0);
47315
- const [isSidebarOpen, setIsSidebarOpen] = useState(false);
47316
- const [streamingStates, setStreamingStates] = useState(/* @__PURE__ */ new Map());
47317
- const [userId, setUserId] = useState(null);
47318
- const [pendingThreadId, setPendingThreadId] = useState(null);
47319
- const [isTransitioning, setIsTransitioning] = useState(false);
47320
- const [typedText, setTypedText] = useState("");
47321
- const [newChatCount, setNewChatCount] = useState(0);
47322
- const [greetingReset, setGreetingReset] = useState(0);
47323
- const [hasStartedTyping, setHasStartedTyping] = useState(false);
47324
- const [typingStartTime, setTypingStartTime] = useState(null);
47325
- const [lastTypingTime, setLastTypingTime] = useState(null);
47326
- const [characterCount, setCharacterCount] = useState(0);
47327
- const typingTimeoutRef = useRef(null);
47328
- const currentGreeting = useMemo(() => getDailyGreeting(), [greetingReset]);
47329
- const isThreadLoading = (threadId) => {
47330
- return threadId ? loadingThreads.has(threadId) : false;
47331
- };
47332
- const getStreamingState = (threadId) => {
47333
- return threadId ? streamingStates.get(threadId) || { message: "", reasoning: "" } : { message: "", reasoning: "" };
47334
- };
47335
- const trackTypingStart = () => {
47336
- if (!hasStartedTyping) {
47337
- const now2 = Date.now();
47338
- setHasStartedTyping(true);
47339
- setTypingStartTime(now2);
47340
- setLastTypingTime(now2);
47341
- trackCoreEvent("AI Agent Input Started", {
47342
- line_id: lineId,
47343
- company_id: companyId,
47344
- shift_id: shiftId,
47345
- active_thread_id: activeThreadId,
47346
- has_existing_messages: messages.length > 0,
47347
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
47348
- });
47349
- }
47350
- };
47351
- const trackTypingProgress = (newValue) => {
47352
- const now2 = Date.now();
47353
- setLastTypingTime(now2);
47354
- setCharacterCount(newValue.length);
47355
- if (typingTimeoutRef.current) {
47356
- clearTimeout(typingTimeoutRef.current);
47357
- }
47358
- typingTimeoutRef.current = setTimeout(() => {
47359
- if (hasStartedTyping && typingStartTime && newValue.length > 0) {
47360
- const typingDuration = now2 - typingStartTime;
47361
- trackCoreEvent("AI Agent Input Typing Progress", {
47362
- line_id: lineId,
47363
- company_id: companyId,
47364
- shift_id: shiftId,
47365
- active_thread_id: activeThreadId,
47366
- character_count: newValue.length,
47367
- typing_duration_ms: typingDuration,
47368
- has_existing_messages: messages.length > 0,
47369
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
47370
- });
47371
- }
47372
- }, 2e3);
47373
- };
47374
- const trackMessageSent = (messageContent) => {
47375
- if (hasStartedTyping && typingStartTime) {
47376
- const now2 = Date.now();
47377
- const totalTypingDuration = now2 - typingStartTime;
47378
- trackCoreEvent("AI Agent Message Sent", {
47379
- line_id: lineId,
47380
- company_id: companyId,
47381
- shift_id: shiftId,
47382
- active_thread_id: activeThreadId,
47383
- message_length: messageContent.length,
47384
- character_count: messageContent.length,
47385
- typing_duration_ms: totalTypingDuration,
47386
- has_existing_messages: messages.length > 0,
47387
- is_new_conversation: !activeThreadId,
47388
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
47389
- });
47390
- }
47391
- resetTypingState();
47392
- };
47393
- const resetTypingState = () => {
47394
- setHasStartedTyping(false);
47395
- setTypingStartTime(null);
47396
- setLastTypingTime(null);
47397
- setCharacterCount(0);
47398
- if (typingTimeoutRef.current) {
47399
- clearTimeout(typingTimeoutRef.current);
47400
- typingTimeoutRef.current = null;
47401
- }
47402
- };
47403
- const textareaRef = useRef(null);
47404
- const messagesEndRef = useRef(null);
47405
- const containerRef = useRef(null);
47406
- const renderedContentCache = useRef(/* @__PURE__ */ new Map());
47407
- const { createThread, mutate: mutateThreads } = useThreads();
47408
- const { messages, addMessage, setMessages } = useMessages(activeThreadId);
47409
- const agnoApiUrl = config.endpoints?.agnoApiUrl || "https://fastapi-production-111f9.up.railway.app";
47410
- const sseClient = useMemo(() => {
47411
- console.log("[AIAgentView] Using AGNO API URL:", agnoApiUrl);
47412
- return new SSEChatClient(agnoApiUrl);
47413
- }, [agnoApiUrl]);
47414
- const getLineIdFromPath = () => {
47415
- const pathParts = pathname.split("/");
47416
- const lineIdIndex = pathParts.findIndex((part) => part === "ai-agent") + 1;
47417
- if (lineIdIndex > 0 && lineIdIndex < pathParts.length) {
47418
- return pathParts[lineIdIndex];
47419
- }
47420
- return entityConfig.defaultLineId || LINE_1_UUID;
47421
- };
47422
- const lineId = getLineIdFromPath();
47423
- const { shiftId } = getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig);
47424
- const companyId = entityConfig.companyId || "default-company-id";
47425
- const configuredLineIds = getConfiguredLineIds(entityConfig);
47426
- const lineDisplayNames = getAllLineDisplayNames(entityConfig);
47427
- const allLines = configuredLineIds.map((id3) => ({
47428
- id: id3,
47429
- name: lineDisplayNames[id3] || `Line ${id3.substring(0, 8)}`
47430
- }));
47431
- const ACTIVE_THREAD_STORAGE_KEY = `ai-agent-active-thread-${lineId}`;
47432
- useLayoutEffect(() => {
47433
- const savedThreadId = localStorage.getItem(ACTIVE_THREAD_STORAGE_KEY);
47434
- if (savedThreadId && savedThreadId !== "undefined") {
47435
- setActiveThreadId(savedThreadId);
47436
- }
47437
- }, [ACTIVE_THREAD_STORAGE_KEY]);
47438
- useEffect(() => {
47439
- if (activeThreadId) {
47440
- localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
47441
- } else {
47442
- localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
47443
- }
47444
- }, [activeThreadId, ACTIVE_THREAD_STORAGE_KEY]);
47445
- useEffect(() => {
47446
- const handleVisibilityChange = () => {
47447
- if (document.visibilityState === "hidden" && activeThreadId) {
47448
- localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
47449
- }
47450
- };
47451
- const handleBeforeUnload = () => {
47452
- if (activeThreadId) {
47453
- localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
47454
- }
47455
- };
47456
- document.addEventListener("visibilitychange", handleVisibilityChange);
47457
- window.addEventListener("beforeunload", handleBeforeUnload);
47458
- return () => {
47459
- document.removeEventListener("visibilitychange", handleVisibilityChange);
47460
- window.removeEventListener("beforeunload", handleBeforeUnload);
47461
- if (activeThreadId) {
47462
- localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
47463
- }
47464
- };
47465
- }, [activeThreadId, ACTIVE_THREAD_STORAGE_KEY]);
47466
- useEffect(() => {
47467
- if (textareaRef.current) {
47468
- textareaRef.current.style.height = "auto";
47469
- textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 120)}px`;
47470
- }
47471
- }, [inputValue]);
47472
- const scrollToBottom = () => {
47473
- messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
47474
- };
47475
- useEffect(() => {
47476
- if (activeThreadId && messages.length > 0) {
47477
- setTimeout(scrollToBottom, 100);
47478
- }
47479
- }, [activeThreadId]);
47480
- useEffect(() => {
47481
- if (messages.length === 0 && !isTransitioning) {
47482
- let index = 0;
47483
- setTypedText("");
47484
- const typeInterval = setInterval(() => {
47485
- if (index < currentGreeting.length) {
47486
- setTypedText(currentGreeting.substring(0, index + 1));
47487
- index++;
47488
- } else {
47489
- clearInterval(typeInterval);
47490
- }
47491
- }, 50);
47492
- return () => clearInterval(typeInterval);
47493
- }
47494
- }, [messages.length, isTransitioning, greetingReset, currentGreeting]);
47495
- useEffect(() => {
47496
- if (isSidebarOpen) {
47497
- setNewChatCount(0);
47498
- }
47499
- }, [isSidebarOpen]);
47500
- const copyToClipboard = async (text, messageId) => {
47501
- try {
47502
- await navigator.clipboard.writeText(text);
47503
- setCopiedMessageId(messageId);
47504
- setTimeout(() => setCopiedMessageId(null), 2e3);
47505
- } catch (err) {
47506
- console.error("Failed to copy text: ", err);
47507
- }
47508
- };
47509
- const handleNewThread = () => {
47510
- setActiveThreadId(void 0);
47511
- setMessages([]);
47512
- setInputValue("");
47513
- setPendingThreadId(null);
47514
- setTypedText("");
47515
- setGreetingReset((prev) => prev + 1);
47516
- resetTypingState();
47517
- localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
47518
- textareaRef.current?.focus();
47519
- };
47520
- useEffect(() => {
47521
- return () => {
47522
- if (typingTimeoutRef.current) {
47523
- clearTimeout(typingTimeoutRef.current);
47524
- }
47525
- };
47526
- }, []);
47527
- useEffect(() => {
47528
- const checkAuth = async () => {
47529
- const supabase2 = _getSupabaseInstance();
47530
- const { data: { session } } = await supabase2.auth.getSession();
47531
- if (session?.user) {
47532
- setUserId(session.user.id);
47533
- console.log("[AIAgentView] User authenticated:", session.user.id);
47534
- } else {
47535
- console.log("[AIAgentView] No authenticated session found");
47536
- }
47537
- };
47538
- checkAuth();
47539
- const supabase = _getSupabaseInstance();
47540
- const { data: { subscription } } = supabase.auth.onAuthStateChange((event, session) => {
47541
- if (session?.user) {
47542
- setUserId(session.user.id);
47543
- } else {
47544
- setUserId(null);
47545
- }
47546
- });
47547
- return () => {
47548
- subscription.unsubscribe();
47549
- };
47550
- }, []);
47551
- const handleSubmit = async (e) => {
47552
- e.preventDefault();
47553
- if (!inputValue.trim() || !userId) return;
47554
- let currentThreadId = activeThreadId || `temp-${Date.now()}`;
47555
- if (isThreadLoading(currentThreadId)) return;
47556
- const userMessage = inputValue.trim();
47557
- trackMessageSent(userMessage);
47558
- if (displayMessages.length === 0) {
47559
- setIsTransitioning(true);
47560
- setTimeout(() => {
47561
- setIsTransitioning(false);
47562
- }, 800);
47563
- }
47564
- setInputValue("");
47565
- setLoadingThreads((prev) => new Set(prev).add(currentThreadId));
47566
- setLastError(null);
47567
- if (!activeThreadId) {
47568
- setPendingThreadId(currentThreadId);
47569
- }
47570
- setStreamingStates((prev) => {
47571
- const newMap = new Map(prev);
47572
- newMap.set(currentThreadId, { message: "", reasoning: "" });
47573
- return newMap;
47574
- });
47575
- const tempUserMessage = {
47576
- id: Date.now(),
47577
- // Temporary ID
47578
- thread_id: activeThreadId || "",
47579
- role: "user",
47580
- content: userMessage,
47581
- reasoning: null,
47582
- model_id: null,
47583
- token_usage: null,
47584
- metadata: null,
47585
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
47586
- position: messages.length
47587
- };
47588
- setMessages((prev) => [...prev, tempUserMessage]);
47589
- setTimeout(scrollToBottom, 100);
47590
- try {
47591
- await sseClient.sendMessage(
47592
- userMessage,
47593
- userId,
47594
- activeThreadId || null,
47595
- {
47596
- companyId,
47597
- lineId,
47598
- shiftId,
47599
- allLines
47600
- },
47601
- {
47602
- onThreadCreated: (threadId) => {
47603
- if (!activeThreadId) {
47604
- const oldThreadId = currentThreadId;
47605
- currentThreadId = threadId;
47606
- setActiveThreadId(threadId);
47607
- setPendingThreadId(null);
47608
- if (!isSidebarOpen) {
47609
- setNewChatCount((prev) => prev + 1);
47610
- }
47611
- setLoadingThreads((prev) => {
47612
- const newSet = new Set(prev);
47613
- if (newSet.has(oldThreadId)) {
47614
- newSet.delete(oldThreadId);
47615
- newSet.add(threadId);
47616
- }
47617
- return newSet;
47618
- });
47619
- setStreamingStates((prev) => {
47620
- const newMap = new Map(prev);
47621
- const streamingState = newMap.get(oldThreadId);
47622
- if (streamingState) {
47623
- newMap.delete(oldThreadId);
47624
- newMap.set(threadId, streamingState);
47625
- }
47626
- return newMap;
47627
- });
47628
- mutateThreads();
47629
- }
47630
- },
47631
- onMessage: (text) => {
47632
- setStreamingStates((prev) => {
47633
- const newMap = new Map(prev);
47634
- const current = newMap.get(currentThreadId) || { message: "", reasoning: "" };
47635
- newMap.set(currentThreadId, { ...current, message: current.message + text });
47636
- return newMap;
47637
- });
47638
- },
47639
- onComplete: async (messageId) => {
47640
- if (currentThreadId && !currentThreadId.startsWith("temp-")) {
47641
- const updatedMessages = await getAllThreadMessages(currentThreadId);
47642
- setMessages(updatedMessages);
47643
- }
47644
- setStreamingStates((prev) => {
47645
- const newMap = new Map(prev);
47646
- newMap.delete(currentThreadId);
47647
- return newMap;
47648
- });
47649
- setLoadingThreads((prev) => {
47650
- const newSet = new Set(prev);
47651
- newSet.delete(currentThreadId);
47652
- return newSet;
47653
- });
47654
- if (!activeThreadId) {
47655
- setPendingThreadId(null);
47656
- }
47657
- },
47658
- onError: (error) => {
47659
- console.error("Chat error:", error);
47660
- setLastError(error);
47661
- setLoadingThreads((prev) => {
47662
- const newSet = new Set(prev);
47663
- newSet.delete(currentThreadId);
47664
- return newSet;
47665
- });
47666
- setStreamingStates((prev) => {
47667
- const newMap = new Map(prev);
47668
- newMap.delete(currentThreadId);
47669
- return newMap;
47670
- });
47671
- if (!activeThreadId) {
47672
- setPendingThreadId(null);
47673
- }
47674
- setMessages((prev) => prev.slice(0, -1));
47675
- }
47676
- }
47677
- );
47678
- } catch (error) {
47679
- console.error("[AIAgentView] Error in chat:", error);
47680
- const errorMessage = error instanceof Error ? error.message : "An unexpected error occurred";
47681
- setLastError(errorMessage);
47682
- setLoadingThreads((prev) => {
47683
- const newSet = new Set(prev);
47684
- newSet.delete(currentThreadId);
47685
- return newSet;
47686
- });
47687
- setStreamingStates((prev) => {
47688
- const newMap = new Map(prev);
47689
- newMap.delete(currentThreadId);
47690
- return newMap;
47691
- });
47692
- if (!activeThreadId) {
47693
- setPendingThreadId(null);
47694
- }
47695
- setMessages((prev) => prev.slice(0, -1));
47696
- }
47697
- };
47698
- const handleKeyDown = (e) => {
47699
- if (e.key === "Enter" && !e.shiftKey) {
47700
- e.preventDefault();
47701
- if (!isCurrentThreadLoading) {
47702
- handleSubmit(e);
47703
- }
47704
- }
47705
- };
47706
- const formatMessage = (content) => {
47707
- const processInlineFormatting = (text) => {
47708
- text = text.replace(/\*\*(.*?)\*\*/g, '<strong class="font-semibold text-gray-900">$1</strong>');
47709
- text = text.replace(/`([^`]+)`/g, '<code class="bg-gray-100 px-1.5 py-0.5 rounded text-sm font-mono text-gray-800">$1</code>');
47710
- return text;
47711
- };
47712
- const parseTableFromText = (lines2, startIndex) => {
47713
- const tableLines = [];
47714
- let i = startIndex;
47715
- while (i < lines2.length) {
47716
- const line = lines2[i].trim();
47717
- if (!line) {
47718
- i++;
47719
- break;
47720
- }
47721
- if (line.includes("|") || line.match(/^[-|=\s]+$/)) {
47722
- tableLines.push(line);
47723
- i++;
47724
- } else {
47725
- break;
47726
- }
47727
- }
47728
- if (tableLines.length === 0) return { html: "", endIndex: startIndex };
47729
- const dataLines = tableLines.filter((line) => !line.match(/^[-|=\s]+$/));
47730
- if (dataLines.length === 0) return { html: "", endIndex: i };
47731
- let headerRow = [];
47732
- let dataRows = [];
47733
- const firstLine = dataLines[0];
47734
- if (firstLine.includes("|")) {
47735
- const cells = firstLine.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
47736
- if (cells.length >= 2) {
47737
- headerRow = cells;
47738
- for (let j = 1; j < dataLines.length; j++) {
47739
- const row = dataLines[j];
47740
- if (row.includes("|")) {
47741
- const rowCells = row.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
47742
- while (rowCells.length < headerRow.length) rowCells.push("");
47743
- if (rowCells.length > headerRow.length) rowCells.splice(headerRow.length);
47744
- dataRows.push(rowCells);
47745
- }
47746
- }
47747
- }
47748
- }
47749
- if (headerRow.length === 0) {
47750
- for (const line of dataLines) {
47751
- if (line.includes("|")) {
47752
- const rowCells = line.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
47753
- if (rowCells.length >= 2) {
47754
- dataRows.push(rowCells);
47755
- }
47756
- }
47757
- }
47758
- if (dataRows.length > 0 && dataRows[0].length > 0) {
47759
- headerRow = dataRows[0].map((_, index) => `Column ${index + 1}`);
47760
- }
47761
- }
47762
- if (headerRow.length > 0 && dataRows.length > 0) {
47763
- let tableHtml = '<div class="overflow-x-auto my-4"><table class="min-w-full border-collapse border border-gray-300 rounded-lg shadow-sm">';
47764
- tableHtml += '<thead class="bg-gray-50">';
47765
- tableHtml += "<tr>";
47766
- headerRow.forEach((header) => {
47767
- tableHtml += `<th class="border border-gray-300 px-4 py-2 text-left font-semibold text-gray-900">${processInlineFormatting(header)}</th>`;
47768
- });
47769
- tableHtml += "</tr>";
47770
- tableHtml += "</thead>";
47771
- tableHtml += '<tbody class="bg-white divide-y divide-gray-200">';
47772
- dataRows.forEach((row, rowIndex) => {
47773
- tableHtml += `<tr class="${rowIndex % 2 === 0 ? "bg-white" : "bg-gray-50"}">`;
47774
- row.forEach((cell) => {
47775
- tableHtml += `<td class="border border-gray-300 px-4 py-2 text-gray-800">${processInlineFormatting(cell)}</td>`;
47776
- });
47777
- tableHtml += "</tr>";
47778
- });
47779
- tableHtml += "</tbody>";
47780
- tableHtml += "</table></div>";
47781
- return { html: tableHtml, endIndex: i };
47782
- }
47783
- return { html: "", endIndex: startIndex };
47784
- };
47785
- const processedContent = content;
47786
- const lines = processedContent.split("\n");
47787
- const formattedLines = [];
47788
- let inList = false;
47789
- for (let i = 0; i < lines.length; i++) {
47790
- let line = lines[i];
47791
- const trimmedLine = line.trim();
47792
- if (!trimmedLine) {
47793
- if (inList) {
47794
- formattedLines.push("</ul>");
47795
- inList = false;
47796
- }
47797
- formattedLines.push("<br/>");
47798
- continue;
47799
- }
47800
- if (trimmedLine.includes("|") && (trimmedLine.match(/\|/g) || []).length >= 1) {
47801
- if (inList) {
47802
- formattedLines.push("</ul>");
47803
- inList = false;
47804
- }
47805
- const tableResult = parseTableFromText(lines, i);
47806
- if (tableResult.html) {
47807
- formattedLines.push(tableResult.html);
47808
- i = tableResult.endIndex - 1;
47809
- continue;
47810
- }
47811
- }
47812
- if (trimmedLine.startsWith("###")) {
47813
- if (inList) {
47814
- formattedLines.push("</ul>");
47815
- inList = false;
47816
- }
47817
- const headerText = processInlineFormatting(trimmedLine.replace(/^###\s*/, ""));
47818
- formattedLines.push(`<h3 class="text-lg font-semibold text-gray-900 mt-4 mb-2">${headerText}</h3>`);
47819
- continue;
47820
- } else if (trimmedLine.startsWith("##")) {
47821
- if (inList) {
47822
- formattedLines.push("</ul>");
47823
- inList = false;
47824
- }
47825
- const headerText = processInlineFormatting(trimmedLine.replace(/^##\s*/, ""));
47826
- formattedLines.push(`<h2 class="text-xl font-semibold text-gray-900 mt-4 mb-2">${headerText}</h2>`);
47827
- continue;
47828
- } else if (trimmedLine.startsWith("#")) {
47829
- if (inList) {
47830
- formattedLines.push("</ul>");
47831
- inList = false;
47832
- }
47833
- const headerText = processInlineFormatting(trimmedLine.replace(/^#\s*/, ""));
47834
- formattedLines.push(`<h1 class="text-3xl font-semibold text-gray-900 mt-4 mb-3">${headerText}</h1>`);
47835
- continue;
47836
- }
47837
- const listMatch = trimmedLine.match(/^([-*•]\s+|\d+\.\s+|^\s*[-*•]\s+)/);
47838
- if (listMatch) {
47839
- if (!inList) {
47840
- formattedLines.push('<ul class="space-y-1 mt-2 mb-2">');
47841
- inList = true;
47842
- }
47843
- const listContent = processInlineFormatting(trimmedLine.replace(/^([-*•]\s+|\d+\.\s+|\s*[-*•]\s+)/, ""));
47844
- formattedLines.push(`<li class="ml-4 text-gray-700 flex items-start"><span class="mr-2 text-gray-500">\u2022</span><span>${listContent}</span></li>`);
47845
- continue;
47846
- } else if (inList) {
47847
- formattedLines.push("</ul>");
47848
- inList = false;
47849
- }
47850
- if (trimmedLine.match(/^---+$/)) {
47851
- formattedLines.push('<hr class="my-4 border-gray-200"/>');
47852
- continue;
47853
- }
47854
- if (trimmedLine) {
47855
- const processedLine = processInlineFormatting(line);
47856
- if (trimmedLine.endsWith(":") && trimmedLine.length < 50 && !trimmedLine.includes("**")) {
47857
- formattedLines.push(`<h3 class="text-lg font-semibold text-gray-900 mt-4 mb-2">${processedLine}</h3>`);
47858
- } else {
47859
- formattedLines.push(`<p class="text-gray-800 leading-relaxed mb-2">${processedLine}</p>`);
47860
- }
47861
- }
47862
- }
47863
- if (inList) {
47864
- formattedLines.push("</ul>");
47865
- }
47866
- return formattedLines.join("");
47867
- };
47868
- const formatTime5 = (timestamp) => {
47869
- const date = new Date(timestamp);
47870
- return date.toLocaleTimeString([], {
47871
- hour: "2-digit",
47872
- minute: "2-digit",
47873
- hour12: false
47874
- });
47875
- };
47876
- const displayMessages = [...messages];
47877
- const effectiveThreadId = activeThreadId || pendingThreadId || void 0;
47878
- const currentStreaming = getStreamingState(effectiveThreadId);
47879
- const isCurrentThreadLoading = isThreadLoading(effectiveThreadId);
47880
- if (isCurrentThreadLoading && currentStreaming.message) {
47881
- displayMessages.push({
47882
- id: -1,
47883
- // Use -1 for streaming message to identify it
47884
- thread_id: activeThreadId || "",
47885
- role: "assistant",
47886
- content: currentStreaming.message,
47887
- reasoning: currentStreaming.reasoning || null,
47888
- model_id: "gpt-4o-mini",
47889
- token_usage: null,
47890
- metadata: null,
47891
- created_at: (/* @__PURE__ */ new Date()).toISOString(),
47892
- position: messages.length
47893
- });
47894
- }
47895
- const renderAssistantContent = (content) => {
47896
- const cached = renderedContentCache.current.get(content);
47897
- if (cached) {
47898
- return cached;
47899
- }
47900
- const parseChartPatterns = (text) => {
47901
- const chartElements = [];
47902
- let lastIndex = 0;
47903
- console.log("[DEBUG] Parsing chart patterns from text:", text);
47904
- const chartRegex = /\[\s*(?:Calling\s+|CALL\s+)?(create_[a-z_]+)\s*\(([\s\S]*?)\)\s*\]/g;
47905
- let match;
47906
- const processedIndices = /* @__PURE__ */ new Set();
47907
- let matchCount = 0;
47908
- while ((match = chartRegex.exec(text)) !== null) {
47909
- matchCount++;
47910
- const startIndex = match.index;
47911
- const endIndex = startIndex + match[0].length;
47912
- console.log(`[DEBUG] Found chart pattern #${matchCount}:`, {
47913
- fullMatch: match[0],
47914
- chartType: match[1],
47915
- argsString: match[2],
47916
- startIndex,
47917
- endIndex
47918
- });
47919
- if (!processedIndices.has(startIndex)) {
47920
- processedIndices.add(startIndex);
47921
- if (startIndex > lastIndex) {
47922
- const beforeText = text.substring(lastIndex, startIndex);
47923
- chartElements.push(
47924
- /* @__PURE__ */ jsx(
47925
- "div",
47926
- {
47927
- dangerouslySetInnerHTML: { __html: formatMessage(beforeText) }
47928
- },
47929
- `text-${lastIndex}`
47930
- )
47931
- );
47932
- }
47933
- const chartType = match[1];
47934
- const argsString = match[2];
47935
- try {
47936
- const args = parseChartArguments(argsString);
47937
- const chartElement = renderChart(chartType, args, startIndex);
47938
- if (chartElement) {
47939
- console.log(`[DEBUG] Successfully rendered chart: ${chartType}`);
47940
- chartElements.push(chartElement);
47941
- } else {
47942
- console.warn(`[DEBUG] Chart element was null for type: ${chartType}`);
47943
- console.warn(`[DEBUG] Args were:`, args);
47944
- chartElements.push(
47945
- /* @__PURE__ */ jsxs(
47946
- "div",
47947
- {
47948
- className: "text-red-500 text-sm border border-red-300 bg-red-50 p-3 rounded",
47949
- children: [
47950
- /* @__PURE__ */ jsx("strong", { children: "Chart Rendering Error:" }),
47951
- " Failed to render ",
47952
- chartType,
47953
- /* @__PURE__ */ jsx("br", {}),
47954
- /* @__PURE__ */ jsxs("small", { children: [
47955
- "Check console for details. Args: ",
47956
- JSON.stringify(args, null, 2)
47957
- ] })
47958
- ]
47959
- },
47960
- `error-${startIndex}`
47961
- )
47962
- );
47963
- }
47964
- } catch (error) {
47965
- console.error(`Failed to parse chart ${chartType}:`, error);
47966
- console.error(`Args string was:`, argsString);
47967
- chartElements.push(
47968
- /* @__PURE__ */ jsxs(
47969
- "div",
47970
- {
47971
- className: "text-red-500 text-sm border border-red-300 bg-red-50 p-3 rounded",
47972
- children: [
47973
- /* @__PURE__ */ jsx("strong", { children: "Chart Parsing Error:" }),
47974
- " Failed to parse ",
47975
- chartType,
47976
- /* @__PURE__ */ jsx("br", {}),
47977
- /* @__PURE__ */ jsxs("small", { children: [
47978
- "Error: ",
47979
- error instanceof Error ? error.message : String(error)
47980
- ] }),
47981
- /* @__PURE__ */ jsx("br", {}),
47982
- /* @__PURE__ */ jsxs("small", { children: [
47983
- "Original: ",
47984
- match[0]
47985
- ] })
47986
- ]
47987
- },
47988
- `error-${startIndex}`
47989
- )
47990
- );
47991
- }
47992
- lastIndex = endIndex;
47993
- }
47994
- }
47995
- console.log(`[DEBUG] Total chart patterns found: ${matchCount}`);
47996
- if (lastIndex < text.length) {
47997
- const remainingText = text.substring(lastIndex);
47998
- chartElements.push(
47999
- /* @__PURE__ */ jsx(
48000
- "div",
48001
- {
48002
- dangerouslySetInnerHTML: { __html: formatMessage(remainingText) }
48003
- },
48004
- `text-${lastIndex}`
48005
- )
48006
- );
48007
- }
48008
- if (chartElements.length === 1 && lastIndex === 0) {
48009
- console.log("[DEBUG] No charts found in text, returning null");
48010
- return null;
48011
- }
48012
- console.log(`[DEBUG] Returning ${chartElements.length} chart elements`);
48013
- return chartElements;
48014
- };
48015
- const parseChartArguments = (argsString) => {
48016
- console.log("[DEBUG] Parsing chart arguments:", argsString);
48017
- const extractParameters = (str) => {
48018
- const params = {};
48019
- let currentPos = 0;
48020
- while (currentPos < str.length) {
48021
- while (currentPos < str.length && /\s|,/.test(str[currentPos])) {
48022
- currentPos++;
48023
- }
48024
- if (currentPos >= str.length) break;
48025
- const paramMatch = str.substring(currentPos).match(/^(\w+)\s*=/);
48026
- if (!paramMatch) {
48027
- console.warn("[DEBUG] No parameter name found at position", currentPos);
48028
- break;
48029
- }
48030
- const paramName = paramMatch[1];
48031
- currentPos += paramMatch[0].length;
48032
- while (currentPos < str.length && /\s/.test(str[currentPos])) {
48033
- currentPos++;
48034
- }
48035
- if (currentPos >= str.length) break;
48036
- let value;
48037
- let valueEnd;
48038
- if (str[currentPos] === "[") {
48039
- let bracketCount = 0;
48040
- let arrayStart = currentPos;
48041
- valueEnd = str.length;
48042
- for (let i = currentPos; i < str.length; i++) {
48043
- if (str[i] === "[") bracketCount++;
48044
- else if (str[i] === "]") bracketCount--;
48045
- if (bracketCount === 0) {
48046
- valueEnd = i + 1;
48047
- break;
48048
- }
48049
- }
48050
- if (bracketCount !== 0) {
48051
- console.error("[DEBUG] Unmatched brackets in array value");
48052
- break;
48053
- }
48054
- const arrayStr = str.substring(arrayStart, valueEnd);
48055
- console.log(`[DEBUG] Found array parameter: ${paramName} = ${arrayStr}`);
48056
- try {
48057
- value = JSON.parse(arrayStr);
48058
- console.log(`[DEBUG] Successfully parsed array ${paramName}:`, value);
48059
- } catch (e) {
48060
- console.error(`[DEBUG] Failed to parse array ${paramName}:`, e);
48061
- console.error(`Array value that failed:`, arrayStr);
48062
- value = arrayStr;
48063
- }
48064
- } else if (str[currentPos] === "{") {
48065
- let braceCount = 0;
48066
- let objectStart = currentPos;
48067
- valueEnd = str.length;
48068
- for (let i = currentPos; i < str.length; i++) {
48069
- if (str[i] === "{") braceCount++;
48070
- else if (str[i] === "}") braceCount--;
48071
- if (braceCount === 0) {
48072
- valueEnd = i + 1;
48073
- break;
48074
- }
48075
- }
48076
- if (braceCount !== 0) {
48077
- console.error("[DEBUG] Unmatched braces in object value");
48078
- break;
48079
- }
48080
- const objectStr = str.substring(objectStart, valueEnd);
48081
- console.log(`[DEBUG] Found object parameter: ${paramName} = ${objectStr}`);
48082
- try {
48083
- value = JSON.parse(objectStr);
48084
- console.log(`[DEBUG] Successfully parsed object ${paramName}:`, value);
48085
- } catch (e) {
48086
- console.error(`[DEBUG] Failed to parse object ${paramName}:`, e);
48087
- console.error(`Object value that failed:`, objectStr);
48088
- value = objectStr;
48089
- }
48090
- } else if (str[currentPos] === '"') {
48091
- let stringStart = currentPos + 1;
48092
- let stringEnd = stringStart;
48093
- while (stringEnd < str.length) {
48094
- if (str[stringEnd] === '"' && str[stringEnd - 1] !== "\\") {
48095
- break;
48096
- }
48097
- stringEnd++;
48098
- }
48099
- if (stringEnd >= str.length) {
48100
- console.error("[DEBUG] Unterminated string value");
48101
- valueEnd = str.length;
48102
- break;
48103
- }
48104
- value = str.substring(stringStart, stringEnd);
48105
- valueEnd = stringEnd + 1;
48106
- console.log(`[DEBUG] Found string parameter: ${paramName} = "${value}"`);
48107
- } else {
48108
- let valueStart = currentPos;
48109
- let valueEndPos = valueStart;
48110
- while (valueEndPos < str.length && str[valueEndPos] !== ",") {
48111
- valueEndPos++;
48112
- }
48113
- const rawValue = str.substring(valueStart, valueEndPos).trim();
48114
- valueEnd = valueEndPos;
48115
- if (rawValue === "true" || rawValue === "True") {
48116
- value = true;
48117
- } else if (rawValue === "false" || rawValue === "False") {
48118
- value = false;
48119
- } else if (rawValue === "null" || rawValue === "None") {
48120
- value = null;
48121
- } else if (!isNaN(Number(rawValue)) && rawValue !== "") {
48122
- value = Number(rawValue);
48123
- } else {
48124
- value = rawValue;
48125
- }
48126
- console.log(`[DEBUG] Found unquoted parameter: ${paramName} = ${rawValue} (parsed as ${typeof value})`);
48127
- }
48128
- params[paramName] = value;
48129
- currentPos = valueEnd;
48130
- }
48131
- return params;
48132
- };
48133
- const result = extractParameters(argsString);
48134
- console.log("[DEBUG] Final parsed arguments:", result);
48135
- return result;
48136
- };
48137
- const renderChart = (chartType, args, key) => {
48138
- console.log(`[DEBUG] Attempting to render chart type: ${chartType}`, args);
48139
- const CHART_COLORS = {
48140
- primary: "#3b82f6",
48141
- // blue-500
48142
- secondary: "#10b981",
48143
- // green-500
48144
- accent: "#f59e0b",
48145
- // amber-500
48146
- danger: "#ef4444",
48147
- // red-500
48148
- violet: "#8b5cf6",
48149
- // violet-500
48150
- cyan: "#06b6d4",
48151
- // cyan-500
48152
- orange: "#f97316",
48153
- // orange-500
48154
- indigo: "#6366f1"
48155
- // indigo-500
48156
- };
48157
- const CHART_COLOR_PALETTE = Object.values(CHART_COLORS);
48158
- const CHART_STYLES = {
48159
- grid: {
48160
- strokeDasharray: "3 3",
48161
- stroke: "#e5e7eb"
48162
- // gray-300
48163
- },
48164
- axis: {
48165
- tick: { fontSize: 12, fill: "#4b5563" },
48166
- // gray-600
48167
- stroke: "#9ca3af"
48168
- // gray-400
48169
- },
48170
- margin: { top: 10, right: 30, left: 20, bottom: 40 },
48171
- barRadius: [4, 4, 0, 0]
48172
- // Top corners rounded
48173
- };
48174
- const CustomTooltip4 = ({ active, payload, label }) => {
48175
- if (active && payload && payload.length) {
48176
- return /* @__PURE__ */ jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
48177
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 mb-1", children: label }),
48178
- payload.map((entry, index) => /* @__PURE__ */ jsxs("p", { className: "text-sm text-gray-600", style: { color: entry.color }, children: [
48179
- entry.name,
48180
- ": ",
48181
- typeof entry.value === "number" ? formatNumber(entry.value) : entry.value,
48182
- args.unit || ""
48183
- ] }, index))
48184
- ] });
48185
- }
48186
- return null;
48187
- };
48188
- const DualAxisTooltip = ({ active, payload, label }) => {
48189
- if (active && payload && payload.length) {
48190
- return /* @__PURE__ */ jsxs("div", { className: "bg-white px-4 py-3 shadow-lg rounded-lg border border-gray-200", children: [
48191
- /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-900 mb-2", children: label }),
48192
- /* @__PURE__ */ jsx("div", { className: "space-y-1", children: payload.map((entry, index) => {
48193
- const value = typeof entry.value === "number" ? formatNumber(entry.value) : entry.value;
48194
- const unit = entry.dataKey === args.left_y_field ? args.left_unit || "" : entry.dataKey === args.right_y_field ? args.right_unit || "" : "";
48195
- return /* @__PURE__ */ jsxs("p", { className: "text-sm", style: { color: entry.color }, children: [
48196
- /* @__PURE__ */ jsxs("span", { className: "font-medium", children: [
48197
- entry.name,
48198
- ":"
48199
- ] }),
48200
- " ",
48201
- value,
48202
- unit
48203
- ] }, index);
48204
- }) })
48205
- ] });
48206
- }
48207
- return null;
48208
- };
48209
- const formatXAxisTick = (value) => {
48210
- if (typeof value === "string") {
48211
- if (value.match(/^\d{2}\/\d{2}\s/)) {
48212
- return value;
48213
- }
48214
- if (value.length > 15) {
48215
- return value.substring(0, 12) + "...";
48216
- }
48217
- }
48218
- return value;
48219
- };
48220
- const ChartWrapper = ({ children, title }) => /* @__PURE__ */ jsxs("div", { className: "my-6 bg-white rounded-xl shadow-sm border border-gray-200 p-6", children: [
48221
- title && /* @__PURE__ */ jsx("h3", { className: "text-base font-semibold text-gray-900 mb-4", children: title }),
48222
- children
48223
- ] });
48224
- switch (chartType) {
48225
- case "create_gauge_chart":
48226
- console.log("[DEBUG] Rendering gauge chart");
48227
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "h-64 w-full flex justify-center", children: /* @__PURE__ */ jsx(
48228
- GaugeChart,
48229
- {
48230
- value: args.value || 0,
48231
- min: args.min_value || 0,
48232
- max: args.max_value || 100,
48233
- target: args.target,
48234
- label: args.label || "",
48235
- unit: args.unit || "",
48236
- thresholds: args.thresholds,
48237
- className: "w-full max-w-sm"
48238
- }
48239
- ) }) }, `gauge-${key}`);
48240
- case "create_bar_chart":
48241
- console.log("[DEBUG] Rendering bar chart");
48242
- if (!args.data || !args.x_field || !args.y_field) {
48243
- console.error("Bar chart missing required parameters:", { data: !!args.data, x_field: !!args.x_field, y_field: !!args.y_field });
48244
- return null;
48245
- }
48246
- if (!Array.isArray(args.data)) {
48247
- console.error("Bar chart data must be an array, got:", typeof args.data, args.data);
48248
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48249
- "Error: Chart data must be an array. Received: ",
48250
- typeof args.data
48251
- ] }) }, `bar-error-${key}`);
48252
- }
48253
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-64", style: { minHeight: "200px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart$1, { data: args.data, margin: CHART_STYLES.margin, children: [
48254
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48255
- /* @__PURE__ */ jsx(
48256
- XAxis,
48257
- {
48258
- dataKey: args.x_field,
48259
- ...CHART_STYLES.axis,
48260
- angle: -45,
48261
- textAnchor: "end",
48262
- height: 60,
48263
- interval: 0,
48264
- tickFormatter: formatXAxisTick
48265
- }
48266
- ),
48267
- /* @__PURE__ */ jsx(
48268
- YAxis,
48269
- {
48270
- ...CHART_STYLES.axis,
48271
- tickFormatter: (value) => formatNumber(value)
48272
- }
48273
- ),
48274
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip4, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
48275
- /* @__PURE__ */ jsx(
48276
- Bar,
48277
- {
48278
- dataKey: args.y_field,
48279
- fill: args.color || CHART_COLORS.primary,
48280
- radius: CHART_STYLES.barRadius
48281
- }
48282
- )
48283
- ] }) }) }) }, `bar-${key}`);
48284
- case "create_line_chart":
48285
- console.log("[DEBUG] Rendering line chart");
48286
- if (!args.data || !args.x_field || !args.y_field) {
48287
- console.error("Line chart missing required parameters:", { data: !!args.data, x_field: !!args.x_field, y_field: !!args.y_field });
48288
- return null;
48289
- }
48290
- if (!Array.isArray(args.data)) {
48291
- console.error("Line chart data must be an array, got:", typeof args.data, args.data);
48292
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48293
- "Error: Chart data must be an array. Received: ",
48294
- typeof args.data
48295
- ] }) }, `line-error-${key}`);
48296
- }
48297
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-64", style: { minHeight: "200px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(LineChart$1, { data: args.data, margin: CHART_STYLES.margin, children: [
48298
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48299
- /* @__PURE__ */ jsx(
48300
- XAxis,
48301
- {
48302
- dataKey: args.x_field,
48303
- ...CHART_STYLES.axis,
48304
- angle: -45,
48305
- textAnchor: "end",
48306
- height: 60,
48307
- interval: 0,
48308
- tickFormatter: formatXAxisTick
48309
- }
48310
- ),
48311
- /* @__PURE__ */ jsx(
48312
- YAxis,
48313
- {
48314
- ...CHART_STYLES.axis,
48315
- tickFormatter: (value) => formatNumber(value)
48316
- }
48317
- ),
48318
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip4, {}), cursor: { strokeDasharray: "3 3" } }),
48319
- /* @__PURE__ */ jsx(
48320
- Line,
48321
- {
48322
- type: "monotone",
48323
- dataKey: args.y_field,
48324
- stroke: CHART_COLORS.primary,
48325
- strokeWidth: 2,
48326
- dot: { r: 4, fill: CHART_COLORS.primary },
48327
- activeDot: { r: 6 }
48328
- }
48329
- )
48330
- ] }) }) }) }, `line-${key}`);
48331
- case "create_pie_chart":
48332
- console.log("[DEBUG] Rendering pie chart");
48333
- if (!args.data || !args.label_field || !args.value_field) {
48334
- console.error("Pie chart missing required parameters:", { data: !!args.data, label_field: !!args.label_field, value_field: !!args.value_field });
48335
- console.error("Available args:", Object.keys(args));
48336
- return null;
48337
- }
48338
- if (!Array.isArray(args.data)) {
48339
- console.error("Pie chart data must be an array, got:", typeof args.data, args.data);
48340
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48341
- "Error: Chart data must be an array. Received: ",
48342
- typeof args.data
48343
- ] }) }, `pie-error-${key}`);
48344
- }
48345
- const pieData = args.data.map((item) => ({
48346
- name: item[args.label_field],
48347
- value: item[args.value_field]
48348
- }));
48349
- console.log("[DEBUG] Pie chart data transformed:", pieData);
48350
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "h-64 w-full max-w-md mx-auto", children: /* @__PURE__ */ jsx(
48351
- PieChart4,
48352
- {
48353
- data: pieData,
48354
- showPercentages: args.show_percentages || false,
48355
- colors: CHART_COLOR_PALETTE
48356
- }
48357
- ) }) }, `pie-${key}`);
48358
- case "create_comparison_table":
48359
- console.log("[DEBUG] Rendering comparison table");
48360
- if (!args.data) {
48361
- console.error("Comparison table missing required data");
48362
- return null;
48363
- }
48364
- if (!Array.isArray(args.data)) {
48365
- console.error("Comparison table data must be an array, got:", typeof args.data, args.data);
48366
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48367
- "Error: Table data must be an array. Received: ",
48368
- typeof args.data
48369
- ] }) }, `table-error-${key}`);
48370
- }
48371
- const columns = args.columns || Object.keys(args.data[0] || {});
48372
- let sortedData = [...args.data];
48373
- if (args.sort_by && columns.includes(args.sort_by)) {
48374
- sortedData.sort((a, b) => {
48375
- const aVal = a[args.sort_by];
48376
- const bVal = b[args.sort_by];
48377
- const comparison = aVal > bVal ? 1 : aVal < bVal ? -1 : 0;
48378
- return args.sort_descending === false ? comparison : -comparison;
48379
- });
48380
- }
48381
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto rounded-lg border border-gray-200", children: /* @__PURE__ */ jsxs("table", { className: "min-w-full divide-y divide-gray-200", children: [
48382
- /* @__PURE__ */ jsx("thead", { className: "bg-gray-50", children: /* @__PURE__ */ jsx("tr", { children: columns.map((col) => /* @__PURE__ */ jsx(
48383
- "th",
48384
- {
48385
- className: `px-6 py-3 text-left text-xs font-medium text-gray-600 uppercase tracking-wider ${col === args.highlight_column ? "bg-blue-50" : ""}`,
48386
- children: col
48387
- },
48388
- col
48389
- )) }) }),
48390
- /* @__PURE__ */ jsx("tbody", { className: "bg-white divide-y divide-gray-200", children: sortedData.map((row, rowIdx) => /* @__PURE__ */ jsx("tr", { className: rowIdx % 2 === 0 ? "bg-white" : "bg-gray-50", children: columns.map((col) => /* @__PURE__ */ jsx(
48391
- "td",
48392
- {
48393
- className: `px-6 py-4 whitespace-nowrap text-sm ${col === args.highlight_column ? "font-medium text-blue-600 bg-blue-50" : "text-gray-900"}`,
48394
- children: typeof row[col] === "number" ? formatNumber(row[col]) : row[col]
48395
- },
48396
- col
48397
- )) }, rowIdx)) })
48398
- ] }) }) }, `table-${key}`);
48399
- case "create_multi_line_chart":
48400
- console.log("[DEBUG] Rendering multi-line chart");
48401
- if (!args.data || !args.x_field || !args.y_fields || !args.legend) {
48402
- console.error("Multi-line chart missing required parameters:", {
48403
- data: !!args.data,
48404
- x_field: !!args.x_field,
48405
- y_fields: !!args.y_fields,
48406
- legend: !!args.legend
48407
- });
48408
- return null;
48409
- }
48410
- if (!Array.isArray(args.data)) {
48411
- console.error("Multi-line chart data must be an array, got:", typeof args.data, args.data);
48412
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48413
- "Error: Chart data must be an array. Received: ",
48414
- typeof args.data
48415
- ] }) }, `multi-line-error-${key}`);
48416
- }
48417
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(LineChart$1, { data: args.data, margin: CHART_STYLES.margin, children: [
48418
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48419
- /* @__PURE__ */ jsx(
48420
- XAxis,
48421
- {
48422
- dataKey: args.x_field,
48423
- ...CHART_STYLES.axis,
48424
- angle: -45,
48425
- textAnchor: "end",
48426
- height: 60,
48427
- interval: 0,
48428
- tickFormatter: formatXAxisTick
48429
- }
48430
- ),
48431
- /* @__PURE__ */ jsx(
48432
- YAxis,
48433
- {
48434
- ...CHART_STYLES.axis,
48435
- tickFormatter: (value) => formatNumber(value)
48436
- }
48437
- ),
48438
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip4, {}), cursor: { strokeDasharray: "3 3" } }),
48439
- /* @__PURE__ */ jsx(
48440
- Legend,
48441
- {
48442
- wrapperStyle: { paddingTop: "20px" },
48443
- formatter: (value) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: value })
48444
- }
48445
- ),
48446
- args.y_fields.map((field, index) => /* @__PURE__ */ jsx(
48447
- Line,
48448
- {
48449
- type: "monotone",
48450
- dataKey: field,
48451
- stroke: CHART_COLOR_PALETTE[index % CHART_COLOR_PALETTE.length],
48452
- strokeWidth: 2,
48453
- name: args.legend[index] || field,
48454
- dot: { r: 4 },
48455
- activeDot: { r: 6 }
48456
- },
48457
- field
48458
- ))
48459
- ] }) }) }) }, `multi-line-${key}`);
48460
- case "create_stacked_bar_chart":
48461
- console.log("[DEBUG] Rendering stacked bar chart");
48462
- if (!args.data || !args.x_field || !args.stack_fields) {
48463
- console.error("Stacked bar chart missing required parameters:", {
48464
- data: !!args.data,
48465
- x_field: !!args.x_field,
48466
- stack_fields: !!args.stack_fields
48467
- });
48468
- return null;
48469
- }
48470
- if (!Array.isArray(args.data)) {
48471
- console.error("Stacked bar chart data must be an array, got:", typeof args.data, args.data);
48472
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48473
- "Error: Chart data must be an array. Received: ",
48474
- typeof args.data
48475
- ] }) }, `stacked-bar-error-${key}`);
48476
- }
48477
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(BarChart$1, { data: args.data, margin: CHART_STYLES.margin, children: [
48478
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48479
- /* @__PURE__ */ jsx(
48480
- XAxis,
48481
- {
48482
- dataKey: args.x_field,
48483
- ...CHART_STYLES.axis,
48484
- angle: -45,
48485
- textAnchor: "end",
48486
- height: 60,
48487
- interval: 0,
48488
- tickFormatter: formatXAxisTick
48489
- }
48490
- ),
48491
- /* @__PURE__ */ jsx(
48492
- YAxis,
48493
- {
48494
- ...CHART_STYLES.axis,
48495
- tickFormatter: (value) => formatNumber(value)
48496
- }
48497
- ),
48498
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip4, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
48499
- /* @__PURE__ */ jsx(
48500
- Legend,
48501
- {
48502
- wrapperStyle: { paddingTop: "20px" },
48503
- formatter: (value) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: value })
48504
- }
48505
- ),
48506
- args.stack_fields.map((field, index) => /* @__PURE__ */ jsx(
48507
- Bar,
48508
- {
48509
- dataKey: field,
48510
- stackId: "stack",
48511
- fill: CHART_COLOR_PALETTE[index % CHART_COLOR_PALETTE.length],
48512
- name: field,
48513
- radius: index === args.stack_fields.length - 1 ? CHART_STYLES.barRadius : void 0
48514
- },
48515
- field
48516
- ))
48517
- ] }) }) }) }, `stacked-bar-${key}`);
48518
- case "create_dual_axis_chart":
48519
- console.log("[DEBUG] Rendering dual-axis chart");
48520
- if (!args.data || !args.x_field || !args.left_y_field || !args.right_y_field) {
48521
- console.error("Dual-axis chart missing required parameters:", {
48522
- data: !!args.data,
48523
- x_field: !!args.x_field,
48524
- left_y_field: !!args.left_y_field,
48525
- right_y_field: !!args.right_y_field
48526
- });
48527
- return null;
48528
- }
48529
- if (!Array.isArray(args.data)) {
48530
- console.error("Dual-axis chart data must be an array, got:", typeof args.data, args.data);
48531
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48532
- "Error: Chart data must be an array. Received: ",
48533
- typeof args.data
48534
- ] }) }, `dual-axis-error-${key}`);
48535
- }
48536
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
48537
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48538
- /* @__PURE__ */ jsx(
48539
- XAxis,
48540
- {
48541
- dataKey: args.x_field,
48542
- ...CHART_STYLES.axis,
48543
- angle: -45,
48544
- textAnchor: "end",
48545
- height: 100,
48546
- interval: 0,
48547
- tickFormatter: formatXAxisTick
48548
- }
48549
- ),
48550
- /* @__PURE__ */ jsx(
48551
- YAxis,
48552
- {
48553
- yAxisId: "left",
48554
- orientation: "left",
48555
- label: {
48556
- value: args.left_label || args.left_y_field,
48557
- angle: -90,
48558
- position: "insideLeft",
48559
- style: { textAnchor: "middle", fill: "#4b5563" }
48560
- },
48561
- ...CHART_STYLES.axis,
48562
- tickFormatter: (value) => `${formatNumber(value)}${args.left_unit || ""}`
48563
- }
48564
- ),
48565
- /* @__PURE__ */ jsx(
48566
- YAxis,
48567
- {
48568
- yAxisId: "right",
48569
- orientation: "right",
48570
- label: {
48571
- value: args.right_label || args.right_y_field,
48572
- angle: 90,
48573
- position: "insideRight",
48574
- style: { textAnchor: "middle", fill: "#4b5563" }
48575
- },
48576
- ...CHART_STYLES.axis,
48577
- tickFormatter: (value) => `${formatNumber(value)}${args.right_unit || ""}`
48578
- }
48579
- ),
48580
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(DualAxisTooltip, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
48581
- /* @__PURE__ */ jsx(
48582
- Legend,
48583
- {
48584
- wrapperStyle: { paddingTop: "20px" },
48585
- formatter: (value) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: value })
48586
- }
48587
- ),
48588
- /* @__PURE__ */ jsx(
48589
- Bar,
48590
- {
48591
- yAxisId: "left",
48592
- dataKey: args.left_y_field,
48593
- fill: CHART_COLORS.primary,
48594
- name: args.left_label || args.left_y_field,
48595
- radius: CHART_STYLES.barRadius
48596
- }
48597
- ),
48598
- /* @__PURE__ */ jsx(
48599
- Line,
48600
- {
48601
- yAxisId: "right",
48602
- type: "monotone",
48603
- dataKey: args.right_y_field,
48604
- stroke: CHART_COLORS.danger,
48605
- strokeWidth: 3,
48606
- name: args.right_label || args.right_y_field,
48607
- dot: { r: 5, fill: CHART_COLORS.danger },
48608
- activeDot: { r: 7 }
48609
- }
48610
- )
48611
- ] }) }) }) }, `dual-axis-${key}`);
48612
- case "create_scatter_plot":
48613
- console.log("[DEBUG] Rendering scatter plot");
48614
- if (!args.data || !args.x_field || !args.y_field || !args.group_field) {
48615
- console.error("Scatter plot missing required parameters:", {
48616
- data: !!args.data,
48617
- x_field: !!args.x_field,
48618
- y_field: !!args.y_field,
48619
- group_field: !!args.group_field
48620
- });
48621
- return null;
48622
- }
48623
- if (!Array.isArray(args.data)) {
48624
- console.error("Scatter plot data must be an array, got:", typeof args.data, args.data);
48625
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48626
- "Error: Chart data must be an array. Received: ",
48627
- typeof args.data
48628
- ] }) }, `scatter-error-${key}`);
48629
- }
48630
- const groupedData = args.data.reduce((acc, item) => {
48631
- const group = item[args.group_field];
48632
- if (!acc[group]) {
48633
- acc[group] = [];
48634
- }
48635
- acc[group].push(item);
48636
- return acc;
48637
- }, {});
48638
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ScatterChart, { margin: CHART_STYLES.margin, children: [
48639
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48640
- /* @__PURE__ */ jsx(
48641
- XAxis,
48642
- {
48643
- dataKey: args.x_field,
48644
- type: "number",
48645
- name: args.x_field,
48646
- ...CHART_STYLES.axis
48647
- }
48648
- ),
48649
- /* @__PURE__ */ jsx(
48650
- YAxis,
48651
- {
48652
- dataKey: args.y_field,
48653
- type: "number",
48654
- name: args.y_field,
48655
- ...CHART_STYLES.axis
48656
- }
48657
- ),
48658
- /* @__PURE__ */ jsx(
48659
- Tooltip,
48660
- {
48661
- cursor: { strokeDasharray: "3 3" },
48662
- content: /* @__PURE__ */ jsx(CustomTooltip4, {})
48663
- }
48664
- ),
48665
- /* @__PURE__ */ jsx(
48666
- Legend,
48667
- {
48668
- wrapperStyle: { paddingTop: "20px" },
48669
- formatter: (value) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: value })
48670
- }
48671
- ),
48672
- Object.entries(groupedData).map(([group, data], index) => /* @__PURE__ */ jsx(
48673
- Scatter,
48674
- {
48675
- name: group,
48676
- data,
48677
- fill: CHART_COLOR_PALETTE[index % CHART_COLOR_PALETTE.length]
48678
- },
48679
- group
48680
- ))
48681
- ] }) }) }) }, `scatter-${key}`);
48682
- case "create_combo_chart":
48683
- console.log("[DEBUG] Rendering combo chart");
48684
- if (!args.data || !args.x_field || !args.bar_field || !args.line_field) {
48685
- console.error("Combo chart missing required parameters:", {
48686
- data: !!args.data,
48687
- x_field: !!args.x_field,
48688
- bar_field: !!args.bar_field,
48689
- line_field: !!args.line_field
48690
- });
48691
- return null;
48692
- }
48693
- if (!Array.isArray(args.data)) {
48694
- console.error("Combo chart data must be an array, got:", typeof args.data, args.data);
48695
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48696
- "Error: Chart data must be an array. Received: ",
48697
- typeof args.data
48698
- ] }) }, `combo-error-${key}`);
48699
- }
48700
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
48701
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48702
- /* @__PURE__ */ jsx(
48703
- XAxis,
48704
- {
48705
- dataKey: args.x_field,
48706
- ...CHART_STYLES.axis,
48707
- angle: -45,
48708
- textAnchor: "end",
48709
- height: 100,
48710
- interval: 0,
48711
- tickFormatter: formatXAxisTick
48712
- }
48713
- ),
48714
- /* @__PURE__ */ jsx(
48715
- YAxis,
48716
- {
48717
- yAxisId: "left",
48718
- orientation: "left",
48719
- ...CHART_STYLES.axis,
48720
- tickFormatter: (value) => formatNumber(value)
48721
- }
48722
- ),
48723
- /* @__PURE__ */ jsx(
48724
- YAxis,
48725
- {
48726
- yAxisId: "right",
48727
- orientation: "right",
48728
- ...CHART_STYLES.axis,
48729
- tickFormatter: (value) => formatNumber(value)
48730
- }
48731
- ),
48732
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip4, {}), cursor: { fill: "rgba(0, 0, 0, 0.05)" } }),
48733
- /* @__PURE__ */ jsx(
48734
- Legend,
48735
- {
48736
- wrapperStyle: { paddingTop: "20px" },
48737
- formatter: (value) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: value })
48738
- }
48739
- ),
48740
- /* @__PURE__ */ jsx(
48741
- Bar,
48742
- {
48743
- yAxisId: "left",
48744
- dataKey: args.bar_field,
48745
- fill: CHART_COLORS.primary,
48746
- name: args.bar_field,
48747
- radius: CHART_STYLES.barRadius
48748
- }
48749
- ),
48750
- /* @__PURE__ */ jsx(
48751
- Line,
48752
- {
48753
- yAxisId: "right",
48754
- type: "monotone",
48755
- dataKey: args.line_field,
48756
- stroke: CHART_COLORS.danger,
48757
- strokeWidth: 3,
48758
- name: args.line_field,
48759
- dot: { r: 5 },
48760
- activeDot: { r: 7 }
48761
- }
48762
- )
48763
- ] }) }) }) }, `combo-${key}`);
48764
- case "create_area_chart":
48765
- console.log("[DEBUG] Rendering area chart");
48766
- if (!args.data || !args.x_field || !args.y_field) {
48767
- console.error("Area chart missing required parameters:", {
48768
- data: !!args.data,
48769
- x_field: !!args.x_field,
48770
- y_field: !!args.y_field
48771
- });
48772
- return null;
48773
- }
48774
- if (!Array.isArray(args.data)) {
48775
- console.error("Area chart data must be an array, got:", typeof args.data, args.data);
48776
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsxs("div", { className: "text-red-500 text-sm", children: [
48777
- "Error: Chart data must be an array. Received: ",
48778
- typeof args.data
48779
- ] }) }, `area-error-${key}`);
48780
- }
48781
- return /* @__PURE__ */ jsx(ChartWrapper, { title: args.title, children: /* @__PURE__ */ jsx("div", { className: "w-full h-80", style: { minHeight: "250px", minWidth: "300px" }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(ComposedChart, { data: args.data, margin: { ...CHART_STYLES.margin, bottom: 80 }, children: [
48782
- /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs("linearGradient", { id: "colorGradient", x1: "0", y1: "0", x2: "0", y2: "1", children: [
48783
- /* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: CHART_COLORS.primary, stopOpacity: 0.8 }),
48784
- /* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: CHART_COLORS.primary, stopOpacity: 0.1 })
48785
- ] }) }),
48786
- /* @__PURE__ */ jsx(CartesianGrid, { ...CHART_STYLES.grid }),
48787
- /* @__PURE__ */ jsx(
48788
- XAxis,
48789
- {
48790
- dataKey: args.x_field,
48791
- ...CHART_STYLES.axis,
48792
- angle: -45,
48793
- textAnchor: "end",
48794
- height: 100,
48795
- interval: 0,
48796
- tickFormatter: formatXAxisTick
48797
- }
48798
- ),
48799
- /* @__PURE__ */ jsx(
48800
- YAxis,
48801
- {
48802
- ...CHART_STYLES.axis,
48803
- tickFormatter: (value) => formatNumber(value)
48804
- }
48805
- ),
48806
- /* @__PURE__ */ jsx(Tooltip, { content: /* @__PURE__ */ jsx(CustomTooltip4, {}), cursor: { strokeDasharray: "3 3" } }),
48807
- /* @__PURE__ */ jsx(
48808
- Legend,
48809
- {
48810
- wrapperStyle: { paddingTop: "20px" },
48811
- formatter: (value) => /* @__PURE__ */ jsx("span", { className: "text-sm", children: value })
48812
- }
48813
- ),
48814
- /* @__PURE__ */ jsx(
48815
- Area,
48816
- {
48817
- type: "monotone",
48818
- dataKey: args.y_field,
48819
- stroke: CHART_COLORS.primary,
48820
- strokeWidth: 2,
48821
- fill: args.fill !== false ? "url(#colorGradient)" : "none",
48822
- name: args.y_field,
48823
- dot: { r: 4, fill: CHART_COLORS.primary },
48824
- activeDot: { r: 6 }
48825
- }
48826
- )
48827
- ] }) }) }) }, `area-${key}`);
48828
- default:
48829
- console.warn(`Unknown chart type: ${chartType}`);
48830
- return null;
48831
- }
48832
- };
48833
- const chartContent = parseChartPatterns(content);
48834
- let finalNode;
48835
- if (chartContent) {
48836
- finalNode = /* @__PURE__ */ jsx("div", { className: "formatted-content", children: chartContent });
48837
- } else {
48838
- finalNode = /* @__PURE__ */ jsx(
48839
- "div",
48840
- {
48841
- className: "formatted-content",
48842
- dangerouslySetInnerHTML: { __html: formatMessage(content) }
48843
- }
48844
- );
48845
- }
48846
- renderedContentCache.current.set(content, finalNode);
48847
- return finalNode;
48848
- };
48849
- return /* @__PURE__ */ jsxs("div", { className: "flex h-screen bg-white", children: [
48850
- /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: {
48851
- __html: `
48852
- @keyframes slideDown {
48853
- 0% {
48854
- transform: translateY(-40vh);
48855
- opacity: 1;
48856
- }
48857
- 100% {
48858
- transform: translateY(0);
48859
- opacity: 1;
48860
- }
48861
- }
48862
-
48863
- @keyframes waveLoad {
48864
- 0% {
48865
- background-position: -200% 0;
48866
- }
48867
- 100% {
48868
- background-position: 200% 0;
48869
- }
48870
- }
48871
-
48872
- .thinking-wave {
48873
- background: linear-gradient(
48874
- 90deg,
48875
- #6b7280 0%,
48876
- #6b7280 40%,
48877
- #3b82f6 50%,
48878
- #6b7280 60%,
48879
- #6b7280 100%
48880
- );
48881
- background-size: 200% 100%;
48882
- -webkit-background-clip: text;
48883
- background-clip: text;
48884
- -webkit-text-fill-color: transparent;
48885
- animation: waveLoad 3s ease-in-out infinite;
48886
- }
48887
- `
48888
- } }),
48889
- /* @__PURE__ */ jsxs("div", { className: `flex-1 flex flex-col h-screen transition-all duration-300 ${isSidebarOpen ? "lg:mr-80 mr-0" : "mr-0"}`, children: [
48890
- /* @__PURE__ */ jsxs("header", { className: "flex-shrink-0 bg-white px-3 sm:px-6 md:px-8 py-2 sm:py-5 md:py-6 shadow-sm border-b border-gray-200/80 sticky top-0 z-10", children: [
48891
- /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
48892
- /* @__PURE__ */ jsx(
48893
- "button",
48894
- {
48895
- onClick: () => navigate("/"),
48896
- className: "p-2 -ml-2 rounded-full active:bg-gray-100 transition-colors",
48897
- "aria-label": "Navigate back",
48898
- children: /* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-gray-700", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M15 19l-7-7 7-7" }) })
48899
- }
48900
- ),
48901
- /* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col items-center justify-center", children: [
48902
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
48903
- /* @__PURE__ */ jsx("h1", { className: "text-base font-semibold text-gray-900", children: "Chat with Axel" }),
48904
- /* @__PURE__ */ jsxs("div", { className: "relative flex h-2 w-2", children: [
48905
- /* @__PURE__ */ jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 opacity-75" }),
48906
- /* @__PURE__ */ jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500" })
48907
- ] })
48908
- ] }),
48909
- /* @__PURE__ */ jsx("span", { className: "text-[10px] text-gray-500", children: /* @__PURE__ */ jsx(ISTTimer_default, {}) })
48910
- ] }),
48911
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
48912
- /* @__PURE__ */ jsx(
48913
- "button",
48914
- {
48915
- onClick: handleNewThread,
48916
- className: "p-2 rounded-full active:bg-gray-100 transition-colors",
48917
- "aria-label": "New chat",
48918
- title: "New chat",
48919
- children: /* @__PURE__ */ jsx(RefreshCw, { className: "w-5 h-5 text-gray-700" })
48920
- }
48921
- ),
48922
- /* @__PURE__ */ jsx(
48923
- "button",
48924
- {
48925
- onClick: () => setIsSidebarOpen(!isSidebarOpen),
48926
- className: "relative p-2 -mr-2 rounded-full active:bg-gray-100 transition-colors",
48927
- "aria-label": "Toggle chat history",
48928
- title: isSidebarOpen ? "Hide history" : "Show history",
48929
- children: isSidebarOpen ? /* @__PURE__ */ jsx(X, { className: "w-5 h-5 text-gray-700" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
48930
- /* @__PURE__ */ jsx(Menu, { className: "w-5 h-5 text-gray-700" }),
48931
- newChatCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute top-1 right-1 bg-red-500 text-white text-[9px] rounded-full w-4 h-4 flex items-center justify-center font-medium", children: newChatCount })
48932
- ] })
48933
- }
48934
- )
48935
- ] })
48936
- ] }) }),
48937
- /* @__PURE__ */ jsxs("div", { className: "hidden sm:flex items-center justify-between relative", children: [
48938
- /* @__PURE__ */ jsx("div", { className: "absolute left-0", children: /* @__PURE__ */ jsx(
48939
- BackButtonMinimal,
48940
- {
48941
- onClick: () => navigate("/"),
48942
- text: "Back",
48943
- size: "default",
48944
- "aria-label": "Navigate back to dashboard"
48945
- }
48946
- ) }),
48947
- /* @__PURE__ */ jsxs("div", { className: "flex-1 text-center mx-auto", children: [
48948
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-3 mb-1", children: [
48949
- /* @__PURE__ */ jsx("h1", { className: "text-xl md:text-2xl lg:text-3xl font-semibold text-gray-900", children: "Chat with Axel" }),
48950
- /* @__PURE__ */ jsx("div", { className: "h-1.5 w-1.5 md:h-2 md:w-2 rounded-full bg-green-500 animate-pulse ring-2 ring-green-500/30 ring-offset-1" })
48951
- ] }),
48952
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm text-gray-500", children: /* @__PURE__ */ jsx(ISTTimer_default, {}) }) })
48953
- ] }),
48954
- /* @__PURE__ */ jsxs("div", { className: "absolute right-0 flex items-center gap-2", children: [
48955
- /* @__PURE__ */ jsxs(
48956
- "button",
48957
- {
48958
- onClick: handleNewThread,
48959
- className: "flex items-center gap-2 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors text-sm font-medium",
48960
- children: [
48961
- /* @__PURE__ */ jsx(RefreshCw, { className: "w-4 h-4" }),
48962
- /* @__PURE__ */ jsx("span", { children: "New Chat" })
48963
- ]
48964
- }
48965
- ),
48966
- /* @__PURE__ */ jsx(
48967
- "button",
48968
- {
48969
- onClick: () => setIsSidebarOpen(!isSidebarOpen),
48970
- className: "relative flex items-center gap-2 px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors text-sm font-medium",
48971
- "aria-label": "Toggle chat history",
48972
- children: isSidebarOpen ? /* @__PURE__ */ jsxs(Fragment, { children: [
48973
- /* @__PURE__ */ jsx(X, { className: "w-4 h-4" }),
48974
- /* @__PURE__ */ jsx("span", { children: "Hide History" })
48975
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
48976
- /* @__PURE__ */ jsx(Menu, { className: "w-4 h-4" }),
48977
- /* @__PURE__ */ jsx("span", { children: "Chat History" }),
48978
- newChatCount > 0 && /* @__PURE__ */ jsx("span", { className: "ml-1 bg-red-500 text-white text-xs rounded-full px-2 py-0.5 font-medium", children: newChatCount })
48979
- ] })
48980
- }
48981
- )
48982
- ] })
48983
- ] })
48984
- ] }),
48985
- /* @__PURE__ */ jsx(
48986
- "main",
48987
- {
48988
- ref: containerRef,
48989
- className: `flex-1 bg-gray-50/50 min-h-0 ${displayMessages.length === 0 && !isTransitioning ? "flex items-center justify-center" : "overflow-y-auto"}`,
48990
- children: !activeThreadId && displayMessages.length === 0 && !isTransitioning ? (
48991
- /* Centered welcome and input for new chat */
48992
- /* @__PURE__ */ jsxs("div", { className: "w-full max-w-3xl mx-auto px-3 sm:px-4 md:px-6 flex flex-col items-center justify-center space-y-8 sm:space-y-12 -mt-8 sm:-mt-16", children: [
48993
- /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
48994
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-4 sm:mb-6 md:mb-8", children: /* @__PURE__ */ jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", size: "2xl", animate: true }) }),
48995
- /* @__PURE__ */ jsxs("h2", { className: "text-lg sm:text-xl md:text-2xl lg:text-3xl font-semibold text-gray-900 px-2 sm:px-4", children: [
48996
- typedText,
48997
- typedText.length < currentGreeting.length && /* @__PURE__ */ jsx("span", { className: "animate-pulse", children: "|" })
48998
- ] })
48999
- ] }),
49000
- /* @__PURE__ */ jsx("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
49001
- /* @__PURE__ */ jsx("div", { className: "relative bg-white rounded-2xl sm:rounded-3xl shadow-lg border border-gray-200 focus-within:border-gray-300 transition-all duration-200", children: /* @__PURE__ */ jsx("div", { className: "flex items-end gap-2 p-3 sm:p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex-1 relative", children: [
49002
- /* @__PURE__ */ jsx(
49003
- "textarea",
49004
- {
49005
- ref: textareaRef,
49006
- value: inputValue,
49007
- onChange: (e) => {
49008
- const newValue = e.target.value;
49009
- setInputValue(newValue);
49010
- if (newValue.length > 0 && !hasStartedTyping) {
49011
- trackTypingStart();
49012
- }
49013
- if (newValue.length > 0) {
49014
- trackTypingProgress(newValue);
49015
- }
49016
- if (newValue.length === 0) {
49017
- resetTypingState();
49018
- }
49019
- },
49020
- onKeyDown: handleKeyDown,
49021
- onFocus: () => {
49022
- trackCoreEvent("AI Agent Input Focused", {
49023
- line_id: lineId,
49024
- company_id: companyId,
49025
- shift_id: shiftId,
49026
- active_thread_id: activeThreadId,
49027
- has_existing_messages: messages.length > 0,
49028
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
49029
- });
49030
- },
49031
- placeholder: "Ask me anything about your shop-floor",
49032
- className: "w-full resize-none bg-transparent px-3 sm:px-4 py-3 sm:py-2 pr-12 sm:pr-14 focus:outline-none placeholder-gray-500 text-gray-900 text-sm sm:text-base leading-relaxed",
49033
- rows: 1,
49034
- style: { minHeight: "40px", maxHeight: "120px" }
49035
- }
49036
- ),
49037
- /* @__PURE__ */ jsx("div", { className: "absolute right-2 sm:right-3 bottom-2 sm:bottom-2 flex items-center gap-2", children: /* @__PURE__ */ jsx(
49038
- "button",
49039
- {
49040
- type: "submit",
49041
- disabled: !inputValue.trim() || isCurrentThreadLoading,
49042
- className: "inline-flex items-center justify-center w-8 h-8 sm:w-9 sm:h-9 bg-gray-900 text-white rounded-full hover:bg-gray-800 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-gray-500/20",
49043
- children: /* @__PURE__ */ jsx(Send, { className: "w-4 h-4" })
49044
- }
49045
- ) })
49046
- ] }) }) }),
49047
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4 mt-2 text-xs text-gray-400", children: [
49048
- /* @__PURE__ */ jsx("span", { className: "text-center", children: isCurrentThreadLoading ? "You can type your next message while Axel responds" : "Press Enter to send \u2022 Shift+Enter for new line" }),
49049
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
49050
- /* @__PURE__ */ jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isCurrentThreadLoading ? "bg-orange-500" : "bg-green-500"}` }),
49051
- /* @__PURE__ */ jsx("span", { children: isCurrentThreadLoading ? "Responding..." : "Connected" })
49052
- ] })
49053
- ] })
49054
- ] }) })
49055
- ] })
49056
- ) : isTransitioning ? (
49057
- /* Transition state - show user message first, then thinking */
49058
- /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-3 sm:px-4 md:px-6 py-4 sm:py-6 pb-24 sm:pb-32", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4 sm:space-y-6", children: [
49059
- displayMessages.map((message, index) => /* @__PURE__ */ jsxs(
49060
- "div",
49061
- {
49062
- className: `flex gap-2 sm:gap-3 md:gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
49063
- children: [
49064
- message.role === "assistant" && /* @__PURE__ */ jsx(ProfilePicture, {}),
49065
- /* @__PURE__ */ jsx("div", { className: `max-w-none w-full group ${message.role === "user" ? "order-1" : ""}`, children: /* @__PURE__ */ jsx(
49066
- "div",
49067
- {
49068
- className: `relative px-3 sm:px-4 md:px-5 py-3 sm:py-4 rounded-xl sm:rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-600 text-white max-w-[90%] sm:max-w-[85%] ml-auto" : "bg-white border border-gray-200/80 max-w-full"}`,
49069
- children: /* @__PURE__ */ jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
49070
- message.role === "assistant" ? message.id === -1 ? /* @__PURE__ */ jsx(
49071
- "div",
49072
- {
49073
- className: "formatted-content",
49074
- dangerouslySetInnerHTML: { __html: formatMessage(message.content) }
49075
- }
49076
- ) : renderAssistantContent(message.content) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
49077
- message.id === -1 && /* @__PURE__ */ jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
49078
- ] })
49079
- }
49080
- ) })
49081
- ]
49082
- },
49083
- message.id === -1 ? "streaming-message" : `${message.id}-${index}`
49084
- )),
49085
- /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
49086
- /* @__PURE__ */ jsx(ProfilePicture, {}),
49087
- /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
49088
- ] })
49089
- ] }) })
49090
- ) : (
49091
- /* Regular chat view with messages */
49092
- /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-3 sm:px-4 md:px-6 py-3 sm:py-6 pb-20 sm:pb-32", children: /* @__PURE__ */ jsxs("div", { className: "space-y-3 sm:space-y-6", children: [
49093
- displayMessages.map((message, index) => /* @__PURE__ */ jsxs(
49094
- "div",
49095
- {
49096
- className: `flex gap-2 sm:gap-3 md:gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
49097
- children: [
49098
- message.role === "assistant" && /* @__PURE__ */ jsx(ProfilePicture, {}),
49099
- /* @__PURE__ */ jsxs("div", { className: `max-w-none w-full group ${message.role === "user" ? "order-1" : ""}`, children: [
49100
- /* @__PURE__ */ jsxs(
49101
- "div",
49102
- {
49103
- className: `relative px-3 sm:px-4 md:px-5 py-2.5 sm:py-4 rounded-2xl sm:rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-500 sm:bg-blue-600 text-white max-w-[85%] sm:max-w-[85%] ml-auto" : "bg-gray-100 sm:bg-white sm:border sm:border-gray-200/80 max-w-full"}`,
49104
- children: [
49105
- /* @__PURE__ */ jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
49106
- message.role === "assistant" ? message.id === -1 ? /* @__PURE__ */ jsx(
49107
- "div",
49108
- {
49109
- className: "formatted-content",
49110
- dangerouslySetInnerHTML: { __html: formatMessage(message.content) }
49111
- }
49112
- ) : renderAssistantContent(message.content) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
49113
- message.id === -1 && /* @__PURE__ */ jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
49114
- ] }),
49115
- message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsx(
49116
- "button",
49117
- {
49118
- onClick: () => copyToClipboard(message.content, message.id.toString()),
49119
- className: "absolute top-2 sm:top-3 right-2 sm:right-3 opacity-100 sm:opacity-0 group-hover:opacity-100 transition-opacity duration-200 p-1 sm:p-1.5 hover:bg-gray-100 rounded-lg",
49120
- title: "Copy message",
49121
- children: copiedMessageId === message.id.toString() ? /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4 text-green-600" }) : /* @__PURE__ */ jsx(Copy, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4 text-gray-500" })
49122
- }
49123
- ),
49124
- message.reasoning && /* @__PURE__ */ jsxs("details", { className: "mt-3 pt-3 border-t border-gray-200", children: [
49125
- /* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-sm text-gray-600 hover:text-gray-800", children: "View reasoning" }),
49126
- /* @__PURE__ */ jsx("div", { className: "mt-2 text-sm text-gray-600", children: message.reasoning })
49127
- ] })
49128
- ]
49129
- }
49130
- ),
49131
- /* @__PURE__ */ jsxs("div", { className: `mt-1.5 sm:mt-2 flex items-center gap-2 text-xs text-gray-400 ${message.role === "user" ? "justify-end" : "justify-start"}`, children: [
49132
- /* @__PURE__ */ jsx("span", { children: formatTime5(message.created_at) }),
49133
- message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
49134
- /* @__PURE__ */ jsx("div", { className: "w-1 h-1 bg-gray-300 rounded-full" }),
49135
- /* @__PURE__ */ jsx("span", { children: "Axel" })
49136
- ] })
49137
- ] })
49138
- ] })
49139
- ]
49140
- },
49141
- message.id === -1 ? "streaming-message" : `${message.id}-${index}`
49142
- )),
49143
- lastError && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
49144
- /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-12 h-12 rounded-xl bg-red-100 flex items-center justify-center", children: /* @__PURE__ */ jsx(AlertCircle, { className: "w-6 h-6 text-red-600" }) }) }),
49145
- /* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: [
49146
- /* @__PURE__ */ jsx("p", { className: "text-red-800 text-sm", children: lastError }),
49147
- /* @__PURE__ */ jsx(
49148
- "button",
49149
- {
49150
- onClick: () => setLastError(null),
49151
- className: "mt-2 text-xs text-red-600 hover:text-red-800 underline",
49152
- children: "Dismiss"
49153
- }
49154
- )
49155
- ] })
49156
- ] }),
49157
- isCurrentThreadLoading && !currentStreaming.message && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
49158
- /* @__PURE__ */ jsx(ProfilePicture, {}),
49159
- /* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx("span", { className: "text-sm font-medium thinking-wave", children: "Thinking" }) }) })
49160
- ] }),
49161
- /* @__PURE__ */ jsx("div", { ref: messagesEndRef })
49162
- ] }) })
49163
- )
49164
- }
49165
- ),
49166
- (displayMessages.length > 0 || isTransitioning) && /* @__PURE__ */ jsx("footer", { className: `fixed bottom-0 left-0 right-0 bg-gradient-to-t from-white via-white/95 to-transparent sm:from-gray-50/50 sm:to-transparent pointer-events-none ${isSidebarOpen ? "lg:right-80" : "right-0"}`, children: /* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto p-2 sm:p-4 md:p-6 pointer-events-auto", children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
49167
- /* @__PURE__ */ jsx(
49168
- "div",
49169
- {
49170
- className: `relative bg-white rounded-xl sm:rounded-3xl shadow-md sm:shadow-lg border border-gray-200 focus-within:border-blue-400 sm:focus-within:border-gray-300 transition-all duration-200 ${isTransitioning ? "animate-slide-down" : ""}`,
49171
- style: isTransitioning ? {
49172
- animation: "slideDown 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards"
49173
- } : {},
49174
- children: /* @__PURE__ */ jsx("div", { className: "flex items-end gap-1 sm:gap-2 p-2 sm:p-4", children: /* @__PURE__ */ jsxs("div", { className: "flex-1 relative", children: [
49175
- /* @__PURE__ */ jsx(
49176
- "textarea",
49177
- {
49178
- ref: textareaRef,
49179
- value: inputValue,
49180
- onChange: (e) => {
49181
- const newValue = e.target.value;
49182
- setInputValue(newValue);
49183
- if (newValue.length > 0 && !hasStartedTyping) {
49184
- trackTypingStart();
49185
- }
49186
- if (newValue.length > 0) {
49187
- trackTypingProgress(newValue);
49188
- }
49189
- if (newValue.length === 0) {
49190
- resetTypingState();
49191
- }
49192
- },
49193
- onKeyDown: handleKeyDown,
49194
- onFocus: () => {
49195
- trackCoreEvent("AI Agent Input Focused", {
49196
- line_id: lineId,
49197
- company_id: companyId,
49198
- shift_id: shiftId,
49199
- active_thread_id: activeThreadId,
49200
- has_existing_messages: messages.length > 0,
49201
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
49202
- });
49203
- },
49204
- placeholder: "Message Axel...",
49205
- className: "w-full resize-none bg-transparent px-2 sm:px-4 py-2 sm:py-2 pr-10 sm:pr-14 focus:outline-none placeholder-gray-400 sm:placeholder-gray-500 text-gray-900 text-sm sm:text-base leading-relaxed",
49206
- rows: 1,
49207
- style: { minHeight: "36px", maxHeight: "120px" }
49208
- }
49209
- ),
49210
- /* @__PURE__ */ jsx("div", { className: "absolute right-1 sm:right-3 bottom-1 sm:bottom-2 flex items-center gap-2", children: /* @__PURE__ */ jsx(
49211
- "button",
49212
- {
49213
- type: "submit",
49214
- disabled: !inputValue.trim() || isCurrentThreadLoading,
49215
- className: "inline-flex items-center justify-center w-7 h-7 sm:w-9 sm:h-9 bg-blue-500 sm:bg-gray-900 text-white rounded-full active:scale-95 sm:hover:bg-gray-800 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-blue-400/20 sm:focus:ring-gray-500/20",
49216
- children: /* @__PURE__ */ jsx(Send, { className: "w-3.5 h-3.5 sm:w-4 sm:h-4" })
49217
- }
49218
- ) })
49219
- ] }) })
49220
- }
49221
- ),
49222
- /* @__PURE__ */ jsxs("div", { className: "hidden sm:flex flex-col sm:flex-row items-center justify-center gap-2 sm:gap-4 mt-2 text-xs text-gray-400", children: [
49223
- /* @__PURE__ */ jsx("span", { className: "text-center", children: isCurrentThreadLoading ? "You can type your next message while Axel responds" : "Press Enter to send \u2022 Shift+Enter for new line" }),
49224
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
49225
- /* @__PURE__ */ jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isCurrentThreadLoading ? "bg-orange-500" : "bg-green-500"}` }),
49226
- /* @__PURE__ */ jsx("span", { children: isCurrentThreadLoading ? "Responding..." : "Connected" })
49227
- ] })
49228
- ] })
49229
- ] }) }) })
49230
- ] }),
49231
- /* @__PURE__ */ jsx("div", { className: `fixed inset-0 sm:inset-auto sm:right-0 sm:top-0 z-20 h-screen transition-transform duration-300 ease-in-out ${isSidebarOpen ? "translate-x-0" : "translate-x-full"}`, children: /* @__PURE__ */ jsx("div", { className: "w-full sm:w-96 lg:w-80 h-full bg-white sm:border-l sm:border-gray-200 shadow-lg", children: /* @__PURE__ */ jsx(
49232
- ThreadSidebar,
49233
- {
49234
- activeThreadId,
49235
- onSelectThread: setActiveThreadId,
49236
- onNewThread: handleNewThread,
49237
- className: "h-full"
49238
- }
49239
- ) }) }),
49240
- isSidebarOpen && /* @__PURE__ */ jsx(
49241
- "div",
49242
- {
49243
- className: "fixed inset-0 bg-black bg-opacity-30 z-10 lg:hidden",
49244
- onClick: () => setIsSidebarOpen(false)
49245
- }
49246
- )
49247
- ] });
49248
- };
49249
- var AIAgentView_default = AIAgentView;
49250
47150
  function AuthCallbackView({
49251
47151
  redirectTo = "/",
49252
47152
  errorRedirect = "/login"
@@ -53303,6 +51203,14 @@ var ShiftsView = ({
53303
51203
  className = ""
53304
51204
  }) => {
53305
51205
  const supabase = useSupabase();
51206
+ const { lines: dbLines } = useLines();
51207
+ const mergedLineNames = useMemo(() => {
51208
+ const merged = { ...lineNames };
51209
+ dbLines.forEach((line) => {
51210
+ merged[line.id] = line.line_name;
51211
+ });
51212
+ return merged;
51213
+ }, [lineNames, dbLines]);
53306
51214
  useEffect(() => {
53307
51215
  console.log("[ShiftsView] Component mounted/re-rendered", {
53308
51216
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
@@ -53378,7 +51286,7 @@ var ShiftsView = ({
53378
51286
  return enabledConfigs.map((config) => {
53379
51287
  const rows = shiftsByLine[config.id] || [];
53380
51288
  const builtConfig = buildShiftConfigFromOperatingHoursRows(rows);
53381
- const lineName = lineNameMap[config.id] || lineNames[config.id] || `Line ${config.id.substring(0, 4)}`;
51289
+ const lineName = lineNameMap[config.id] || mergedLineNames[config.id] || `Line ${config.id.substring(0, 4)}`;
53382
51290
  const sortedShifts = [...builtConfig.shifts || []].sort((a, b) => a.shiftId - b.shiftId);
53383
51291
  return {
53384
51292
  ...config,
@@ -54937,6 +52845,14 @@ var TargetsView = ({
54937
52845
  const supabase = useSupabase();
54938
52846
  const effectiveUserId = userId || "6bf6f271-1e55-4a95-9b89-1c3820b58739";
54939
52847
  const dashboardConfig = useDashboardConfig();
52848
+ const { lines: dbLines } = useLines();
52849
+ const mergedLineNames = useMemo(() => {
52850
+ const merged = { ...lineNames };
52851
+ dbLines.forEach((line) => {
52852
+ merged[line.id] = line.line_name;
52853
+ });
52854
+ return merged;
52855
+ }, [lineNames, dbLines]);
54940
52856
  const { legend, updateLegend } = useEfficiencyLegend(companyId);
54941
52857
  const { skus, isLoading: skusLoading } = useSKUs(companyId);
54942
52858
  const skuEnabled = dashboardConfig?.skuConfig?.enabled || false;
@@ -55330,7 +53246,7 @@ var TargetsView = ({
55330
53246
  const { error: lineUpsertError } = await supabase.from("line_thresholds").upsert(lineThresholdData, { onConflict: "factory_id,line_id,date,shift_id" });
55331
53247
  if (lineUpsertError) {
55332
53248
  console.error(`[handleSaveLine] Error upserting line_thresholds for ${lineId}:`, lineUpsertError);
55333
- toast.error(`Failed to save line thresholds for ${lineNames[lineId] || lineId}`);
53249
+ toast.error(`Failed to save line thresholds for ${mergedLineNames[lineId] || lineId}`);
55334
53250
  throw lineUpsertError;
55335
53251
  }
55336
53252
  console.log(`[handleSaveLine] Successfully upserted line_thresholds for ${lineId}`);
@@ -55360,19 +53276,19 @@ var TargetsView = ({
55360
53276
  });
55361
53277
  console.log(`[handleSaveLine] Cleared user edited fields for line ${lineId}`);
55362
53278
  setSaveSuccess((prev) => ({ ...prev, [lineId]: true }));
55363
- toast.success(`${lineNames[lineId] || lineId} targets saved successfully`);
53279
+ toast.success(`${mergedLineNames[lineId] || lineId} targets saved successfully`);
55364
53280
  if (onSaveChanges) onSaveChanges(lineId);
55365
53281
  setTimeout(() => setSaveSuccess((prev) => ({ ...prev, [lineId]: false })), 3e3);
55366
53282
  console.log(`[handleSaveLine] Save process completed successfully for ${lineId}`);
55367
53283
  } catch (error) {
55368
53284
  console.error(`[handleSaveLine] Error saving targets for ${lineId}:`, error);
55369
53285
  const errorMessage = typeof error === "object" && error !== null && "message" in error ? error.message : "Unknown error";
55370
- toast.error(`Failed to save ${lineNames[lineId] || lineId} targets: ${errorMessage}`);
53286
+ toast.error(`Failed to save ${mergedLineNames[lineId] || lineId} targets: ${errorMessage}`);
55371
53287
  } finally {
55372
53288
  setSavingLines((prev) => ({ ...prev, [lineId]: false }));
55373
53289
  console.log(`[handleSaveLine] Set savingLines to false for ${lineId} in finally block`);
55374
53290
  }
55375
- }, [canSaveTargets, supabase, lineWorkspaces, selectedShift, lineNames, onSaveChanges, skuEnabled, dashboardConfig]);
53291
+ }, [canSaveTargets, supabase, lineWorkspaces, selectedShift, mergedLineNames, onSaveChanges, skuEnabled, dashboardConfig]);
55376
53292
  const handleSaveLegend = useCallback(async (nextLegend) => {
55377
53293
  if (!canSaveTargets) {
55378
53294
  toast.error("You do not have permission to update the legend.");
@@ -55421,7 +53337,7 @@ var TargetsView = ({
55421
53337
  {
55422
53338
  isLoading: isLoading || skusLoading,
55423
53339
  lineWorkspaces,
55424
- lineNames,
53340
+ lineNames: mergedLineNames,
55425
53341
  dropdownStates,
55426
53342
  savingLines,
55427
53343
  saveSuccess,
@@ -59524,16 +57440,59 @@ var ImprovementCenterView = () => {
59524
57440
  const diffDays = Math.max(0, Math.floor((now2.getTime() - firstSeen.getTime()) / (1e3 * 60 * 60 * 24)));
59525
57441
  return Math.max(1, Math.ceil(diffDays / 7));
59526
57442
  };
57443
+ const toZonedDate = (value) => {
57444
+ if (!value) return void 0;
57445
+ const raw = new Date(value);
57446
+ if (Number.isNaN(raw.getTime())) return void 0;
57447
+ return new Date(raw.toLocaleString("en-US", { timeZone: timezone }));
57448
+ };
57449
+ const getDaySuffix = (day) => {
57450
+ const dayMod = day % 100;
57451
+ if (dayMod >= 11 && dayMod <= 13) return "th";
57452
+ if (day % 10 === 1) return "st";
57453
+ if (day % 10 === 2) return "nd";
57454
+ if (day % 10 === 3) return "rd";
57455
+ return "th";
57456
+ };
59527
57457
  const formatOpenedDate = (firstSeenAt) => {
59528
57458
  if (!firstSeenAt) return void 0;
59529
- const raw = new Date(firstSeenAt);
59530
- if (Number.isNaN(raw.getTime())) return void 0;
59531
- const zoned = new Date(raw.toLocaleString("en-US", { timeZone: timezone }));
57459
+ const zoned = toZonedDate(firstSeenAt);
57460
+ if (!zoned) return void 0;
59532
57461
  const day = zoned.getDate();
59533
57462
  const month = zoned.toLocaleString("en-US", { month: "short" });
59534
- const dayMod = day % 100;
59535
- const suffix = dayMod >= 11 && dayMod <= 13 ? "th" : day % 10 === 1 ? "st" : day % 10 === 2 ? "nd" : day % 10 === 3 ? "rd" : "th";
59536
- return `${day}${suffix} ${month}`;
57463
+ return `${day}${getDaySuffix(day)} ${month}`;
57464
+ };
57465
+ const formatMonthDay = (date) => {
57466
+ const month = date.toLocaleString("en-US", { month: "short" });
57467
+ return `${month} ${date.getDate()}`;
57468
+ };
57469
+ const formatDayMonth = (date, withSuffix = true) => {
57470
+ const day = date.getDate();
57471
+ const month = date.toLocaleString("en-US", { month: "short" });
57472
+ return withSuffix ? `${day}${getDaySuffix(day)} ${month}` : `${day} ${month}`;
57473
+ };
57474
+ const formatPeriodRange = (start, end) => {
57475
+ const startDate = toZonedDate(start);
57476
+ const endDate = toZonedDate(end);
57477
+ if (!startDate || !endDate) return void 0;
57478
+ return `${formatMonthDay(startDate)} - ${formatMonthDay(endDate)}`;
57479
+ };
57480
+ const stripPeriodFromDescription = (description, start, end) => {
57481
+ if (!description) return description;
57482
+ const startDate = toZonedDate(start);
57483
+ const endDate = toZonedDate(end);
57484
+ if (!startDate || !endDate) return description;
57485
+ const labels = [
57486
+ `${formatMonthDay(startDate)} - ${formatMonthDay(endDate)}`,
57487
+ `${formatDayMonth(startDate)} - ${formatDayMonth(endDate)}`,
57488
+ `${formatDayMonth(startDate, false)} - ${formatDayMonth(endDate, false)}`
57489
+ ];
57490
+ let cleaned = description;
57491
+ labels.forEach((label) => {
57492
+ cleaned = cleaned.replace(`(${label})`, "").replace(` (${label})`, "");
57493
+ });
57494
+ cleaned = cleaned.replace(/\s{2,}/g, " ").replace(/\s+([.,])/g, "$1").trim();
57495
+ return cleaned;
59537
57496
  };
59538
57497
  const configuredLines = useMemo(() => {
59539
57498
  return entityConfig.lines || entityConfig.lineNames || {};
@@ -59743,7 +57702,7 @@ var ImprovementCenterView = () => {
59743
57702
  }
59744
57703
  if (selectedMemberId !== "all" && !(rec.assigned_user_ids?.includes(selectedMemberId) || rec.assigned_to_user_id === selectedMemberId)) return false;
59745
57704
  return true;
59746
- }).sort((a, b) => (b.weeks_open || 0) - (a.weeks_open || 0));
57705
+ }).sort((a, b) => (a.issue_number || 0) - (b.issue_number || 0));
59747
57706
  }, [recommendations, selectedLineId, selectedStatus, selectedShift, selectedWeeksRange, selectedMemberId]);
59748
57707
  const stats = useMemo(() => {
59749
57708
  const baseFiltered = recommendations.filter((rec) => {
@@ -59965,7 +57924,9 @@ var ImprovementCenterView = () => {
59965
57924
  filteredRecommendations.length > 0 ? filteredRecommendations.map((rec, index) => {
59966
57925
  const weeksOpen = rec.weeks_open || 1;
59967
57926
  const openLabel = weeksOpen <= 1 ? "Opened this week" : `Opened for ${weeksOpen} weeks`;
59968
- const openedOnLabel = formatOpenedDate(rec.first_seen_at);
57927
+ formatOpenedDate(rec.first_seen_at);
57928
+ const periodLabel = formatPeriodRange(rec.period_start, rec.period_end);
57929
+ const description = stripPeriodFromDescription(rec.description, rec.period_start, rec.period_end);
59969
57930
  return /* @__PURE__ */ jsx(
59970
57931
  motion.div,
59971
57932
  {
@@ -59988,10 +57949,6 @@ var ImprovementCenterView = () => {
59988
57949
  /* @__PURE__ */ jsx(ClockIcon, { className: "w-3.5 h-3.5" }),
59989
57950
  openLabel
59990
57951
  ] }),
59991
- openedOnLabel && /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 px-2.5 py-0.5 rounded-full text-xs font-medium text-gray-600 bg-gray-100 border border-gray-200", children: [
59992
- "Opened on ",
59993
- openedOnLabel
59994
- ] }),
59995
57952
  rec.assigned_user_ids && rec.assigned_user_ids.length > 0 && /* @__PURE__ */ jsxs(Fragment, { children: [
59996
57953
  /* @__PURE__ */ jsx("div", { className: "h-3 w-px bg-gray-200" }),
59997
57954
  /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: rec.assigned_user_ids.map((uid) => {
@@ -60018,14 +57975,22 @@ var ImprovementCenterView = () => {
60018
57975
  (rec.shift_label || rec.shift_id !== void 0) && /* @__PURE__ */ jsxs(Fragment, { children: [
60019
57976
  /* @__PURE__ */ jsx("span", { children: "\u2022" }),
60020
57977
  /* @__PURE__ */ jsx("span", { className: "uppercase tracking-wide text-xs pt-0.5 text-gray-500 font-medium", children: rec.shift_label || `Shift ${rec.shift_id}` })
57978
+ ] }),
57979
+ periodLabel && /* @__PURE__ */ jsxs(Fragment, { children: [
57980
+ /* @__PURE__ */ jsx("span", { children: "\u2022" }),
57981
+ /* @__PURE__ */ jsx("span", { className: "text-gray-500 font-medium", children: periodLabel })
60021
57982
  ] })
60022
57983
  ] })
60023
57984
  ] })
60024
57985
  ] }) }),
60025
- /* @__PURE__ */ jsx("div", { className: "prose prose-sm text-gray-600", children: /* @__PURE__ */ jsx("p", { children: rec.description }) }),
57986
+ /* @__PURE__ */ jsx("div", { className: "prose prose-sm text-gray-600", children: /* @__PURE__ */ jsx("p", { children: description }) }),
60026
57987
  rec.resolution_instructions && /* @__PURE__ */ jsx("div", { className: "bg-blue-50 border border-blue-100 rounded-lg p-3", children: /* @__PURE__ */ jsxs("p", { className: "text-sm text-blue-800 font-medium flex items-start gap-2", children: [
60027
57988
  /* @__PURE__ */ jsx(CheckCircleIcon, { className: "w-5 h-5 flex-shrink-0" }),
60028
- rec.resolution_instructions
57989
+ /* @__PURE__ */ jsxs("span", { children: [
57990
+ /* @__PURE__ */ jsx("span", { className: "font-semibold", children: "Resolution Condition:" }),
57991
+ " ",
57992
+ rec.resolution_instructions
57993
+ ] })
60029
57994
  ] }) })
60030
57995
  ] }),
60031
57996
  /* @__PURE__ */ 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__ */ jsx(
@@ -60516,5 +58481,84 @@ var streamProxyConfig = {
60516
58481
  responseLimit: false
60517
58482
  }
60518
58483
  };
58484
+ var ThreadSidebar = ({
58485
+ activeThreadId,
58486
+ onSelectThread,
58487
+ onNewThread,
58488
+ className = ""
58489
+ }) => {
58490
+ const { threads, isLoading, error, deleteThread: deleteThread2 } = useThreads();
58491
+ const [deletingId, setDeletingId] = useState(null);
58492
+ const handleDelete = async (e, threadId) => {
58493
+ e.stopPropagation();
58494
+ if (confirm("Are you sure you want to delete this conversation?")) {
58495
+ setDeletingId(threadId);
58496
+ try {
58497
+ await deleteThread2(threadId);
58498
+ if (activeThreadId === threadId) {
58499
+ onNewThread();
58500
+ }
58501
+ } catch (error2) {
58502
+ console.error("Error deleting thread:", error2);
58503
+ alert("Failed to delete conversation. Please try again.");
58504
+ } finally {
58505
+ setDeletingId(null);
58506
+ }
58507
+ }
58508
+ };
58509
+ const formatDate2 = (dateString) => {
58510
+ const date = new Date(dateString);
58511
+ const now2 = /* @__PURE__ */ new Date();
58512
+ const diffMs = now2.getTime() - date.getTime();
58513
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
58514
+ if (diffDays === 0) {
58515
+ return "Today";
58516
+ } else if (diffDays === 1) {
58517
+ return "Yesterday";
58518
+ } else if (diffDays < 7) {
58519
+ return date.toLocaleDateString("en-US", { weekday: "short" });
58520
+ } else {
58521
+ return date.toLocaleDateString("en-US", { month: "short", day: "numeric" });
58522
+ }
58523
+ };
58524
+ if (error) {
58525
+ return /* @__PURE__ */ jsx("div", { className: `p-4 text-red-600 text-sm ${className}`, children: "Failed to load conversations" });
58526
+ }
58527
+ return /* @__PURE__ */ jsxs("div", { className: `flex flex-col h-screen bg-gray-50 border-r border-gray-200 ${className}`, children: [
58528
+ /* @__PURE__ */ jsxs("div", { className: "flex-shrink-0 p-4 border-b border-gray-200", children: [
58529
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Chat History" }),
58530
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 mt-1", children: "Your previous conversations" })
58531
+ ] }),
58532
+ /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto min-h-0", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center p-8", children: /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "sm" }) }) : threads.length === 0 ? /* @__PURE__ */ jsx("div", { className: "p-4 text-center text-gray-500 text-sm", children: "No conversations yet" }) : /* @__PURE__ */ jsx("div", { className: "py-2", children: threads.map((thread) => /* @__PURE__ */ jsxs(
58533
+ "div",
58534
+ {
58535
+ onClick: () => onSelectThread(thread.id),
58536
+ className: `group relative flex items-start gap-3 px-4 py-3 cursor-pointer transition-all ${activeThreadId === thread.id ? "bg-blue-50 border-l-4 border-blue-600 hover:bg-blue-100" : "hover:bg-gray-100 border-l-4 border-transparent"}`,
58537
+ children: [
58538
+ /* @__PURE__ */ jsx(MessageSquare, { className: `w-4 h-4 mt-0.5 flex-shrink-0 ${activeThreadId === thread.id ? "text-blue-600" : "text-gray-400"}` }),
58539
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
58540
+ /* @__PURE__ */ jsx("h3", { className: `text-sm font-medium truncate ${activeThreadId === thread.id ? "text-blue-900" : "text-gray-900"}`, children: thread.title || "Untitled Chat" }),
58541
+ /* @__PURE__ */ jsx("p", { className: `text-xs mt-0.5 ${activeThreadId === thread.id ? "text-blue-700" : "text-gray-500"}`, children: formatDate2(thread.created_at) })
58542
+ ] }),
58543
+ deletingId === thread.id ? /* @__PURE__ */ jsx(OptifyeLogoLoader_default, { size: "sm", className: "flex-shrink-0" }) : /* @__PURE__ */ jsx(
58544
+ "button",
58545
+ {
58546
+ onClick: (e) => handleDelete(e, thread.id),
58547
+ className: "flex-shrink-0 opacity-0 group-hover:opacity-100 p-1 hover:bg-gray-200 rounded transition-all",
58548
+ title: "Delete conversation",
58549
+ children: /* @__PURE__ */ jsx(Trash2, { className: "w-3.5 h-3.5 text-gray-500" })
58550
+ }
58551
+ )
58552
+ ]
58553
+ },
58554
+ thread.id
58555
+ )) }) }),
58556
+ /* @__PURE__ */ jsx("div", { className: "flex-shrink-0 p-4 border-t border-gray-200", children: /* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 text-center", children: [
58557
+ threads.length,
58558
+ " conversation",
58559
+ threads.length !== 1 ? "s" : ""
58560
+ ] }) })
58561
+ ] });
58562
+ };
60519
58563
 
60520
- export { ACTION_NAMES, AIAgentView_default as AIAgentView, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, TeamUsagePdfGenerator, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, buildDateKey, buildKPIsFromLineMetricsRow, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAvailableShiftIds, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getReasonColor, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isFullMonthRange, isLegacyConfiguration, isPrefetchError, isSafari, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeDateKeyRange, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMultiLineShiftConfigs, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };
58564
+ export { ACTION_NAMES, AcceptInvite, AcceptInviteView_default as AcceptInviteView, AdvancedFilterDialog, AdvancedFilterPanel, AudioService, AuthCallback, AuthCallbackView_default as AuthCallbackView, AuthProvider, AuthService, AuthenticatedBottleneckClipsView, AuthenticatedFactoryView, AuthenticatedHelpView, AuthenticatedHomeView, AuthenticatedShiftsView, AuthenticatedTargetsView, AuthenticatedTicketsView, AuthenticatedWorkspaceHealthView, AxelNotificationPopup, AxelOrb, BackButton, BackButtonMinimal, BarChart, BaseHistoryCalendar, BottleneckClipsModal, BottleneckClipsView_default as BottleneckClipsView, BottlenecksContent, BreakNotificationPopup, CachePrefetchStatus, Card2 as Card, CardContent2 as CardContent, CardDescription2 as CardDescription, CardFooter2 as CardFooter, CardHeader2 as CardHeader, CardTitle2 as CardTitle, ChangeRoleDialog, ClipFilterProvider, CompactWorkspaceHealthCard, ConfirmRemoveUserDialog, CongratulationsOverlay, CroppedHlsVideoPlayer, CroppedVideoPlayer, CycleTimeChart, CycleTimeOverTimeChart, DEFAULT_ANALYTICS_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_CONFIG, DEFAULT_DATABASE_CONFIG, DEFAULT_DATE_TIME_CONFIG, DEFAULT_ENDPOINTS_CONFIG, DEFAULT_ENTITY_CONFIG, DEFAULT_HOME_VIEW_CONFIG, DEFAULT_MAP_VIEW_CONFIG, DEFAULT_SHIFT_CONFIG, DEFAULT_SHIFT_DATA, DEFAULT_THEME_CONFIG, DEFAULT_VIDEO_CONFIG, DEFAULT_WORKSPACE_CONFIG, DEFAULT_WORKSPACE_POSITIONS, DashboardHeader, DashboardLayout, DashboardOverridesProvider, DashboardProvider, DateDisplay_default as DateDisplay, DateTimeDisplay, DebugAuth, DebugAuthView_default as DebugAuthView, DetailedHealthStatus, DiagnosisVideoModal, EmptyStateMessage, EncouragementOverlay, FactoryAssignmentDropdown, FactoryView_default as FactoryView, FileManagerFilters, FilterDialogTrigger, FirstTimeLoginDebug, FirstTimeLoginHandler, GaugeChart, GridComponentsPlaceholder, HamburgerButton, Header, HealthDateShiftSelector, HealthStatusGrid, HealthStatusIndicator, HelpView_default as HelpView, HlsVideoPlayer, HomeView_default as HomeView, HourlyOutputChart2 as HourlyOutputChart, ISTTimer_default as ISTTimer, ImprovementCenterView_default as ImprovementCenterView, InlineEditableText, InteractiveOnboardingTour, InvitationService, InvitationsTable, InviteUserDialog, KPICard, KPIDetailView_default as KPIDetailView, KPIGrid, KPIHeader, KPISection, KPIsOverviewView_default as KPIsOverviewView, LINE_1_UUID, LINE_2_UUID, LargeOutputProgressChart, LeaderboardDetailView_default as LeaderboardDetailView, Legend6 as Legend, LineAssignmentDropdown, LineChart, LineHistoryCalendar, LineMonthlyHistory, LineMonthlyPdfGenerator, LinePdfExportButton, LinePdfGenerator, LineWhatsAppShareButton, LinesService, LiveTimer, LoadingInline, LoadingOverlay_default as LoadingOverlay, LoadingPage_default as LoadingPage, LoadingSkeleton, LoadingState, LoginPage, LoginView_default as LoginView, Logo, MainLayout, MapGridView, MetricCard_default as MetricCard, MinimalOnboardingPopup, NewClipsNotification, NoWorkspaceData, OnboardingDemo, OnboardingTour, OptifyeAgentClient, OptifyeLogoLoader_default as OptifyeLogoLoader, OutputProgressChart, PageHeader, PieChart4 as PieChart, PlayPauseIndicator, PrefetchConfigurationError, PrefetchError, PrefetchEvents, PrefetchStatus, PrefetchTimeoutError, ProfileView_default as ProfileView, RegistryProvider, RoleBadge, S3ClipsSupabaseService as S3ClipsService, S3Service, SKUManagementView, SOPComplianceChart, SSEChatClient, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, SessionTracker, SessionTrackingContext, SessionTrackingProvider, ShiftDisplay_default as ShiftDisplay, ShiftsView_default as ShiftsView, SideNavBar, SignupWithInvitation, SilentErrorBoundary, SimpleOnboardingPopup, SingleVideoStream_default as SingleVideoStream, Skeleton, SubscriptionManager, SubscriptionManagerProvider, SupabaseProvider, SupervisorDropdown_default as SupervisorDropdown, SupervisorManagementView_default as SupervisorManagementView, SupervisorService, TargetWorkspaceGrid, TargetsView_default as TargetsView, TeamManagementView_default as TeamManagementView, TeamUsagePdfGenerator, ThreadSidebar, TicketHistory_default as TicketHistory, TicketHistoryService, TicketsView_default as TicketsView, TimeDisplay_default as TimeDisplay, TimePickerDropdown, Timer_default as Timer, TimezoneProvider, TimezoneService, UserManagementService, UserManagementTable, UserService, UserUsageDetailModal, UserUsageStats, VideoCard, VideoGridView, VideoPlayer, VideoPreloader, WORKSPACE_POSITIONS, WhatsAppShareButton, WorkspaceCard, WorkspaceDetailView_default as WorkspaceDetailView, WorkspaceDisplayNameExample, WorkspaceGrid, WorkspaceGridItem, WorkspaceHealthCard, WorkspaceHealthView_default as WorkspaceHealthView, WorkspaceHistoryCalendar, WorkspaceMetricCards, WorkspaceMetricCardsImpl, WorkspaceMonthlyDataFetcher, WorkspaceMonthlyHistory, WorkspaceMonthlyPdfGenerator, WorkspacePdfExportButton, WorkspacePdfGenerator, WorkspaceWhatsAppShareButton, actionService, aggregateKPIsFromLineMetricsRows, apiUtils, areAllLinesOnSameShift, authCoreService, authOTPService, authRateLimitService, buildDateKey, buildKPIsFromLineMetricsRow, checkRateLimit2 as checkRateLimit, clearAllRateLimits2 as clearAllRateLimits, clearRateLimit2 as clearRateLimit, clearS3VideoCache, clearS3VideoFromCache, clearWorkspaceDisplayNamesCache, cn, createDefaultKPIs, createInvitationService, createLinesService, createSessionTracker, createStreamProxyHandler, createSupabaseClient, createSupervisorService, createThrottledReload, createUserManagementService, createUserService, dashboardService, deleteThread, fetchIdleTimeReasons, filterDataByDateKeyRange, forceRefreshWorkspaceDisplayNames, formatDateInZone, formatDateKeyForDisplay, formatDateTimeInZone, formatDuration, formatISTDate, formatIdleTime, formatRangeLabel, formatReasonLabel, formatRelativeTime, formatTimeInZone, fromUrlFriendlyName, getAllLineDisplayNames, getAllThreadMessages, getAllWorkspaceDisplayNamesAsync, getAllWorkspaceDisplayNamesSnapshot, getAnonClient, getAvailableShiftIds, getBrowserName, getCameraNumber, getCompanyMetricsTableName, getConfigurableShortWorkspaceDisplayName, getConfigurableWorkspaceDisplayName, getConfiguredLineIds, getCoreSessionRecordingProperties, getCoreSessionReplayUrl, getCurrentShift, getCurrentShiftForLine, getCurrentTimeInZone, getDashboardHeaderTimeInZone, getDateKeyFromDate, getDaysDifferenceInZone, getDefaultCameraStreamUrl, getDefaultLineId, getDefaultTabForWorkspace, getLineDisplayName, getManufacturingInsights, getMetricsTablePrefix, getMonthKeyBounds, getMonthWeekRanges, getNextUpdateInterval, getOperationalDate, getReasonColor, getS3SignedUrl, getS3VideoSrc, getShiftData, getShiftNameById, getShortShiftName, getShortWorkspaceDisplayName, getShortWorkspaceDisplayNameAsync, getStoredWorkspaceMappings, getSubscriptionManager, getThreadMessages, getUniformShiftGroup, getUserThreads, getUserThreadsPaginated, getWorkspaceDisplayName, getWorkspaceDisplayNameAsync, getWorkspaceDisplayNamesMap, getWorkspaceFromUrl, getWorkspaceNavigationParams, groupLinesByShift, hasAnyShiftData, identifyCoreUser, initializeCoreMixpanel, isFullMonthRange, isLegacyConfiguration, isPrefetchError, isSafari, isTransitionPeriod, isUrlPermanentlyFailed, isValidFactoryViewConfiguration, isValidLineInfoPayload, isValidPrefetchParams, isValidPrefetchStatus, isValidWorkspaceDetailedMetricsPayload, isValidWorkspaceMetricsPayload, isWorkspaceDisplayNamesLoaded, isWorkspaceDisplayNamesLoading, linesService, mergeWithDefaultConfig, migrateLegacyConfiguration, normalizeDateKeyRange, optifyeAgentClient, parseDateKeyToDate, parseS3Uri, preInitializeWorkspaceDisplayNames, preloadS3Video, preloadS3VideoUrl, preloadS3VideosUrl, preloadVideoUrl, preloadVideosUrl, qualityService, realtimeService, refreshWorkspaceDisplayNames, resetCoreMixpanel, resetFailedUrl, resetSubscriptionManager, s3VideoPreloader, shuffleArray, simulateApiDelay, skuService, startCoreSessionRecording, stopCoreSessionRecording, storeWorkspaceMapping, streamProxyConfig, subscribeWorkspaceDisplayNames, throttledReloadDashboard, toUrlFriendlyName, trackCoreEvent, trackCorePageView, transformToChartData, updateThreadTitle, upsertWorkspaceDisplayNameInCache, useAccessControl, useActiveBreaks, useActiveLineId, useAllWorkspaceMetrics, useAnalyticsConfig, useAppTimezone, useAudioService, useAuth, useAuthConfig, useAxelNotifications, useCanSaveTargets, useClipFilter, useClipTypes, useClipTypesWithCounts, useCompanyUsersUsage, useComponentOverride, useCustomConfig, useDashboardConfig, useDashboardMetrics, useDatabaseConfig, useDateFormatter, useDateTimeConfig, useDynamicShiftConfig, useEndpointsConfig, useEntityConfig, useFactoryOverviewMetrics, useFeatureFlags, useFormatNumber, useHasLineAccess, useHistoricWorkspaceMetrics, useHlsStream, useHlsStreamWithCropping, useHookOverride, useHourEndTimer, useHourlyTargetAchievements, useHourlyTargetMisses, useIdleTimeClipClassifications, useIdleTimeReasons, useLeaderboardMetrics, useLineDetailedMetrics, useLineKPIs, useLineMetrics, useLineShiftConfig, useLineSupervisor, useLineWorkspaceMetrics, useLines, useMessages, useMetrics, useMultiLineShiftConfigs, useNavigation, useOverrides, usePageOverride, usePrefetchClipCounts, useRealtimeLineMetrics, useRegistry, useSKUs, useSessionKeepAlive, useSessionTracking, useSessionTrackingContext, useShiftConfig, useShifts, useSubscriptionManager, useSubscriptionManagerSafe, useSupabase, useSupabaseClient, useSupervisorsByLineIds, useTargets, useTeamManagementPermissions, useTheme, useThemeConfig, useThreads, useTicketHistory, useTimezoneContext, useUserLineAccess, useUserUsage, useVideoConfig, useWorkspaceConfig, useWorkspaceDetailedMetrics, useWorkspaceDisplayName, useWorkspaceDisplayNames, useWorkspaceDisplayNamesMap, useWorkspaceHealthById, useWorkspaceHealthStatus, useWorkspaceMetrics, useWorkspaceNavigation, useWorkspaceOperators, useWorkspaceUptimeTimeline, userService, videoPrefetchManager, videoPreloader, whatsappService, withAccessControl, withAuth, withRegistry, withTimezone, workspaceHealthService, workspaceService };