@optifye/dashboard-core 4.1.0 → 4.1.2
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.d.mts +31 -2
- package/dist/index.d.ts +31 -2
- package/dist/index.js +780 -162
- package/dist/index.mjs +781 -163
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -12,7 +12,7 @@ import { noop, warning, invariant, progress, secondsToMilliseconds, milliseconds
|
|
|
12
12
|
import { getValueTransition, hover, press, isPrimaryPointer, GroupPlaybackControls, setDragLock, supportsLinearEasing, attachTimeline, isGenerator, calcGeneratorDuration, isWaapiSupportedEasing, mapEasingToNativeEasing, maxGeneratorDuration, generateLinearEasing, isBezierDefinition } from 'motion-dom';
|
|
13
13
|
import { ResponsiveContainer, BarChart as BarChart$1, CartesianGrid, XAxis, YAxis, Tooltip, ReferenceLine, Bar, Cell, LabelList, PieChart, Pie, Legend, LineChart as LineChart$1, Line } from 'recharts';
|
|
14
14
|
import { Slot } from '@radix-ui/react-slot';
|
|
15
|
-
import { Camera, Map as Map$1, Video, ChevronDown, ChevronUp, Check, X, Clock, Coffee, Plus, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2,
|
|
15
|
+
import { Camera, Map as Map$1, Video, ChevronDown, ChevronUp, Check, X, Clock, Coffee, Plus, Minus, ArrowDown, ArrowUp, Search, CheckCircle, AlertTriangle, Info, Share2, Download, User, XCircle, ChevronLeft, ChevronRight, AlertCircle, Sun, Moon, MessageSquare, Trash2, ArrowLeft, Menu, RefreshCw, Send, Copy, Edit2, UserCheck, Save, LogOut, Calendar, Clock8, AlarmClock, Settings, LifeBuoy, Loader2, ArrowLeftIcon as ArrowLeftIcon$1, Settings2, CheckCircle2, Zap, UserCircle } from 'lucide-react';
|
|
16
16
|
import { DayPicker, useNavigation as useNavigation$1 } from 'react-day-picker';
|
|
17
17
|
import html2canvas from 'html2canvas';
|
|
18
18
|
import jsPDF, { jsPDF as jsPDF$1 } from 'jspdf';
|
|
@@ -25308,6 +25308,32 @@ var S3ClipsService = class {
|
|
|
25308
25308
|
return null;
|
|
25309
25309
|
}
|
|
25310
25310
|
}
|
|
25311
|
+
/**
|
|
25312
|
+
* Fetches full metadata including timestamps
|
|
25313
|
+
*/
|
|
25314
|
+
async getFullMetadata(playlistUri) {
|
|
25315
|
+
try {
|
|
25316
|
+
const metadataUri = playlistUri.replace(/playlist\.m3u8$/, "metadata.json");
|
|
25317
|
+
const url = new URL(metadataUri);
|
|
25318
|
+
const bucket = url.hostname;
|
|
25319
|
+
const key = url.pathname.substring(1);
|
|
25320
|
+
const command = new GetObjectCommand({
|
|
25321
|
+
Bucket: bucket,
|
|
25322
|
+
Key: key
|
|
25323
|
+
});
|
|
25324
|
+
const response = await this.s3Client.send(command);
|
|
25325
|
+
if (!response.Body) {
|
|
25326
|
+
console.warn(`Empty response body for metadata file: ${key}`);
|
|
25327
|
+
return null;
|
|
25328
|
+
}
|
|
25329
|
+
const metadataContent = await response.Body.transformToString();
|
|
25330
|
+
const metadata = JSON.parse(metadataContent);
|
|
25331
|
+
return metadata;
|
|
25332
|
+
} catch (error) {
|
|
25333
|
+
console.error(`Error fetching or parsing metadata:`, error);
|
|
25334
|
+
return null;
|
|
25335
|
+
}
|
|
25336
|
+
}
|
|
25311
25337
|
/**
|
|
25312
25338
|
* Converts S3 URI to CloudFront URL
|
|
25313
25339
|
* Uses streaming proxy for localhost development to handle CORS
|
|
@@ -25320,15 +25346,22 @@ var S3ClipsService = class {
|
|
|
25320
25346
|
/**
|
|
25321
25347
|
* Processes a single video completely
|
|
25322
25348
|
*/
|
|
25323
|
-
async processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime) {
|
|
25349
|
+
async processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime, includeMetadata = false) {
|
|
25324
25350
|
const parsedInfo = parseS3Uri(uri);
|
|
25325
25351
|
if (!parsedInfo) {
|
|
25326
25352
|
console.warn(`Skipping URI due to parsing failure: ${uri}`);
|
|
25327
25353
|
return null;
|
|
25328
25354
|
}
|
|
25329
25355
|
let cycleTimeSeconds = null;
|
|
25330
|
-
|
|
25331
|
-
|
|
25356
|
+
let creationTimestamp = void 0;
|
|
25357
|
+
if (includeMetadata || includeCycleTime && (parsedInfo.type === "bottleneck" && parsedInfo.description.toLowerCase().includes("cycle time") || parsedInfo.type === "best_cycle_time" || parsedInfo.type === "worst_cycle_time")) {
|
|
25358
|
+
const metadata = await this.getFullMetadata(uri);
|
|
25359
|
+
if (metadata) {
|
|
25360
|
+
if (metadata.original_task_metadata?.cycle_time) {
|
|
25361
|
+
cycleTimeSeconds = metadata.original_task_metadata.cycle_time;
|
|
25362
|
+
}
|
|
25363
|
+
creationTimestamp = metadata.upload_timestamp || metadata.original_task_metadata?.timestamp || metadata.creation_timestamp || metadata[""];
|
|
25364
|
+
}
|
|
25332
25365
|
}
|
|
25333
25366
|
const cloudfrontPlaylistUrl = this.s3UriToCloudfront(uri);
|
|
25334
25367
|
const { type: videoType, timestamp: videoTimestamp } = parsedInfo;
|
|
@@ -25337,7 +25370,8 @@ var S3ClipsService = class {
|
|
|
25337
25370
|
src: cloudfrontPlaylistUrl,
|
|
25338
25371
|
// Direct CloudFront playlist URL
|
|
25339
25372
|
...parsedInfo,
|
|
25340
|
-
cycle_time_seconds: cycleTimeSeconds || void 0
|
|
25373
|
+
cycle_time_seconds: cycleTimeSeconds || void 0,
|
|
25374
|
+
creation_timestamp: creationTimestamp
|
|
25341
25375
|
};
|
|
25342
25376
|
}
|
|
25343
25377
|
/**
|
|
@@ -25399,7 +25433,7 @@ var S3ClipsService = class {
|
|
|
25399
25433
|
* Main method to fetch clips based on parameters
|
|
25400
25434
|
*/
|
|
25401
25435
|
async fetchClips(params) {
|
|
25402
|
-
const { workspaceId, date: inputDate, shift, category, limit, mode, includeCycleTime } = params;
|
|
25436
|
+
const { workspaceId, date: inputDate, shift, category, limit, mode, includeCycleTime, includeMetadata, timestampStart, timestampEnd } = params;
|
|
25403
25437
|
if (!workspaceId) {
|
|
25404
25438
|
throw new Error("Valid Workspace ID is required");
|
|
25405
25439
|
}
|
|
@@ -25504,7 +25538,7 @@ var S3ClipsService = class {
|
|
|
25504
25538
|
const batch = filteredUris.slice(i, i + concurrencyLimit);
|
|
25505
25539
|
const batchPromises = batch.map(async (uri, batchIndex) => {
|
|
25506
25540
|
const index = i + batchIndex;
|
|
25507
|
-
const result = await this.processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime || false);
|
|
25541
|
+
const result = await this.processFullVideo(uri, index, workspaceId, date, shiftId, includeCycleTime || false, includeMetadata || (!!timestampStart || !!timestampEnd));
|
|
25508
25542
|
processedCount++;
|
|
25509
25543
|
if (processedCount % 10 === 0) {
|
|
25510
25544
|
console.log(`S3ClipsService: Processed ${processedCount}/${filteredUris.length} videos for category '${category || "all"}'...`);
|
|
@@ -25514,7 +25548,26 @@ var S3ClipsService = class {
|
|
|
25514
25548
|
const batchResults = await Promise.all(batchPromises);
|
|
25515
25549
|
videoResults.push(...batchResults);
|
|
25516
25550
|
}
|
|
25517
|
-
|
|
25551
|
+
let videos = videoResults.filter((v) => v !== null);
|
|
25552
|
+
if (timestampStart || timestampEnd) {
|
|
25553
|
+
videos = videos.filter((video) => {
|
|
25554
|
+
if (!video.creation_timestamp) return false;
|
|
25555
|
+
const videoTimestamp = new Date(video.creation_timestamp).getTime();
|
|
25556
|
+
if (timestampStart && timestampEnd) {
|
|
25557
|
+
const start = new Date(timestampStart).getTime();
|
|
25558
|
+
const end = new Date(timestampEnd).getTime();
|
|
25559
|
+
return videoTimestamp >= start && videoTimestamp <= end;
|
|
25560
|
+
} else if (timestampStart) {
|
|
25561
|
+
const start = new Date(timestampStart).getTime();
|
|
25562
|
+
return videoTimestamp >= start;
|
|
25563
|
+
} else if (timestampEnd) {
|
|
25564
|
+
const end = new Date(timestampEnd).getTime();
|
|
25565
|
+
return videoTimestamp <= end;
|
|
25566
|
+
}
|
|
25567
|
+
return true;
|
|
25568
|
+
});
|
|
25569
|
+
console.log(`S3ClipsService: Filtered by timestamp - ${videos.length} videos remain after filtering`);
|
|
25570
|
+
}
|
|
25518
25571
|
console.log(`S3ClipsService: Successfully processed ${videos.length} out of ${filteredUris.length} video clips for category '${category || "all"}' (limit: ${limitPerCategory} per category).`);
|
|
25519
25572
|
const typeCounts = videos.reduce((acc, video) => {
|
|
25520
25573
|
acc[video.type] = (acc[video.type] || 0) + 1;
|
|
@@ -25559,6 +25612,7 @@ var BottlenecksContent = ({
|
|
|
25559
25612
|
const dashboardConfig = useDashboardConfig();
|
|
25560
25613
|
const videoRef = useRef(null);
|
|
25561
25614
|
const fullscreenContainerRef = useRef(null);
|
|
25615
|
+
const timestampFilterRef = useRef(null);
|
|
25562
25616
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
25563
25617
|
const [currentTime, setCurrentTime] = useState(0);
|
|
25564
25618
|
const [duration, setDuration] = useState(0);
|
|
@@ -25568,6 +25622,22 @@ var BottlenecksContent = ({
|
|
|
25568
25622
|
const [allVideos, setAllVideos] = useState([]);
|
|
25569
25623
|
const [isLoading, setIsLoading] = useState(true);
|
|
25570
25624
|
const [error, setError] = useState(null);
|
|
25625
|
+
const [showTimestampFilter, setShowTimestampFilter] = useState(false);
|
|
25626
|
+
const [timestampStart, setTimestampStart] = useState("");
|
|
25627
|
+
const [timestampEnd, setTimestampEnd] = useState("");
|
|
25628
|
+
useEffect(() => {
|
|
25629
|
+
const handleClickOutside = (event) => {
|
|
25630
|
+
if (timestampFilterRef.current && !timestampFilterRef.current.contains(event.target)) {
|
|
25631
|
+
setShowTimestampFilter(false);
|
|
25632
|
+
}
|
|
25633
|
+
};
|
|
25634
|
+
if (showTimestampFilter) {
|
|
25635
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
25636
|
+
}
|
|
25637
|
+
return () => {
|
|
25638
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
25639
|
+
};
|
|
25640
|
+
}, [showTimestampFilter]);
|
|
25571
25641
|
const s3ClipsService = useMemo(() => {
|
|
25572
25642
|
if (!dashboardConfig?.s3Config) {
|
|
25573
25643
|
console.warn("S3 configuration not found in dashboard config");
|
|
@@ -25580,13 +25650,26 @@ var BottlenecksContent = ({
|
|
|
25580
25650
|
setIsLoading(true);
|
|
25581
25651
|
setError(null);
|
|
25582
25652
|
try {
|
|
25653
|
+
const operationalDate = date || getOperationalDate();
|
|
25654
|
+
let timestampStartFull;
|
|
25655
|
+
let timestampEndFull;
|
|
25656
|
+
if (timestampStart) {
|
|
25657
|
+
timestampStartFull = `${operationalDate}T${timestampStart}:00`;
|
|
25658
|
+
}
|
|
25659
|
+
if (timestampEnd) {
|
|
25660
|
+
timestampEndFull = `${operationalDate}T${timestampEnd}:00`;
|
|
25661
|
+
}
|
|
25583
25662
|
const videos = await s3ClipsService.fetchClips({
|
|
25584
25663
|
workspaceId,
|
|
25585
|
-
date:
|
|
25664
|
+
date: operationalDate,
|
|
25586
25665
|
mode: "full",
|
|
25587
25666
|
includeCycleTime: true,
|
|
25588
|
-
|
|
25667
|
+
includeMetadata: true,
|
|
25668
|
+
// Always include metadata for timestamp info
|
|
25669
|
+
limit: 50,
|
|
25589
25670
|
// Reasonable limit for UI performance
|
|
25671
|
+
timestampStart: timestampStartFull,
|
|
25672
|
+
timestampEnd: timestampEndFull
|
|
25590
25673
|
});
|
|
25591
25674
|
if (Array.isArray(videos) && videos.length > 0) {
|
|
25592
25675
|
preloadVideoUrl2(videos[0].src);
|
|
@@ -25614,7 +25697,7 @@ var BottlenecksContent = ({
|
|
|
25614
25697
|
} finally {
|
|
25615
25698
|
setIsLoading(false);
|
|
25616
25699
|
}
|
|
25617
|
-
}, [workspaceId, date, s3ClipsService]);
|
|
25700
|
+
}, [workspaceId, date, s3ClipsService, timestampStart, timestampEnd]);
|
|
25618
25701
|
useEffect(() => {
|
|
25619
25702
|
if (s3ClipsService) {
|
|
25620
25703
|
fetchClips();
|
|
@@ -25983,6 +26066,43 @@ var BottlenecksContent = ({
|
|
|
25983
26066
|
return "Bottleneck";
|
|
25984
26067
|
}
|
|
25985
26068
|
};
|
|
26069
|
+
const formatTimestamp = (timestamp) => {
|
|
26070
|
+
if (!timestamp) return "";
|
|
26071
|
+
try {
|
|
26072
|
+
const date2 = new Date(timestamp);
|
|
26073
|
+
const today = /* @__PURE__ */ new Date();
|
|
26074
|
+
const isToday = date2.toDateString() === today.toDateString();
|
|
26075
|
+
if (isToday) {
|
|
26076
|
+
return date2.toLocaleString("en-US", {
|
|
26077
|
+
hour: "numeric",
|
|
26078
|
+
minute: "2-digit",
|
|
26079
|
+
hour12: true
|
|
26080
|
+
});
|
|
26081
|
+
} else {
|
|
26082
|
+
return date2.toLocaleString("en-US", {
|
|
26083
|
+
month: "short",
|
|
26084
|
+
day: "numeric",
|
|
26085
|
+
hour: "numeric",
|
|
26086
|
+
minute: "2-digit",
|
|
26087
|
+
hour12: true
|
|
26088
|
+
});
|
|
26089
|
+
}
|
|
26090
|
+
} catch {
|
|
26091
|
+
return "";
|
|
26092
|
+
}
|
|
26093
|
+
};
|
|
26094
|
+
const formatTimeOnly = (time2) => {
|
|
26095
|
+
if (!time2) return "";
|
|
26096
|
+
try {
|
|
26097
|
+
const [hours, minutes] = time2.split(":");
|
|
26098
|
+
const hour = parseInt(hours);
|
|
26099
|
+
const ampm = hour >= 12 ? "PM" : "AM";
|
|
26100
|
+
const displayHour = hour % 12 || 12;
|
|
26101
|
+
return `${displayHour}:${minutes} ${ampm}`;
|
|
26102
|
+
} catch {
|
|
26103
|
+
return time2;
|
|
26104
|
+
}
|
|
26105
|
+
};
|
|
25986
26106
|
if (!dashboardConfig?.s3Config) {
|
|
25987
26107
|
return /* @__PURE__ */ jsxs("div", { className: "flex-grow p-4 flex flex-col items-center justify-center h-[calc(100vh-12rem)] text-center", children: [
|
|
25988
26108
|
/* @__PURE__ */ jsx(XCircle, { className: "w-12 h-12 text-red-400 mb-3" }),
|
|
@@ -26091,6 +26211,74 @@ var BottlenecksContent = ({
|
|
|
26091
26211
|
/* @__PURE__ */ jsx("div", { className: "px-4 py-3 border-b border-gray-100", children: /* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center", children: [
|
|
26092
26212
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-800", children: activeFilter === "low_value" ? `Low Value Moments (${clipCounts.lowValue})` : activeFilter === "best_cycle_time" ? `Best Cycle Times (${clipCounts.bestCycleTimes})` : activeFilter === "worst_cycle_time" ? `Worst Cycle Times (${clipCounts.worstCycleTimes})` : activeFilter === "long_cycle_time" ? `Long Cycle Time (${clipCounts.longCycleTimes})` : `All Clips (${clipCounts.total})` }),
|
|
26093
26213
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
26214
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", ref: timestampFilterRef, children: [
|
|
26215
|
+
/* @__PURE__ */ jsx(
|
|
26216
|
+
"button",
|
|
26217
|
+
{
|
|
26218
|
+
onClick: () => setShowTimestampFilter(!showTimestampFilter),
|
|
26219
|
+
className: `p-2 rounded-lg transition-all ${timestampStart || timestampEnd ? "bg-blue-50 text-blue-600 hover:bg-blue-100" : "text-gray-600 hover:bg-gray-100"}`,
|
|
26220
|
+
"aria-label": "Filter by time",
|
|
26221
|
+
title: "Filter by time",
|
|
26222
|
+
children: /* @__PURE__ */ jsx(Clock, { className: "h-5 w-5" })
|
|
26223
|
+
}
|
|
26224
|
+
),
|
|
26225
|
+
showTimestampFilter && /* @__PURE__ */ jsxs("div", { className: "absolute right-0 mt-2 w-80 bg-white rounded-lg shadow-lg border border-gray-200 p-4 z-20", children: [
|
|
26226
|
+
/* @__PURE__ */ jsx("h4", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Filter by Time" }),
|
|
26227
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
26228
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
26229
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "timestamp-start", className: "block text-xs font-medium text-gray-600 mb-1", children: "Start Time" }),
|
|
26230
|
+
/* @__PURE__ */ jsx(
|
|
26231
|
+
"input",
|
|
26232
|
+
{
|
|
26233
|
+
id: "timestamp-start",
|
|
26234
|
+
type: "time",
|
|
26235
|
+
value: timestampStart,
|
|
26236
|
+
onChange: (e) => setTimestampStart(e.target.value),
|
|
26237
|
+
className: "w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
26238
|
+
}
|
|
26239
|
+
)
|
|
26240
|
+
] }),
|
|
26241
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
26242
|
+
/* @__PURE__ */ jsx("label", { htmlFor: "timestamp-end", className: "block text-xs font-medium text-gray-600 mb-1", children: "End Time" }),
|
|
26243
|
+
/* @__PURE__ */ jsx(
|
|
26244
|
+
"input",
|
|
26245
|
+
{
|
|
26246
|
+
id: "timestamp-end",
|
|
26247
|
+
type: "time",
|
|
26248
|
+
value: timestampEnd,
|
|
26249
|
+
onChange: (e) => setTimestampEnd(e.target.value),
|
|
26250
|
+
className: "w-full px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
|
|
26251
|
+
}
|
|
26252
|
+
)
|
|
26253
|
+
] }),
|
|
26254
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-between pt-2", children: [
|
|
26255
|
+
/* @__PURE__ */ jsx(
|
|
26256
|
+
"button",
|
|
26257
|
+
{
|
|
26258
|
+
onClick: () => {
|
|
26259
|
+
setTimestampStart("");
|
|
26260
|
+
setTimestampEnd("");
|
|
26261
|
+
setShowTimestampFilter(false);
|
|
26262
|
+
},
|
|
26263
|
+
className: "px-3 py-1.5 text-sm text-gray-600 hover:text-gray-800 transition-colors",
|
|
26264
|
+
children: "Clear"
|
|
26265
|
+
}
|
|
26266
|
+
),
|
|
26267
|
+
/* @__PURE__ */ jsx(
|
|
26268
|
+
"button",
|
|
26269
|
+
{
|
|
26270
|
+
onClick: () => {
|
|
26271
|
+
setShowTimestampFilter(false);
|
|
26272
|
+
fetchClips();
|
|
26273
|
+
},
|
|
26274
|
+
className: "px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 transition-colors",
|
|
26275
|
+
children: "Apply Filter"
|
|
26276
|
+
}
|
|
26277
|
+
)
|
|
26278
|
+
] })
|
|
26279
|
+
] })
|
|
26280
|
+
] })
|
|
26281
|
+
] }),
|
|
26094
26282
|
/* @__PURE__ */ jsx(
|
|
26095
26283
|
"button",
|
|
26096
26284
|
{
|
|
@@ -26114,6 +26302,29 @@ var BottlenecksContent = ({
|
|
|
26114
26302
|
)
|
|
26115
26303
|
] })
|
|
26116
26304
|
] }) }),
|
|
26305
|
+
(timestampStart || timestampEnd) && /* @__PURE__ */ jsxs("div", { className: "px-4 py-2 bg-blue-50 border-b border-blue-100 flex items-center justify-between", children: [
|
|
26306
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 text-sm text-blue-700", children: [
|
|
26307
|
+
/* @__PURE__ */ jsx(Clock, { className: "h-4 w-4" }),
|
|
26308
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
26309
|
+
"Filtered by time: ",
|
|
26310
|
+
timestampStart ? formatTimeOnly(timestampStart) : "Any",
|
|
26311
|
+
" - ",
|
|
26312
|
+
timestampEnd ? formatTimeOnly(timestampEnd) : "Any"
|
|
26313
|
+
] })
|
|
26314
|
+
] }),
|
|
26315
|
+
/* @__PURE__ */ jsx(
|
|
26316
|
+
"button",
|
|
26317
|
+
{
|
|
26318
|
+
onClick: () => {
|
|
26319
|
+
setTimestampStart("");
|
|
26320
|
+
setTimestampEnd("");
|
|
26321
|
+
fetchClips();
|
|
26322
|
+
},
|
|
26323
|
+
className: "text-sm text-blue-600 hover:text-blue-800 transition-colors",
|
|
26324
|
+
children: "Clear filter"
|
|
26325
|
+
}
|
|
26326
|
+
)
|
|
26327
|
+
] }),
|
|
26117
26328
|
isLoading && allVideos.length > 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsx(LoadingSpinner2, { size: "md", message: "Loading clips..." }) }) : allVideos.length === 0 ? /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-[calc(100%-4rem)]", children: /* @__PURE__ */ jsxs("div", { className: "text-center p-8", children: [
|
|
26118
26329
|
/* @__PURE__ */ jsx("svg", { className: "w-16 h-16 text-gray-300 mx-auto mb-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" }) }),
|
|
26119
26330
|
/* @__PURE__ */ jsx("h3", { className: "text-xl font-medium text-gray-700 mb-2", children: "No Clips Found" }),
|
|
@@ -26173,6 +26384,7 @@ var BottlenecksContent = ({
|
|
|
26173
26384
|
/* @__PURE__ */ jsx("span", { className: "opacity-80 hidden sm:inline", children: currentVideo.description })
|
|
26174
26385
|
] }) })
|
|
26175
26386
|
),
|
|
26387
|
+
currentVideo.creation_timestamp && /* @__PURE__ */ jsx("div", { className: "absolute bottom-3 left-3 z-10 bg-black/50 backdrop-blur-sm px-2 py-1 rounded text-white shadow-sm text-xs", children: /* @__PURE__ */ jsx("span", { className: "opacity-80", children: formatTimestamp(currentVideo.creation_timestamp) }) }),
|
|
26176
26388
|
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 p-3 bg-gradient-to-t from-black/70 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-white", children: [
|
|
26177
26389
|
/* @__PURE__ */ jsx(
|
|
26178
26390
|
"button",
|
|
@@ -28093,9 +28305,9 @@ var SideNavBar = memo(({
|
|
|
28093
28305
|
}
|
|
28094
28306
|
)
|
|
28095
28307
|
] }),
|
|
28096
|
-
/* @__PURE__ */ jsxs("div", { className: "mt-auto", children: [
|
|
28097
|
-
/* @__PURE__ */ jsx("div", { className: "w-10 h-px bg-gray-200 my-
|
|
28098
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
28308
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-auto mb-2", children: [
|
|
28309
|
+
/* @__PURE__ */ jsx("div", { className: "w-10 h-px bg-gray-200 my-3" }),
|
|
28310
|
+
/* @__PURE__ */ jsx("div", { className: "w-full", children: /* @__PURE__ */ jsx(
|
|
28099
28311
|
"button",
|
|
28100
28312
|
{
|
|
28101
28313
|
onClick: handleProfileClick,
|
|
@@ -28677,7 +28889,7 @@ var ThreadSidebar = ({
|
|
|
28677
28889
|
if (error) {
|
|
28678
28890
|
return /* @__PURE__ */ jsx("div", { className: `p-4 text-red-600 text-sm ${className}`, children: "Failed to load conversations" });
|
|
28679
28891
|
}
|
|
28680
|
-
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col h-
|
|
28892
|
+
return /* @__PURE__ */ jsxs("div", { className: `flex flex-col h-screen bg-gray-50 border-r border-gray-200 ${className}`, children: [
|
|
28681
28893
|
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0 p-4 border-b border-gray-200", children: /* @__PURE__ */ jsxs(
|
|
28682
28894
|
"button",
|
|
28683
28895
|
{
|
|
@@ -28689,7 +28901,7 @@ var ThreadSidebar = ({
|
|
|
28689
28901
|
]
|
|
28690
28902
|
}
|
|
28691
28903
|
) }),
|
|
28692
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: isLoading ? /* @__PURE__ */ jsx("div", { className: "flex justify-center p-8", children: /* @__PURE__ */ jsx(LoadingSpinner_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(
|
|
28904
|
+
/* @__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(LoadingSpinner_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(
|
|
28693
28905
|
"div",
|
|
28694
28906
|
{
|
|
28695
28907
|
onClick: () => onSelectThread(thread.id),
|
|
@@ -28721,6 +28933,23 @@ var ThreadSidebar = ({
|
|
|
28721
28933
|
] });
|
|
28722
28934
|
};
|
|
28723
28935
|
var axelProfilePng = "/axel-profile.png";
|
|
28936
|
+
var ProfilePicture = React46__default.memo(({ alt = "Axel", className = "w-12 h-12" }) => {
|
|
28937
|
+
return /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: `${className} rounded-xl overflow-hidden shadow-sm`, children: /* @__PURE__ */ jsx(
|
|
28938
|
+
"img",
|
|
28939
|
+
{
|
|
28940
|
+
src: axelProfilePng,
|
|
28941
|
+
alt,
|
|
28942
|
+
className: "w-full h-full object-cover",
|
|
28943
|
+
loading: "eager",
|
|
28944
|
+
decoding: "async"
|
|
28945
|
+
}
|
|
28946
|
+
) }) });
|
|
28947
|
+
});
|
|
28948
|
+
ProfilePicture.displayName = "ProfilePicture";
|
|
28949
|
+
var preloadImage = (src) => {
|
|
28950
|
+
const img = new Image();
|
|
28951
|
+
img.src = src;
|
|
28952
|
+
};
|
|
28724
28953
|
var AIAgentView = () => {
|
|
28725
28954
|
const { navigate, pathname } = useNavigation();
|
|
28726
28955
|
const config = useDashboardConfig();
|
|
@@ -28732,16 +28961,92 @@ var AIAgentView = () => {
|
|
|
28732
28961
|
const [lastError, setLastError] = useState(null);
|
|
28733
28962
|
const [copiedMessageId, setCopiedMessageId] = useState(null);
|
|
28734
28963
|
const [activeThreadId, setActiveThreadId] = useState(void 0);
|
|
28735
|
-
const [isSidebarOpen, setIsSidebarOpen] = useState(
|
|
28964
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(false);
|
|
28736
28965
|
const [streamingStates, setStreamingStates] = useState(/* @__PURE__ */ new Map());
|
|
28737
28966
|
const [userId, setUserId] = useState(null);
|
|
28738
28967
|
const [pendingThreadId, setPendingThreadId] = useState(null);
|
|
28968
|
+
const [isTransitioning, setIsTransitioning] = useState(false);
|
|
28969
|
+
const [typedText, setTypedText] = useState("");
|
|
28970
|
+
const [newChatCount, setNewChatCount] = useState(0);
|
|
28971
|
+
const [hasStartedTyping, setHasStartedTyping] = useState(false);
|
|
28972
|
+
const [typingStartTime, setTypingStartTime] = useState(null);
|
|
28973
|
+
const [lastTypingTime, setLastTypingTime] = useState(null);
|
|
28974
|
+
const [characterCount, setCharacterCount] = useState(0);
|
|
28975
|
+
const typingTimeoutRef = useRef(null);
|
|
28739
28976
|
const isThreadLoading = (threadId) => {
|
|
28740
28977
|
return threadId ? loadingThreads.has(threadId) : false;
|
|
28741
28978
|
};
|
|
28742
28979
|
const getStreamingState = (threadId) => {
|
|
28743
28980
|
return threadId ? streamingStates.get(threadId) || { message: "", reasoning: "" } : { message: "", reasoning: "" };
|
|
28744
28981
|
};
|
|
28982
|
+
const trackTypingStart = () => {
|
|
28983
|
+
if (!hasStartedTyping) {
|
|
28984
|
+
const now2 = Date.now();
|
|
28985
|
+
setHasStartedTyping(true);
|
|
28986
|
+
setTypingStartTime(now2);
|
|
28987
|
+
setLastTypingTime(now2);
|
|
28988
|
+
trackCoreEvent("AI Agent Input Started", {
|
|
28989
|
+
line_id: lineId,
|
|
28990
|
+
company_id: companyId,
|
|
28991
|
+
shift_id: shiftId,
|
|
28992
|
+
active_thread_id: activeThreadId,
|
|
28993
|
+
has_existing_messages: messages.length > 0,
|
|
28994
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
28995
|
+
});
|
|
28996
|
+
}
|
|
28997
|
+
};
|
|
28998
|
+
const trackTypingProgress = (newValue) => {
|
|
28999
|
+
const now2 = Date.now();
|
|
29000
|
+
setLastTypingTime(now2);
|
|
29001
|
+
setCharacterCount(newValue.length);
|
|
29002
|
+
if (typingTimeoutRef.current) {
|
|
29003
|
+
clearTimeout(typingTimeoutRef.current);
|
|
29004
|
+
}
|
|
29005
|
+
typingTimeoutRef.current = setTimeout(() => {
|
|
29006
|
+
if (hasStartedTyping && typingStartTime && newValue.length > 0) {
|
|
29007
|
+
const typingDuration = now2 - typingStartTime;
|
|
29008
|
+
trackCoreEvent("AI Agent Input Typing Progress", {
|
|
29009
|
+
line_id: lineId,
|
|
29010
|
+
company_id: companyId,
|
|
29011
|
+
shift_id: shiftId,
|
|
29012
|
+
active_thread_id: activeThreadId,
|
|
29013
|
+
character_count: newValue.length,
|
|
29014
|
+
typing_duration_ms: typingDuration,
|
|
29015
|
+
has_existing_messages: messages.length > 0,
|
|
29016
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
29017
|
+
});
|
|
29018
|
+
}
|
|
29019
|
+
}, 2e3);
|
|
29020
|
+
};
|
|
29021
|
+
const trackMessageSent = (messageContent) => {
|
|
29022
|
+
if (hasStartedTyping && typingStartTime) {
|
|
29023
|
+
const now2 = Date.now();
|
|
29024
|
+
const totalTypingDuration = now2 - typingStartTime;
|
|
29025
|
+
trackCoreEvent("AI Agent Message Sent", {
|
|
29026
|
+
line_id: lineId,
|
|
29027
|
+
company_id: companyId,
|
|
29028
|
+
shift_id: shiftId,
|
|
29029
|
+
active_thread_id: activeThreadId,
|
|
29030
|
+
message_length: messageContent.length,
|
|
29031
|
+
character_count: messageContent.length,
|
|
29032
|
+
typing_duration_ms: totalTypingDuration,
|
|
29033
|
+
has_existing_messages: messages.length > 0,
|
|
29034
|
+
is_new_conversation: !activeThreadId,
|
|
29035
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
29036
|
+
});
|
|
29037
|
+
}
|
|
29038
|
+
resetTypingState();
|
|
29039
|
+
};
|
|
29040
|
+
const resetTypingState = () => {
|
|
29041
|
+
setHasStartedTyping(false);
|
|
29042
|
+
setTypingStartTime(null);
|
|
29043
|
+
setLastTypingTime(null);
|
|
29044
|
+
setCharacterCount(0);
|
|
29045
|
+
if (typingTimeoutRef.current) {
|
|
29046
|
+
clearTimeout(typingTimeoutRef.current);
|
|
29047
|
+
typingTimeoutRef.current = null;
|
|
29048
|
+
}
|
|
29049
|
+
};
|
|
28745
29050
|
const textareaRef = useRef(null);
|
|
28746
29051
|
const messagesEndRef = useRef(null);
|
|
28747
29052
|
const containerRef = useRef(null);
|
|
@@ -28763,6 +29068,41 @@ var AIAgentView = () => {
|
|
|
28763
29068
|
const lineId = getLineIdFromPath();
|
|
28764
29069
|
const { shiftId } = getCurrentShift(dateTimeConfig.defaultTimezone || "Asia/Kolkata", shiftConfig);
|
|
28765
29070
|
const companyId = entityConfig.companyId || "default-company-id";
|
|
29071
|
+
const ACTIVE_THREAD_STORAGE_KEY = `ai-agent-active-thread-${lineId}`;
|
|
29072
|
+
useLayoutEffect(() => {
|
|
29073
|
+
const savedThreadId = localStorage.getItem(ACTIVE_THREAD_STORAGE_KEY);
|
|
29074
|
+
if (savedThreadId && savedThreadId !== "undefined") {
|
|
29075
|
+
setActiveThreadId(savedThreadId);
|
|
29076
|
+
}
|
|
29077
|
+
}, [ACTIVE_THREAD_STORAGE_KEY]);
|
|
29078
|
+
useEffect(() => {
|
|
29079
|
+
if (activeThreadId) {
|
|
29080
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
29081
|
+
} else {
|
|
29082
|
+
localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
|
|
29083
|
+
}
|
|
29084
|
+
}, [activeThreadId, ACTIVE_THREAD_STORAGE_KEY]);
|
|
29085
|
+
useEffect(() => {
|
|
29086
|
+
const handleVisibilityChange = () => {
|
|
29087
|
+
if (document.visibilityState === "hidden" && activeThreadId) {
|
|
29088
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
29089
|
+
}
|
|
29090
|
+
};
|
|
29091
|
+
const handleBeforeUnload = () => {
|
|
29092
|
+
if (activeThreadId) {
|
|
29093
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
29094
|
+
}
|
|
29095
|
+
};
|
|
29096
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
29097
|
+
window.addEventListener("beforeunload", handleBeforeUnload);
|
|
29098
|
+
return () => {
|
|
29099
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
29100
|
+
window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
29101
|
+
if (activeThreadId) {
|
|
29102
|
+
localStorage.setItem(ACTIVE_THREAD_STORAGE_KEY, activeThreadId);
|
|
29103
|
+
}
|
|
29104
|
+
};
|
|
29105
|
+
}, [activeThreadId, ACTIVE_THREAD_STORAGE_KEY]);
|
|
28766
29106
|
useEffect(() => {
|
|
28767
29107
|
if (textareaRef.current) {
|
|
28768
29108
|
textareaRef.current.style.height = "auto";
|
|
@@ -28777,6 +29117,27 @@ var AIAgentView = () => {
|
|
|
28777
29117
|
setTimeout(scrollToBottom, 100);
|
|
28778
29118
|
}
|
|
28779
29119
|
}, [activeThreadId]);
|
|
29120
|
+
useEffect(() => {
|
|
29121
|
+
if (messages.length === 0 && !isTransitioning) {
|
|
29122
|
+
const fullText = "Hi, I'm Axel - Your AI Supervisor";
|
|
29123
|
+
let index = 0;
|
|
29124
|
+
setTypedText("");
|
|
29125
|
+
const typeInterval = setInterval(() => {
|
|
29126
|
+
if (index < fullText.length) {
|
|
29127
|
+
setTypedText(fullText.substring(0, index + 1));
|
|
29128
|
+
index++;
|
|
29129
|
+
} else {
|
|
29130
|
+
clearInterval(typeInterval);
|
|
29131
|
+
}
|
|
29132
|
+
}, 50);
|
|
29133
|
+
return () => clearInterval(typeInterval);
|
|
29134
|
+
}
|
|
29135
|
+
}, [messages.length, isTransitioning]);
|
|
29136
|
+
useEffect(() => {
|
|
29137
|
+
if (isSidebarOpen) {
|
|
29138
|
+
setNewChatCount(0);
|
|
29139
|
+
}
|
|
29140
|
+
}, [isSidebarOpen]);
|
|
28780
29141
|
const copyToClipboard = async (text, messageId) => {
|
|
28781
29142
|
try {
|
|
28782
29143
|
await navigator.clipboard.writeText(text);
|
|
@@ -28791,8 +29152,21 @@ var AIAgentView = () => {
|
|
|
28791
29152
|
setMessages([]);
|
|
28792
29153
|
setInputValue("");
|
|
28793
29154
|
setPendingThreadId(null);
|
|
29155
|
+
setTypedText("");
|
|
29156
|
+
resetTypingState();
|
|
29157
|
+
localStorage.removeItem(ACTIVE_THREAD_STORAGE_KEY);
|
|
28794
29158
|
textareaRef.current?.focus();
|
|
28795
29159
|
};
|
|
29160
|
+
useEffect(() => {
|
|
29161
|
+
preloadImage(axelProfilePng);
|
|
29162
|
+
}, []);
|
|
29163
|
+
useEffect(() => {
|
|
29164
|
+
return () => {
|
|
29165
|
+
if (typingTimeoutRef.current) {
|
|
29166
|
+
clearTimeout(typingTimeoutRef.current);
|
|
29167
|
+
}
|
|
29168
|
+
};
|
|
29169
|
+
}, []);
|
|
28796
29170
|
useEffect(() => {
|
|
28797
29171
|
const checkAuth = async () => {
|
|
28798
29172
|
const supabase2 = _getSupabaseInstance();
|
|
@@ -28823,6 +29197,13 @@ var AIAgentView = () => {
|
|
|
28823
29197
|
let currentThreadId = activeThreadId || `temp-${Date.now()}`;
|
|
28824
29198
|
if (isThreadLoading(currentThreadId)) return;
|
|
28825
29199
|
const userMessage = inputValue.trim();
|
|
29200
|
+
trackMessageSent(userMessage);
|
|
29201
|
+
if (displayMessages.length === 0) {
|
|
29202
|
+
setIsTransitioning(true);
|
|
29203
|
+
setTimeout(() => {
|
|
29204
|
+
setIsTransitioning(false);
|
|
29205
|
+
}, 800);
|
|
29206
|
+
}
|
|
28826
29207
|
setInputValue("");
|
|
28827
29208
|
setLoadingThreads((prev) => new Set(prev).add(currentThreadId));
|
|
28828
29209
|
setLastError(null);
|
|
@@ -28866,6 +29247,9 @@ var AIAgentView = () => {
|
|
|
28866
29247
|
currentThreadId = threadId;
|
|
28867
29248
|
setActiveThreadId(threadId);
|
|
28868
29249
|
setPendingThreadId(null);
|
|
29250
|
+
if (!isSidebarOpen) {
|
|
29251
|
+
setNewChatCount((prev) => prev + 1);
|
|
29252
|
+
}
|
|
28869
29253
|
setLoadingThreads((prev) => {
|
|
28870
29254
|
const newSet = new Set(prev);
|
|
28871
29255
|
if (newSet.has(oldThreadId)) {
|
|
@@ -28964,7 +29348,9 @@ var AIAgentView = () => {
|
|
|
28964
29348
|
const handleKeyDown = (e) => {
|
|
28965
29349
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
28966
29350
|
e.preventDefault();
|
|
28967
|
-
|
|
29351
|
+
if (!isCurrentThreadLoading) {
|
|
29352
|
+
handleSubmit(e);
|
|
29353
|
+
}
|
|
28968
29354
|
}
|
|
28969
29355
|
};
|
|
28970
29356
|
const formatMessage = (content) => {
|
|
@@ -28973,7 +29359,81 @@ var AIAgentView = () => {
|
|
|
28973
29359
|
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>');
|
|
28974
29360
|
return text;
|
|
28975
29361
|
};
|
|
28976
|
-
const
|
|
29362
|
+
const parseTableFromText = (lines2, startIndex) => {
|
|
29363
|
+
const tableLines = [];
|
|
29364
|
+
let i = startIndex;
|
|
29365
|
+
while (i < lines2.length) {
|
|
29366
|
+
const line = lines2[i].trim();
|
|
29367
|
+
if (!line) {
|
|
29368
|
+
i++;
|
|
29369
|
+
break;
|
|
29370
|
+
}
|
|
29371
|
+
if (line.includes("|") || line.match(/^[-|=\s]+$/)) {
|
|
29372
|
+
tableLines.push(line);
|
|
29373
|
+
i++;
|
|
29374
|
+
} else {
|
|
29375
|
+
break;
|
|
29376
|
+
}
|
|
29377
|
+
}
|
|
29378
|
+
if (tableLines.length === 0) return { html: "", endIndex: startIndex };
|
|
29379
|
+
const dataLines = tableLines.filter((line) => !line.match(/^[-|=\s]+$/));
|
|
29380
|
+
if (dataLines.length === 0) return { html: "", endIndex: i };
|
|
29381
|
+
let headerRow = [];
|
|
29382
|
+
let dataRows = [];
|
|
29383
|
+
const firstLine = dataLines[0];
|
|
29384
|
+
if (firstLine.includes("|")) {
|
|
29385
|
+
const cells = firstLine.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
29386
|
+
if (cells.length >= 2) {
|
|
29387
|
+
headerRow = cells;
|
|
29388
|
+
for (let j = 1; j < dataLines.length; j++) {
|
|
29389
|
+
const row = dataLines[j];
|
|
29390
|
+
if (row.includes("|")) {
|
|
29391
|
+
const rowCells = row.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
29392
|
+
while (rowCells.length < headerRow.length) rowCells.push("");
|
|
29393
|
+
if (rowCells.length > headerRow.length) rowCells.splice(headerRow.length);
|
|
29394
|
+
dataRows.push(rowCells);
|
|
29395
|
+
}
|
|
29396
|
+
}
|
|
29397
|
+
}
|
|
29398
|
+
}
|
|
29399
|
+
if (headerRow.length === 0) {
|
|
29400
|
+
for (const line of dataLines) {
|
|
29401
|
+
if (line.includes("|")) {
|
|
29402
|
+
const rowCells = line.split("|").map((cell) => cell.trim()).filter((cell) => cell.length > 0);
|
|
29403
|
+
if (rowCells.length >= 2) {
|
|
29404
|
+
dataRows.push(rowCells);
|
|
29405
|
+
}
|
|
29406
|
+
}
|
|
29407
|
+
}
|
|
29408
|
+
if (dataRows.length > 0 && dataRows[0].length > 0) {
|
|
29409
|
+
headerRow = dataRows[0].map((_, index) => `Column ${index + 1}`);
|
|
29410
|
+
}
|
|
29411
|
+
}
|
|
29412
|
+
if (headerRow.length > 0 && dataRows.length > 0) {
|
|
29413
|
+
let tableHtml = '<div class="overflow-x-auto my-4"><table class="min-w-full border-collapse border border-gray-300 rounded-lg shadow-sm">';
|
|
29414
|
+
tableHtml += '<thead class="bg-gray-50">';
|
|
29415
|
+
tableHtml += "<tr>";
|
|
29416
|
+
headerRow.forEach((header) => {
|
|
29417
|
+
tableHtml += `<th class="border border-gray-300 px-4 py-2 text-left font-semibold text-gray-900">${processInlineFormatting(header)}</th>`;
|
|
29418
|
+
});
|
|
29419
|
+
tableHtml += "</tr>";
|
|
29420
|
+
tableHtml += "</thead>";
|
|
29421
|
+
tableHtml += '<tbody class="bg-white">';
|
|
29422
|
+
dataRows.forEach((row, rowIndex) => {
|
|
29423
|
+
tableHtml += `<tr class="${rowIndex % 2 === 0 ? "bg-white" : "bg-gray-50"}">`;
|
|
29424
|
+
row.forEach((cell) => {
|
|
29425
|
+
tableHtml += `<td class="border border-gray-300 px-4 py-2 text-gray-800">${processInlineFormatting(cell)}</td>`;
|
|
29426
|
+
});
|
|
29427
|
+
tableHtml += "</tr>";
|
|
29428
|
+
});
|
|
29429
|
+
tableHtml += "</tbody>";
|
|
29430
|
+
tableHtml += "</table></div>";
|
|
29431
|
+
return { html: tableHtml, endIndex: i };
|
|
29432
|
+
}
|
|
29433
|
+
return { html: "", endIndex: startIndex };
|
|
29434
|
+
};
|
|
29435
|
+
const processedContent = content;
|
|
29436
|
+
const lines = processedContent.split("\n");
|
|
28977
29437
|
const formattedLines = [];
|
|
28978
29438
|
let inList = false;
|
|
28979
29439
|
for (let i = 0; i < lines.length; i++) {
|
|
@@ -28987,6 +29447,18 @@ var AIAgentView = () => {
|
|
|
28987
29447
|
formattedLines.push("<br/>");
|
|
28988
29448
|
continue;
|
|
28989
29449
|
}
|
|
29450
|
+
if (trimmedLine.includes("|") && (trimmedLine.match(/\|/g) || []).length >= 1) {
|
|
29451
|
+
if (inList) {
|
|
29452
|
+
formattedLines.push("</ul>");
|
|
29453
|
+
inList = false;
|
|
29454
|
+
}
|
|
29455
|
+
const tableResult = parseTableFromText(lines, i);
|
|
29456
|
+
if (tableResult.html) {
|
|
29457
|
+
formattedLines.push(tableResult.html);
|
|
29458
|
+
i = tableResult.endIndex - 1;
|
|
29459
|
+
continue;
|
|
29460
|
+
}
|
|
29461
|
+
}
|
|
28990
29462
|
if (trimmedLine.startsWith("###")) {
|
|
28991
29463
|
if (inList) {
|
|
28992
29464
|
formattedLines.push("</ul>");
|
|
@@ -29070,100 +29542,200 @@ var AIAgentView = () => {
|
|
|
29070
29542
|
position: messages.length
|
|
29071
29543
|
});
|
|
29072
29544
|
}
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
|
|
29545
|
+
const renderAssistantContent = (content) => {
|
|
29546
|
+
return /* @__PURE__ */ jsx(
|
|
29547
|
+
"div",
|
|
29076
29548
|
{
|
|
29077
|
-
|
|
29078
|
-
|
|
29079
|
-
onNewThread: handleNewThread,
|
|
29080
|
-
className: "h-full"
|
|
29549
|
+
className: "formatted-content",
|
|
29550
|
+
dangerouslySetInnerHTML: { __html: formatMessage(content) }
|
|
29081
29551
|
}
|
|
29082
|
-
)
|
|
29083
|
-
|
|
29084
|
-
|
|
29085
|
-
|
|
29086
|
-
|
|
29087
|
-
|
|
29088
|
-
{
|
|
29089
|
-
|
|
29090
|
-
|
|
29091
|
-
"aria-label": "Toggle sidebar",
|
|
29092
|
-
children: isSidebarOpen ? /* @__PURE__ */ jsx(X, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(Menu, { className: "w-5 h-5" })
|
|
29552
|
+
);
|
|
29553
|
+
};
|
|
29554
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex h-screen bg-white", children: [
|
|
29555
|
+
/* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: {
|
|
29556
|
+
__html: `
|
|
29557
|
+
@keyframes slideDown {
|
|
29558
|
+
0% {
|
|
29559
|
+
transform: translateY(-40vh);
|
|
29560
|
+
opacity: 1;
|
|
29093
29561
|
}
|
|
29094
|
-
|
|
29095
|
-
|
|
29096
|
-
|
|
29097
|
-
{
|
|
29098
|
-
onClick: () => navigate("/"),
|
|
29099
|
-
className: "flex items-center gap-2 text-gray-600 hover:text-gray-900 transition-colors",
|
|
29100
|
-
"aria-label": "Go back",
|
|
29101
|
-
children: [
|
|
29102
|
-
/* @__PURE__ */ jsx(ArrowLeft, { className: "w-5 h-5" }),
|
|
29103
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Back" })
|
|
29104
|
-
]
|
|
29562
|
+
100% {
|
|
29563
|
+
transform: translateY(0);
|
|
29564
|
+
opacity: 1;
|
|
29105
29565
|
}
|
|
29106
|
-
|
|
29107
|
-
|
|
29566
|
+
}
|
|
29567
|
+
`
|
|
29568
|
+
} }),
|
|
29569
|
+
/* @__PURE__ */ jsxs("div", { className: `flex-1 flex flex-col h-screen transition-all duration-300 ${isSidebarOpen ? "mr-80" : "mr-0"}`, children: [
|
|
29570
|
+
/* @__PURE__ */ jsx("header", { className: "flex-shrink-0 bg-white border-b border-gray-200 sticky top-0 z-10", children: /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
29571
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: /* @__PURE__ */ jsxs(
|
|
29572
|
+
"button",
|
|
29573
|
+
{
|
|
29574
|
+
onClick: () => navigate("/"),
|
|
29575
|
+
className: "flex items-center gap-2 text-gray-600 hover:text-gray-900 transition-colors",
|
|
29576
|
+
"aria-label": "Go back",
|
|
29577
|
+
children: [
|
|
29578
|
+
/* @__PURE__ */ jsx(ArrowLeft, { className: "w-5 h-5" }),
|
|
29579
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: "Back" })
|
|
29580
|
+
]
|
|
29581
|
+
}
|
|
29582
|
+
) }),
|
|
29108
29583
|
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
29109
29584
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
29110
|
-
/* @__PURE__ */ jsx("h1", { className: "text-xl sm:text-2xl md:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: "
|
|
29585
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl sm:text-2xl md:text-3xl font-bold text-gray-800 tracking-tight leading-none", children: "Chat with Axel" }),
|
|
29111
29586
|
/* @__PURE__ */ jsx("div", { className: "h-2 w-2 rounded-full bg-blue-500 animate-pulse ring-2 ring-blue-500/30" })
|
|
29112
29587
|
] }),
|
|
29113
29588
|
/* @__PURE__ */ jsx("div", { className: "flex items-center mt-1", children: /* @__PURE__ */ jsx("span", { className: "text-xs font-medium text-gray-500", children: /* @__PURE__ */ jsx(ISTTimer_default, {}) }) })
|
|
29114
29589
|
] }),
|
|
29115
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
29590
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsxs(
|
|
29591
|
+
"button",
|
|
29592
|
+
{
|
|
29593
|
+
onClick: () => setIsSidebarOpen(!isSidebarOpen),
|
|
29594
|
+
className: "relative p-2 hover:bg-gray-100 rounded-lg transition-colors",
|
|
29595
|
+
"aria-label": "Toggle sidebar",
|
|
29596
|
+
children: [
|
|
29597
|
+
isSidebarOpen ? /* @__PURE__ */ jsx(X, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(Menu, { className: "w-5 h-5" }),
|
|
29598
|
+
!isSidebarOpen && newChatCount > 0 && /* @__PURE__ */ jsx("div", { className: "absolute -top-1 -right-1 bg-red-500 text-white text-xs rounded-full w-5 h-5 flex items-center justify-center font-medium", children: newChatCount })
|
|
29599
|
+
]
|
|
29600
|
+
}
|
|
29601
|
+
) })
|
|
29116
29602
|
] }) }) }),
|
|
29117
29603
|
/* @__PURE__ */ jsx(
|
|
29118
29604
|
"main",
|
|
29119
29605
|
{
|
|
29120
29606
|
ref: containerRef,
|
|
29121
|
-
className:
|
|
29122
|
-
children:
|
|
29123
|
-
|
|
29124
|
-
|
|
29125
|
-
|
|
29126
|
-
{
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
className: "
|
|
29130
|
-
}
|
|
29131
|
-
|
|
29132
|
-
/* @__PURE__ */ jsxs("div", { className: "
|
|
29133
|
-
/* @__PURE__ */ jsx("
|
|
29134
|
-
|
|
29607
|
+
className: `flex-1 bg-gray-50/50 min-h-0 ${displayMessages.length === 0 && !isTransitioning ? "flex items-center justify-center" : "overflow-y-auto"}`,
|
|
29608
|
+
children: !activeThreadId && displayMessages.length === 0 && !isTransitioning ? (
|
|
29609
|
+
/* Centered welcome and input for new chat */
|
|
29610
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full max-w-3xl mx-auto px-4 sm:px-6 flex flex-col items-center justify-center space-y-12 -mt-16", children: [
|
|
29611
|
+
/* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
29612
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center mb-8", children: /* @__PURE__ */ jsx(ProfilePicture, { alt: "Axel - AI Manufacturing Expert", className: "w-24 h-24" }) }),
|
|
29613
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-3xl font-semibold text-gray-900", children: [
|
|
29614
|
+
typedText,
|
|
29615
|
+
typedText.length < "Hi, I'm Axel - Your AI Supervisor".length && /* @__PURE__ */ jsx("span", { className: "animate-pulse", children: "|" })
|
|
29616
|
+
] })
|
|
29617
|
+
] }),
|
|
29618
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full max-w-2xl", children: [
|
|
29619
|
+
activeThreadId && messages.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxs(
|
|
29620
|
+
"button",
|
|
29621
|
+
{
|
|
29622
|
+
onClick: handleNewThread,
|
|
29623
|
+
className: "inline-flex items-center gap-2 px-3 py-1.5 text-xs font-medium text-gray-500 hover:text-gray-700 hover:bg-gray-100 rounded-lg transition-colors",
|
|
29624
|
+
children: [
|
|
29625
|
+
/* @__PURE__ */ jsx(RefreshCw, { className: "w-3.5 h-3.5" }),
|
|
29626
|
+
"New conversation"
|
|
29627
|
+
]
|
|
29628
|
+
}
|
|
29629
|
+
) }),
|
|
29630
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
|
|
29631
|
+
/* @__PURE__ */ jsx("div", { className: "relative bg-white 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", children: /* @__PURE__ */ jsxs("div", { className: "flex-1 relative", children: [
|
|
29632
|
+
/* @__PURE__ */ jsx(
|
|
29633
|
+
"textarea",
|
|
29634
|
+
{
|
|
29635
|
+
ref: textareaRef,
|
|
29636
|
+
value: inputValue,
|
|
29637
|
+
onChange: (e) => {
|
|
29638
|
+
const newValue = e.target.value;
|
|
29639
|
+
setInputValue(newValue);
|
|
29640
|
+
if (newValue.length > 0 && !hasStartedTyping) {
|
|
29641
|
+
trackTypingStart();
|
|
29642
|
+
}
|
|
29643
|
+
if (newValue.length > 0) {
|
|
29644
|
+
trackTypingProgress(newValue);
|
|
29645
|
+
}
|
|
29646
|
+
if (newValue.length === 0) {
|
|
29647
|
+
resetTypingState();
|
|
29648
|
+
}
|
|
29649
|
+
},
|
|
29650
|
+
onKeyDown: handleKeyDown,
|
|
29651
|
+
onFocus: () => {
|
|
29652
|
+
trackCoreEvent("AI Agent Input Focused", {
|
|
29653
|
+
line_id: lineId,
|
|
29654
|
+
company_id: companyId,
|
|
29655
|
+
shift_id: shiftId,
|
|
29656
|
+
active_thread_id: activeThreadId,
|
|
29657
|
+
has_existing_messages: messages.length > 0,
|
|
29658
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
29659
|
+
});
|
|
29660
|
+
},
|
|
29661
|
+
placeholder: "Ask me about production optimization, quality metrics, or any manufacturing challenge...",
|
|
29662
|
+
className: "w-full resize-none bg-transparent px-2 py-2 pr-12 focus:outline-none placeholder-gray-500 text-gray-900 text-sm leading-relaxed",
|
|
29663
|
+
rows: 1,
|
|
29664
|
+
style: { minHeight: "24px", maxHeight: "120px" }
|
|
29665
|
+
}
|
|
29666
|
+
),
|
|
29667
|
+
/* @__PURE__ */ jsx("div", { className: "absolute right-2 bottom-2 flex items-center gap-2", children: /* @__PURE__ */ jsx(
|
|
29668
|
+
"button",
|
|
29669
|
+
{
|
|
29670
|
+
type: "submit",
|
|
29671
|
+
disabled: !inputValue.trim() || isCurrentThreadLoading,
|
|
29672
|
+
className: "inline-flex items-center justify-center w-8 h-8 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",
|
|
29673
|
+
children: /* @__PURE__ */ jsx(Send, { className: "w-4 h-4" })
|
|
29674
|
+
}
|
|
29675
|
+
) })
|
|
29676
|
+
] }) }) }),
|
|
29677
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center mt-2 text-xs text-gray-400", children: [
|
|
29678
|
+
/* @__PURE__ */ jsx("span", { children: isCurrentThreadLoading ? "You can type your next message while Axel responds" : "Press Enter to send \u2022 Shift+Enter for new line" }),
|
|
29679
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 ml-4", children: [
|
|
29680
|
+
/* @__PURE__ */ jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isCurrentThreadLoading ? "bg-orange-500" : "bg-green-500"}` }),
|
|
29681
|
+
/* @__PURE__ */ jsx("span", { children: isCurrentThreadLoading ? "Responding..." : "Connected" })
|
|
29682
|
+
] })
|
|
29683
|
+
] })
|
|
29684
|
+
] })
|
|
29135
29685
|
] })
|
|
29136
|
-
] })
|
|
29137
|
-
|
|
29686
|
+
] })
|
|
29687
|
+
) : isTransitioning ? (
|
|
29688
|
+
/* Transition state - show user message first, then thinking */
|
|
29689
|
+
/* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 py-6 pb-32", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
29138
29690
|
displayMessages.map((message, index) => /* @__PURE__ */ jsxs(
|
|
29139
29691
|
"div",
|
|
29140
29692
|
{
|
|
29141
29693
|
className: `flex gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
|
|
29142
29694
|
children: [
|
|
29143
|
-
message.role === "assistant" && /* @__PURE__ */ jsx(
|
|
29144
|
-
|
|
29695
|
+
message.role === "assistant" && /* @__PURE__ */ jsx(ProfilePicture, {}),
|
|
29696
|
+
/* @__PURE__ */ jsx("div", { className: `max-w-none w-full group ${message.role === "user" ? "order-1" : ""}`, children: /* @__PURE__ */ jsx(
|
|
29697
|
+
"div",
|
|
29145
29698
|
{
|
|
29146
|
-
|
|
29147
|
-
|
|
29148
|
-
|
|
29699
|
+
className: `relative px-5 py-4 rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-600 text-white max-w-[85%] ml-auto" : "bg-white border border-gray-200/80 max-w-full"}`,
|
|
29700
|
+
children: /* @__PURE__ */ jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
|
|
29701
|
+
message.role === "assistant" ? renderAssistantContent(message.content) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
|
|
29702
|
+
message.id === -1 && /* @__PURE__ */ jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
|
|
29703
|
+
] })
|
|
29149
29704
|
}
|
|
29150
|
-
) })
|
|
29151
|
-
|
|
29705
|
+
) })
|
|
29706
|
+
]
|
|
29707
|
+
},
|
|
29708
|
+
message.id === -1 ? "streaming-message" : `${message.id}-${index}`
|
|
29709
|
+
)),
|
|
29710
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
29711
|
+
/* @__PURE__ */ jsx(ProfilePicture, {}),
|
|
29712
|
+
/* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
29713
|
+
/* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
|
|
29714
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
|
|
29715
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
|
|
29716
|
+
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
|
|
29717
|
+
] }),
|
|
29718
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 text-sm", children: "Axel is thinking..." })
|
|
29719
|
+
] }) })
|
|
29720
|
+
] })
|
|
29721
|
+
] }) })
|
|
29722
|
+
) : (
|
|
29723
|
+
/* Regular chat view with messages */
|
|
29724
|
+
/* @__PURE__ */ jsx("div", { className: "max-w-4xl mx-auto px-4 sm:px-6 py-6 pb-32", children: /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
29725
|
+
displayMessages.map((message, index) => /* @__PURE__ */ jsxs(
|
|
29726
|
+
"div",
|
|
29727
|
+
{
|
|
29728
|
+
className: `flex gap-4 ${message.role === "user" ? "justify-end" : "justify-start"}`,
|
|
29729
|
+
children: [
|
|
29730
|
+
message.role === "assistant" && /* @__PURE__ */ jsx(ProfilePicture, {}),
|
|
29731
|
+
/* @__PURE__ */ jsxs("div", { className: `max-w-none w-full group ${message.role === "user" ? "order-1" : ""}`, children: [
|
|
29152
29732
|
/* @__PURE__ */ jsxs(
|
|
29153
29733
|
"div",
|
|
29154
29734
|
{
|
|
29155
|
-
className: `relative px-5 py-4 rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-600 text-white" : "bg-white border border-gray-200/80"}`,
|
|
29735
|
+
className: `relative px-5 py-4 rounded-2xl shadow-sm ${message.role === "user" ? "bg-blue-600 text-white max-w-[85%] ml-auto" : "bg-white border border-gray-200/80 max-w-full"}`,
|
|
29156
29736
|
children: [
|
|
29157
29737
|
/* @__PURE__ */ jsxs("div", { className: `${message.role === "user" ? "text-white" : "text-gray-800"}`, children: [
|
|
29158
|
-
message.role === "assistant" ? /* @__PURE__ */ jsx(
|
|
29159
|
-
"div",
|
|
29160
|
-
{
|
|
29161
|
-
className: "formatted-content",
|
|
29162
|
-
dangerouslySetInnerHTML: {
|
|
29163
|
-
__html: formatMessage(message.content)
|
|
29164
|
-
}
|
|
29165
|
-
}
|
|
29166
|
-
) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
|
|
29738
|
+
message.role === "assistant" ? renderAssistantContent(message.content) : /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap leading-relaxed", children: message.content }),
|
|
29167
29739
|
message.id === -1 && /* @__PURE__ */ jsx("span", { className: "inline-block w-0.5 h-4 bg-gray-400 animate-pulse ml-0.5" })
|
|
29168
29740
|
] }),
|
|
29169
29741
|
message.role === "assistant" && message.id !== -1 && /* @__PURE__ */ jsx(
|
|
@@ -29189,15 +29761,14 @@ var AIAgentView = () => {
|
|
|
29189
29761
|
/* @__PURE__ */ jsx("span", { children: "Axel" })
|
|
29190
29762
|
] })
|
|
29191
29763
|
] })
|
|
29192
|
-
] })
|
|
29193
|
-
message.role === "user" && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx("div", { className: "w-10 h-10 bg-gray-700 text-white rounded-xl flex items-center justify-center text-sm font-semibold", children: entityConfig.companyId?.charAt(0).toUpperCase() || "U" }) })
|
|
29764
|
+
] })
|
|
29194
29765
|
]
|
|
29195
29766
|
},
|
|
29196
|
-
message.id === -1 ?
|
|
29767
|
+
message.id === -1 ? "streaming-message" : `${message.id}-${index}`
|
|
29197
29768
|
)),
|
|
29198
29769
|
lastError && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
29199
29770
|
/* @__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" }) }) }),
|
|
29200
|
-
/* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 px-5 py-4 rounded-2xl shadow-sm max-w-
|
|
29771
|
+
/* @__PURE__ */ jsxs("div", { className: "bg-red-50 border border-red-200 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: [
|
|
29201
29772
|
/* @__PURE__ */ jsx("p", { className: "text-red-800 text-sm", children: lastError }),
|
|
29202
29773
|
/* @__PURE__ */ jsx(
|
|
29203
29774
|
"button",
|
|
@@ -29210,29 +29781,22 @@ var AIAgentView = () => {
|
|
|
29210
29781
|
] })
|
|
29211
29782
|
] }),
|
|
29212
29783
|
isCurrentThreadLoading && !currentStreaming.message && /* @__PURE__ */ jsxs("div", { className: "flex gap-4 justify-start", children: [
|
|
29213
|
-
/* @__PURE__ */ jsx(
|
|
29214
|
-
|
|
29215
|
-
{
|
|
29216
|
-
src: axelProfilePng,
|
|
29217
|
-
alt: "Axel",
|
|
29218
|
-
className: "w-full h-full object-cover"
|
|
29219
|
-
}
|
|
29220
|
-
) }) }),
|
|
29221
|
-
/* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-[75%]", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
29784
|
+
/* @__PURE__ */ jsx(ProfilePicture, {}),
|
|
29785
|
+
/* @__PURE__ */ jsx("div", { className: "bg-white border border-gray-200/80 px-5 py-4 rounded-2xl shadow-sm max-w-full", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
29222
29786
|
/* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
|
|
29223
29787
|
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce" }),
|
|
29224
29788
|
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.1s" } }),
|
|
29225
29789
|
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-blue-500 rounded-full animate-bounce", style: { animationDelay: "0.2s" } })
|
|
29226
29790
|
] }),
|
|
29227
|
-
/* @__PURE__ */ jsx("span", { className: "text-gray-600 text-sm", children: "Axel is
|
|
29791
|
+
/* @__PURE__ */ jsx("span", { className: "text-gray-600 text-sm", children: "Axel is thinking..." })
|
|
29228
29792
|
] }) })
|
|
29229
29793
|
] }),
|
|
29230
29794
|
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
29231
|
-
] })
|
|
29232
|
-
|
|
29795
|
+
] }) })
|
|
29796
|
+
)
|
|
29233
29797
|
}
|
|
29234
29798
|
),
|
|
29235
|
-
/* @__PURE__ */ jsx("footer", { className: "
|
|
29799
|
+
(displayMessages.length > 0 || isTransitioning) && /* @__PURE__ */ jsx("footer", { className: "fixed bottom-0 left-0 right-0 bg-gradient-to-t from-gray-50/50 to-transparent pointer-events-none", children: /* @__PURE__ */ jsxs("div", { className: "max-w-4xl mx-auto p-4 sm:p-6 pointer-events-auto", children: [
|
|
29236
29800
|
activeThreadId && messages.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxs(
|
|
29237
29801
|
"button",
|
|
29238
29802
|
{
|
|
@@ -29244,48 +29808,81 @@ var AIAgentView = () => {
|
|
|
29244
29808
|
]
|
|
29245
29809
|
}
|
|
29246
29810
|
) }),
|
|
29247
|
-
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit,
|
|
29248
|
-
/* @__PURE__ */
|
|
29249
|
-
|
|
29250
|
-
|
|
29251
|
-
|
|
29252
|
-
|
|
29253
|
-
|
|
29254
|
-
|
|
29255
|
-
|
|
29256
|
-
|
|
29257
|
-
|
|
29258
|
-
|
|
29259
|
-
|
|
29260
|
-
|
|
29261
|
-
|
|
29262
|
-
|
|
29263
|
-
|
|
29264
|
-
|
|
29265
|
-
|
|
29266
|
-
|
|
29267
|
-
|
|
29268
|
-
|
|
29269
|
-
|
|
29270
|
-
|
|
29271
|
-
|
|
29272
|
-
|
|
29273
|
-
|
|
29274
|
-
|
|
29275
|
-
|
|
29276
|
-
|
|
29277
|
-
|
|
29278
|
-
|
|
29279
|
-
|
|
29280
|
-
|
|
29281
|
-
|
|
29282
|
-
|
|
29283
|
-
|
|
29284
|
-
|
|
29811
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
|
|
29812
|
+
/* @__PURE__ */ jsx(
|
|
29813
|
+
"div",
|
|
29814
|
+
{
|
|
29815
|
+
className: `relative bg-white rounded-3xl shadow-lg border border-gray-200 focus-within:border-gray-300 transition-all duration-200 ${isTransitioning ? "animate-slide-down" : ""}`,
|
|
29816
|
+
style: isTransitioning ? {
|
|
29817
|
+
animation: "slideDown 0.8s cubic-bezier(0.4, 0, 0.2, 1) forwards"
|
|
29818
|
+
} : {},
|
|
29819
|
+
children: /* @__PURE__ */ jsx("div", { className: "flex items-end gap-2 p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex-1 relative", children: [
|
|
29820
|
+
/* @__PURE__ */ jsx(
|
|
29821
|
+
"textarea",
|
|
29822
|
+
{
|
|
29823
|
+
ref: textareaRef,
|
|
29824
|
+
value: inputValue,
|
|
29825
|
+
onChange: (e) => {
|
|
29826
|
+
const newValue = e.target.value;
|
|
29827
|
+
setInputValue(newValue);
|
|
29828
|
+
if (newValue.length > 0 && !hasStartedTyping) {
|
|
29829
|
+
trackTypingStart();
|
|
29830
|
+
}
|
|
29831
|
+
if (newValue.length > 0) {
|
|
29832
|
+
trackTypingProgress(newValue);
|
|
29833
|
+
}
|
|
29834
|
+
if (newValue.length === 0) {
|
|
29835
|
+
resetTypingState();
|
|
29836
|
+
}
|
|
29837
|
+
},
|
|
29838
|
+
onKeyDown: handleKeyDown,
|
|
29839
|
+
onFocus: () => {
|
|
29840
|
+
trackCoreEvent("AI Agent Input Focused", {
|
|
29841
|
+
line_id: lineId,
|
|
29842
|
+
company_id: companyId,
|
|
29843
|
+
shift_id: shiftId,
|
|
29844
|
+
active_thread_id: activeThreadId,
|
|
29845
|
+
has_existing_messages: messages.length > 0,
|
|
29846
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
29847
|
+
});
|
|
29848
|
+
},
|
|
29849
|
+
placeholder: "Ask me about production optimization, quality metrics, or any manufacturing challenge...",
|
|
29850
|
+
className: "w-full resize-none bg-transparent px-2 py-2 pr-12 focus:outline-none placeholder-gray-500 text-gray-900 text-sm leading-relaxed",
|
|
29851
|
+
rows: 1,
|
|
29852
|
+
style: { minHeight: "24px", maxHeight: "120px" }
|
|
29853
|
+
}
|
|
29854
|
+
),
|
|
29855
|
+
/* @__PURE__ */ jsx("div", { className: "absolute right-2 bottom-2 flex items-center gap-2", children: /* @__PURE__ */ jsx(
|
|
29856
|
+
"button",
|
|
29857
|
+
{
|
|
29858
|
+
type: "submit",
|
|
29859
|
+
disabled: !inputValue.trim() || isCurrentThreadLoading,
|
|
29860
|
+
className: "inline-flex items-center justify-center w-8 h-8 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",
|
|
29861
|
+
children: /* @__PURE__ */ jsx(Send, { className: "w-4 h-4" })
|
|
29862
|
+
}
|
|
29863
|
+
) })
|
|
29864
|
+
] }) })
|
|
29865
|
+
}
|
|
29866
|
+
),
|
|
29867
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center mt-2 text-xs text-gray-400", children: [
|
|
29868
|
+
/* @__PURE__ */ jsx("span", { children: isCurrentThreadLoading ? "You can type your next message while Axel responds" : "Press Enter to send \u2022 Shift+Enter for new line" }),
|
|
29869
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 ml-4", children: [
|
|
29870
|
+
/* @__PURE__ */ jsx("div", { className: `w-1.5 h-1.5 rounded-full ${isCurrentThreadLoading ? "bg-orange-500" : "bg-green-500"}` }),
|
|
29871
|
+
/* @__PURE__ */ jsx("span", { children: isCurrentThreadLoading ? "Responding..." : "Connected" })
|
|
29872
|
+
] })
|
|
29285
29873
|
] })
|
|
29286
29874
|
] })
|
|
29287
29875
|
] }) })
|
|
29288
|
-
] })
|
|
29876
|
+
] }),
|
|
29877
|
+
/* @__PURE__ */ jsx("div", { className: `${isSidebarOpen ? "w-80" : "w-0"} transition-all duration-300 overflow-hidden flex-shrink-0 border-l border-gray-200 h-screen fixed right-0 top-0 z-20`, children: /* @__PURE__ */ jsx(
|
|
29878
|
+
ThreadSidebar,
|
|
29879
|
+
{
|
|
29880
|
+
activeThreadId,
|
|
29881
|
+
onSelectThread: setActiveThreadId,
|
|
29882
|
+
onNewThread: handleNewThread,
|
|
29883
|
+
className: "h-full"
|
|
29884
|
+
}
|
|
29885
|
+
) })
|
|
29289
29886
|
] });
|
|
29290
29887
|
};
|
|
29291
29888
|
var AIAgentView_default = AIAgentView;
|
|
@@ -31162,7 +31759,8 @@ var parseBreaksFromDB = (dbBreaks) => {
|
|
|
31162
31759
|
duration: calculateBreakDuration(
|
|
31163
31760
|
breakItem.start || breakItem.startTime || "00:00",
|
|
31164
31761
|
breakItem.end || breakItem.endTime || "00:00"
|
|
31165
|
-
)
|
|
31762
|
+
),
|
|
31763
|
+
remarks: breakItem.remarks || breakItem.name || ""
|
|
31166
31764
|
}));
|
|
31167
31765
|
} else if (dbBreaks.breaks && Array.isArray(dbBreaks.breaks)) {
|
|
31168
31766
|
return dbBreaks.breaks.map((breakItem) => ({
|
|
@@ -31171,7 +31769,8 @@ var parseBreaksFromDB = (dbBreaks) => {
|
|
|
31171
31769
|
duration: calculateBreakDuration(
|
|
31172
31770
|
breakItem.start || breakItem.startTime || "00:00",
|
|
31173
31771
|
breakItem.end || breakItem.endTime || "00:00"
|
|
31174
|
-
)
|
|
31772
|
+
),
|
|
31773
|
+
remarks: breakItem.remarks || breakItem.name || ""
|
|
31175
31774
|
}));
|
|
31176
31775
|
} else {
|
|
31177
31776
|
console.warn("Unexpected breaks format:", dbBreaks);
|
|
@@ -31189,7 +31788,8 @@ var formatBreaks = (breaks) => {
|
|
|
31189
31788
|
return {
|
|
31190
31789
|
breaks: breaks.map((breakItem) => ({
|
|
31191
31790
|
start: breakItem.startTime,
|
|
31192
|
-
end: breakItem.endTime
|
|
31791
|
+
end: breakItem.endTime,
|
|
31792
|
+
remarks: breakItem.remarks || ""
|
|
31193
31793
|
}))
|
|
31194
31794
|
};
|
|
31195
31795
|
};
|
|
@@ -31199,13 +31799,14 @@ var BreakRow = memo(({
|
|
|
31199
31799
|
onRemove,
|
|
31200
31800
|
index
|
|
31201
31801
|
}) => {
|
|
31202
|
-
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-
|
|
31802
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-2 sm:gap-4 items-center w-full bg-white hover:bg-gray-50 rounded-md transition-all duration-200 p-2", children: [
|
|
31203
31803
|
/* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
|
|
31204
31804
|
"input",
|
|
31205
31805
|
{
|
|
31206
31806
|
type: "time",
|
|
31207
31807
|
value: breakItem.startTime,
|
|
31208
31808
|
onChange: (e) => onUpdate(index, "startTime", e.target.value),
|
|
31809
|
+
step: "60",
|
|
31209
31810
|
className: "w-full px-2 sm:px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
31210
31811
|
}
|
|
31211
31812
|
) }),
|
|
@@ -31215,6 +31816,7 @@ var BreakRow = memo(({
|
|
|
31215
31816
|
type: "time",
|
|
31216
31817
|
value: breakItem.endTime,
|
|
31217
31818
|
onChange: (e) => onUpdate(index, "endTime", e.target.value),
|
|
31819
|
+
step: "60",
|
|
31218
31820
|
className: "w-full px-2 sm:px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
31219
31821
|
}
|
|
31220
31822
|
) }),
|
|
@@ -31222,6 +31824,16 @@ var BreakRow = memo(({
|
|
|
31222
31824
|
breakItem.duration,
|
|
31223
31825
|
" min"
|
|
31224
31826
|
] }) }),
|
|
31827
|
+
/* @__PURE__ */ jsx("div", { className: "col-span-3", children: /* @__PURE__ */ jsx(
|
|
31828
|
+
"input",
|
|
31829
|
+
{
|
|
31830
|
+
type: "text",
|
|
31831
|
+
value: breakItem.remarks || "",
|
|
31832
|
+
onChange: (e) => onUpdate(index, "remarks", e.target.value),
|
|
31833
|
+
placeholder: "Break remarks",
|
|
31834
|
+
className: "w-full px-2 sm:px-3 py-2 border border-gray-300 rounded-md text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
31835
|
+
}
|
|
31836
|
+
) }),
|
|
31225
31837
|
/* @__PURE__ */ jsx("div", { className: "col-span-1 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
31226
31838
|
"button",
|
|
31227
31839
|
{
|
|
@@ -31338,10 +31950,11 @@ var ShiftPanel = memo(({
|
|
|
31338
31950
|
"Breaks"
|
|
31339
31951
|
] }) }),
|
|
31340
31952
|
/* @__PURE__ */ jsx("div", { className: "space-y-2 mb-4 w-full", children: breaks.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31341
|
-
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-
|
|
31953
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-12 gap-2 sm:gap-4 text-xs font-medium text-gray-500 mb-1 w-full px-2", children: [
|
|
31342
31954
|
/* @__PURE__ */ jsx("div", { className: "col-span-3", children: "Break Start" }),
|
|
31343
31955
|
/* @__PURE__ */ jsx("div", { className: "col-span-3", children: "Break End" }),
|
|
31344
31956
|
/* @__PURE__ */ jsx("div", { className: "col-span-2", children: "Duration" }),
|
|
31957
|
+
/* @__PURE__ */ jsx("div", { className: "col-span-3", children: "Remarks" }),
|
|
31345
31958
|
/* @__PURE__ */ jsx("div", { className: "col-span-1" })
|
|
31346
31959
|
] }),
|
|
31347
31960
|
/* @__PURE__ */ jsx("div", { className: "bg-gray-50/80 p-2 rounded-md", children: breaks.map((breakItem, index) => /* @__PURE__ */ jsx(
|
|
@@ -31554,7 +32167,8 @@ var ShiftsView = ({
|
|
|
31554
32167
|
const newBreak = {
|
|
31555
32168
|
startTime: dayShift.startTime,
|
|
31556
32169
|
endTime: dayShift.startTime,
|
|
31557
|
-
duration: 0
|
|
32170
|
+
duration: 0,
|
|
32171
|
+
remarks: ""
|
|
31558
32172
|
};
|
|
31559
32173
|
return {
|
|
31560
32174
|
...typedConfig,
|
|
@@ -31595,14 +32209,16 @@ var ShiftsView = ({
|
|
|
31595
32209
|
const dayShift = { ...typedConfig.dayShift };
|
|
31596
32210
|
const newBreaks = [...dayShift.breaks];
|
|
31597
32211
|
newBreaks[index] = { ...newBreaks[index], [field]: value };
|
|
31598
|
-
|
|
31599
|
-
|
|
31600
|
-
|
|
31601
|
-
|
|
31602
|
-
|
|
31603
|
-
endMinutes
|
|
31604
|
-
|
|
31605
|
-
|
|
32212
|
+
if (field === "startTime" || field === "endTime") {
|
|
32213
|
+
const startParts = newBreaks[index].startTime.split(":").map(Number);
|
|
32214
|
+
const endParts = newBreaks[index].endTime.split(":").map(Number);
|
|
32215
|
+
let startMinutes = startParts[0] * 60 + startParts[1];
|
|
32216
|
+
let endMinutes = endParts[0] * 60 + endParts[1];
|
|
32217
|
+
if (endMinutes < startMinutes) {
|
|
32218
|
+
endMinutes += 24 * 60;
|
|
32219
|
+
}
|
|
32220
|
+
newBreaks[index].duration = endMinutes - startMinutes;
|
|
32221
|
+
}
|
|
31606
32222
|
return {
|
|
31607
32223
|
...typedConfig,
|
|
31608
32224
|
dayShift: {
|
|
@@ -31621,14 +32237,16 @@ var ShiftsView = ({
|
|
|
31621
32237
|
const nightShift = { ...typedConfig.nightShift };
|
|
31622
32238
|
const newBreaks = [...nightShift.breaks];
|
|
31623
32239
|
newBreaks[index] = { ...newBreaks[index], [field]: value };
|
|
31624
|
-
|
|
31625
|
-
|
|
31626
|
-
|
|
31627
|
-
|
|
31628
|
-
|
|
31629
|
-
endMinutes
|
|
31630
|
-
|
|
31631
|
-
|
|
32240
|
+
if (field === "startTime" || field === "endTime") {
|
|
32241
|
+
const startParts = newBreaks[index].startTime.split(":").map(Number);
|
|
32242
|
+
const endParts = newBreaks[index].endTime.split(":").map(Number);
|
|
32243
|
+
let startMinutes = startParts[0] * 60 + startParts[1];
|
|
32244
|
+
let endMinutes = endParts[0] * 60 + endParts[1];
|
|
32245
|
+
if (endMinutes < startMinutes) {
|
|
32246
|
+
endMinutes += 24 * 60;
|
|
32247
|
+
}
|
|
32248
|
+
newBreaks[index].duration = endMinutes - startMinutes;
|
|
32249
|
+
}
|
|
31632
32250
|
return {
|
|
31633
32251
|
...typedConfig,
|
|
31634
32252
|
nightShift: {
|