@contenify/chatbot 0.1.2 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -49,9 +49,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
49
49
  var index_exports = {};
50
50
  __export(index_exports, {
51
51
  ContenifyChatBot: () => ContenifyChatBot,
52
- default: () => index_default
52
+ default: () => index_default,
53
+ setConfig: () => setConfig
53
54
  });
54
55
  module.exports = __toCommonJS(index_exports);
56
+ var import_react11 = require("react");
55
57
 
56
58
  // contexts/PreferencesContext.tsx
57
59
  var import_react = require("react");
@@ -60,12 +62,22 @@ var import_react = require("react");
60
62
  var import_axios = __toESM(require("axios"));
61
63
 
62
64
  // lib/config.ts
65
+ var _apiUrl = process.env.NEXT_PUBLIC_CONTENIFY_API_URL || "http://localhost:8080/api";
66
+ var _apiKey = process.env.NEXT_PUBLIC_API_KEY || "";
67
+ var _domain = process.env.NEXT_PUBLIC_DOMAIN || "";
68
+ function setConfig(config) {
69
+ if (config.apiUrl) _apiUrl = config.apiUrl;
70
+ if (config.apiKey) _apiKey = config.apiKey;
71
+ if (config.domain) _domain = config.domain;
72
+ }
63
73
  function getApiBaseUrl() {
64
- return process.env.NEXT_PUBLIC_CONTENIFY_API_URL || DEFAULT_API_BASE_URL;
74
+ return _apiUrl;
65
75
  }
66
76
  function getServerBaseUrl() {
67
- const apiUrl = getApiBaseUrl();
68
- return apiUrl.replace(/\/api\/?$/, "");
77
+ return _apiUrl.replace(/\/api\/?$/, "");
78
+ }
79
+ function getApiKey() {
80
+ return _apiKey;
69
81
  }
70
82
 
71
83
  // lib/api.ts
@@ -78,7 +90,7 @@ var api = import_axios.default.create({
78
90
  });
79
91
  api.interceptors.request.use(
80
92
  (config) => {
81
- const apiKey = process.env.NEXT_PUBLIC_API_KEY;
93
+ const apiKey = getApiKey();
82
94
  if (apiKey) {
83
95
  config.headers["x-api-key"] = apiKey;
84
96
  }
@@ -101,6 +113,88 @@ var getMyPreferencesApi = async () => {
101
113
  const { data } = await api_default.get("/preferences/me");
102
114
  return data.data;
103
115
  };
116
+ var savePreferencesApi = async ({
117
+ botName,
118
+ logo,
119
+ state,
120
+ cities,
121
+ primaryColor,
122
+ secondaryColor,
123
+ theme,
124
+ language,
125
+ showSidebar,
126
+ showHeader,
127
+ activeThemePreset,
128
+ showNewsPanel,
129
+ tone,
130
+ style,
131
+ wordCount,
132
+ includeQuotes,
133
+ includeFAQ,
134
+ targetAudience
135
+ }) => {
136
+ const formData = new FormData();
137
+ if (botName) {
138
+ formData.append("botName", botName);
139
+ }
140
+ if (logo) {
141
+ formData.append("logo", logo);
142
+ }
143
+ if (state) {
144
+ formData.append("state", state);
145
+ }
146
+ if (cities) {
147
+ formData.append("cities", JSON.stringify(cities));
148
+ }
149
+ if (primaryColor) {
150
+ formData.append("primaryColor", primaryColor);
151
+ }
152
+ if (secondaryColor) {
153
+ formData.append("secondaryColor", secondaryColor);
154
+ }
155
+ if (theme) {
156
+ formData.append("theme", theme);
157
+ }
158
+ if (language) {
159
+ formData.append("language", language);
160
+ }
161
+ if (showSidebar !== void 0) {
162
+ formData.append("showSidebar", String(showSidebar));
163
+ }
164
+ if (showHeader !== void 0) {
165
+ formData.append("showHeader", String(showHeader));
166
+ }
167
+ if (activeThemePreset !== void 0) {
168
+ formData.append("activeThemePreset", activeThemePreset != null ? activeThemePreset : "");
169
+ }
170
+ if (showNewsPanel !== void 0) {
171
+ formData.append("showNewsPanel", String(showNewsPanel));
172
+ }
173
+ if (tone) {
174
+ formData.append("tone", tone);
175
+ }
176
+ if (style) {
177
+ formData.append("style", style);
178
+ }
179
+ if (wordCount) {
180
+ formData.append("wordCount", wordCount);
181
+ }
182
+ if (includeQuotes !== void 0) {
183
+ formData.append("includeQuotes", String(includeQuotes));
184
+ }
185
+ if (includeFAQ !== void 0) {
186
+ formData.append("includeFAQ", String(includeFAQ));
187
+ }
188
+ if (targetAudience !== void 0) {
189
+ formData.append("targetAudience", targetAudience);
190
+ }
191
+ const { data } = await api_default.put("/preferences", formData, {
192
+ headers: {
193
+ "Content-Type": "multipart/form-data"
194
+ }
195
+ });
196
+ return data.data;
197
+ };
104
198
 
105
199
  // contexts/PreferencesContext.tsx
106
200
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -205,59 +299,6 @@ function usePreferences() {
205
299
  // components/chatbot/ChatBot.tsx
206
300
  var import_react10 = require("react");
207
301
 
208
- // components/chatbot/ArticleModal.tsx
209
- var import_jsx_runtime2 = require("react/jsx-runtime");
210
- function ArticleModal({
211
- article,
212
- onClose,
213
- onRecreate
214
- }) {
215
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm flex items-center justify-center px-4", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "relative w-full max-w-3xl bg-white rounded-xl shadow-card border border-gray-200 animate-in fade-in zoom-in", children: [
216
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-start justify-between px-6 py-4 border-b border-gray-300", children: [
217
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { children: [
218
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs text-gray-500 mb-1", children: "Source Article" }),
219
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h2", { className: "text-lg font-semibold text-gray-900 leading-snug", children: article.title })
220
- ] }),
221
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
222
- "button",
223
- {
224
- onClick: onClose,
225
- className: "text-gray-400 hover:text-gray-700 transition",
226
- "aria-label": "Close modal",
227
- children: "\u2715"
228
- }
229
- )
230
- ] }),
231
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "px-6 py-5 max-h-[65vh] overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "prose prose-sm max-w-none text-gray-800", children: article.content }) }),
232
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-t bg-gray-50 rounded-b-xl", children: [
233
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs text-gray-400", children: "This content will be recreated using AI" }),
234
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2", children: [
235
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
236
- "button",
237
- {
238
- onClick: onClose,
239
- className: "px-4 py-2 text-sm rounded-md border border-gray-300 text-gray-700 hover:bg-gray-100 transition",
240
- children: "Cancel"
241
- }
242
- ),
243
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
244
- "button",
245
- {
246
- onClick: () => onRecreate({
247
- title: article.title,
248
- content: article.content,
249
- id: article._id
250
- // Include article ID when available
251
- }),
252
- className: "px-4 py-2 text-sm rounded-md bg-gray-900 text-white hover:bg-black transition",
253
- children: "Recreate Article"
254
- }
255
- )
256
- ] })
257
- ] })
258
- ] }) });
259
- }
260
-
261
302
  // util/util.ts
262
303
  function extractArticleContent(raw) {
263
304
  if (!raw) {
@@ -299,7 +340,7 @@ var import_starter_kit = __toESM(require("@tiptap/starter-kit"));
299
340
  var import_extension_placeholder = __toESM(require("@tiptap/extension-placeholder"));
300
341
  var import_lucide_react = require("lucide-react");
301
342
  var import_react3 = require("react");
302
- var import_jsx_runtime3 = require("react/jsx-runtime");
343
+ var import_jsx_runtime2 = require("react/jsx-runtime");
303
344
  function RichTextEditor({
304
345
  content,
305
346
  onChange,
@@ -321,7 +362,7 @@ function RichTextEditor({
321
362
  content,
322
363
  editorProps: {
323
364
  attributes: {
324
- class: "prose prose-sm max-w-none focus:outline-none min-h-[350px] p-4"
365
+ class: "ProseMirror"
325
366
  }
326
367
  },
327
368
  onUpdate: ({ editor: editor2 }) => {
@@ -334,96 +375,96 @@ function RichTextEditor({
334
375
  }
335
376
  }, [content, editor]);
336
377
  if (!editor) {
337
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "w-full h-[400px] border border-gray-300 rounded-lg flex items-center justify-center text-gray-400", children: "Loading editor..." });
378
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "cnfy-editor-loading", children: "Loading editor..." });
338
379
  }
339
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "w-full border border-gray-300 rounded-lg overflow-hidden", children: [
340
- /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-wrap items-center gap-1 p-2 border-b border-gray-200 bg-gray-50", children: [
341
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
380
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "cnfy-editor", children: [
381
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "cnfy-toolbar", children: [
382
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
342
383
  ToolbarButton,
343
384
  {
344
385
  onClick: () => editor.chain().focus().toggleHeading({ level: 1 }).run(),
345
386
  isActive: editor.isActive("heading", { level: 1 }),
346
387
  title: "Heading 1",
347
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Heading1, { size: 18 })
388
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Heading1, { size: 18 })
348
389
  }
349
390
  ),
350
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
391
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
351
392
  ToolbarButton,
352
393
  {
353
394
  onClick: () => editor.chain().focus().toggleHeading({ level: 2 }).run(),
354
395
  isActive: editor.isActive("heading", { level: 2 }),
355
396
  title: "Heading 2",
356
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Heading2, { size: 18 })
397
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Heading2, { size: 18 })
357
398
  }
358
399
  ),
359
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
400
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
360
401
  ToolbarButton,
361
402
  {
362
403
  onClick: () => editor.chain().focus().setParagraph().run(),
363
404
  isActive: editor.isActive("paragraph"),
364
405
  title: "Paragraph",
365
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Pilcrow, { size: 18 })
406
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Pilcrow, { size: 18 })
366
407
  }
367
408
  ),
368
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }),
369
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
409
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "cnfy-toolbar-divider" }),
410
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
370
411
  ToolbarButton,
371
412
  {
372
413
  onClick: () => editor.chain().focus().toggleBold().run(),
373
414
  isActive: editor.isActive("bold"),
374
415
  title: "Bold",
375
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Bold, { size: 18 })
416
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Bold, { size: 18 })
376
417
  }
377
418
  ),
378
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
419
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
379
420
  ToolbarButton,
380
421
  {
381
422
  onClick: () => editor.chain().focus().toggleItalic().run(),
382
423
  isActive: editor.isActive("italic"),
383
424
  title: "Italic",
384
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Italic, { size: 18 })
425
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Italic, { size: 18 })
385
426
  }
386
427
  ),
387
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }),
388
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
428
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "cnfy-toolbar-divider" }),
429
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
389
430
  ToolbarButton,
390
431
  {
391
432
  onClick: () => editor.chain().focus().toggleBulletList().run(),
392
433
  isActive: editor.isActive("bulletList"),
393
434
  title: "Bullet List",
394
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.List, { size: 18 })
435
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.List, { size: 18 })
395
436
  }
396
437
  ),
397
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
438
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
398
439
  ToolbarButton,
399
440
  {
400
441
  onClick: () => editor.chain().focus().toggleOrderedList().run(),
401
442
  isActive: editor.isActive("orderedList"),
402
443
  title: "Numbered List",
403
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.ListOrdered, { size: 18 })
444
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.ListOrdered, { size: 18 })
404
445
  }
405
446
  ),
406
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "w-px h-6 bg-gray-300 mx-1" }),
407
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
447
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "cnfy-toolbar-divider" }),
448
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
408
449
  ToolbarButton,
409
450
  {
410
451
  onClick: () => editor.chain().focus().undo().run(),
411
452
  disabled: !editor.can().undo(),
412
453
  title: "Undo",
413
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Undo, { size: 18 })
454
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Undo, { size: 18 })
414
455
  }
415
456
  ),
416
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
457
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
417
458
  ToolbarButton,
418
459
  {
419
460
  onClick: () => editor.chain().focus().redo().run(),
420
461
  disabled: !editor.can().redo(),
421
462
  title: "Redo",
422
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react.Redo, { size: 18 })
463
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Redo, { size: 18 })
423
464
  }
424
465
  )
425
466
  ] }),
426
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react2.EditorContent, { editor, className: "min-h-[350px]" })
467
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react2.EditorContent, { editor, className: "cnfy-editor-content" })
427
468
  ] });
428
469
  }
429
470
  function ToolbarButton({
@@ -433,13 +474,13 @@ function ToolbarButton({
433
474
  title,
434
475
  children
435
476
  }) {
436
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
477
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
437
478
  "button",
438
479
  {
439
480
  onClick,
440
481
  disabled,
441
482
  title,
442
- className: `p-2 rounded hover:bg-gray-200 transition-colors ${isActive ? "bg-gray-200 text-emerald-600" : "text-gray-600"} ${disabled ? "opacity-40 cursor-not-allowed" : ""}`,
483
+ className: `cnfy-toolbar-btn ${isActive ? "cnfy-toolbar-btn--active" : ""} ${disabled ? "cnfy-toolbar-btn--disabled" : ""}`,
443
484
  children
444
485
  }
445
486
  );
@@ -464,7 +505,7 @@ function useTheme() {
464
505
  }
465
506
 
466
507
  // components/chatbot/EditModal.tsx
467
- var import_jsx_runtime4 = require("react/jsx-runtime");
508
+ var import_jsx_runtime3 = require("react/jsx-runtime");
468
509
  function EditModal({
469
510
  isOpen,
470
511
  initialContent,
@@ -523,30 +564,30 @@ function EditModal({
523
564
  }
524
565
  };
525
566
  if (!isOpen) return null;
526
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "fixed inset-0 z-50 flex items-center justify-center", children: [
527
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
567
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-overlay", children: [
568
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
528
569
  "div",
529
570
  {
530
- className: "absolute inset-0 bg-black/50",
571
+ className: "cnfy-edit-modal-backdrop",
531
572
  onClick: onClose
532
573
  }
533
574
  ),
534
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative w-full h-full max-w-5xl max-h-[90vh] m-4 bg-white rounded-xl shadow-2xl flex flex-col overflow-hidden", children: [
535
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b", children: [
536
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "text-xl font-semibold text-gray-900", children: "Edit Article" }),
537
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
575
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal", children: [
576
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-header", children: [
577
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "cnfy-edit-modal-title", children: "Edit Article" }),
578
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
538
579
  "button",
539
580
  {
540
581
  onClick: onClose,
541
- className: "p-2 rounded-full hover:bg-gray-100 transition-colors",
542
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.X, { size: 20, className: "text-gray-500" })
582
+ className: "cnfy-edit-modal-close-btn",
583
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { size: 20, className: "cnfy-edit-modal-close-icon" })
543
584
  }
544
585
  )
545
586
  ] }),
546
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex-1 overflow-y-auto p-6 space-y-6", children: [
547
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
548
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Article Content" }),
549
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
587
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-body", children: [
588
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
589
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Article Content" }),
590
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
550
591
  RichTextEditor,
551
592
  {
552
593
  content,
@@ -555,29 +596,29 @@ function EditModal({
555
596
  }
556
597
  )
557
598
  ] }),
558
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
559
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Meta Keywords" }),
560
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex flex-wrap gap-2 mb-3", children: keywords.map((keyword, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
599
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
600
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("label", { className: "cnfy-edit-label", children: "Meta Keywords" }),
601
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "cnfy-keyword-list", children: keywords.map((keyword, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
561
602
  "span",
562
603
  {
563
- className: "inline-flex items-center gap-1 px-3 py-1 bg-gray-100 text-gray-700 rounded-full text-sm",
604
+ className: "cnfy-keyword-tag",
564
605
  children: [
565
606
  "#",
566
607
  keyword,
567
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
608
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
568
609
  "button",
569
610
  {
570
611
  onClick: () => handleRemoveKeyword(index),
571
- className: "ml-1 text-gray-400 hover:text-gray-600",
572
- children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react2.X, { size: 14 })
612
+ className: "cnfy-keyword-remove-btn",
613
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { size: 14 })
573
614
  }
574
615
  )
575
616
  ]
576
617
  },
577
618
  index
578
619
  )) }),
579
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex gap-2", children: [
580
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
620
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-keyword-input-row", children: [
621
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
581
622
  "input",
582
623
  {
583
624
  type: "text",
@@ -585,42 +626,42 @@ function EditModal({
585
626
  onChange: (e) => setNewKeyword(e.target.value),
586
627
  onKeyDown: handleKeyDown,
587
628
  placeholder: "Add a keyword...",
588
- className: "flex-1 px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-emerald-500 focus:border-emerald-500"
629
+ className: "cnfy-keyword-input"
589
630
  }
590
631
  ),
591
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
632
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
592
633
  "button",
593
634
  {
594
635
  onClick: handleAddKeyword,
595
- className: "px-4 py-2 bg-gray-100 text-gray-700 rounded-lg text-sm font-medium hover:bg-gray-200 transition-colors",
636
+ className: "cnfy-btn-add-keyword",
596
637
  children: "Add"
597
638
  }
598
639
  )
599
640
  ] })
600
641
  ] })
601
642
  ] }),
602
- /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center justify-end gap-3 px-6 py-4 border-t bg-gray-50", children: [
603
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
643
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "cnfy-edit-modal-footer", children: [
644
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
604
645
  "button",
605
646
  {
606
647
  onClick: onClose,
607
- className: "px-4 py-2 text-gray-700 text-sm font-medium hover:bg-gray-100 rounded-lg transition-colors",
648
+ className: "cnfy-btn-footer-cancel",
608
649
  children: "Cancel"
609
650
  }
610
651
  ),
611
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
652
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
612
653
  "button",
613
654
  {
614
655
  onClick: () => onSaveDraft(content, keywords),
615
- className: "px-4 py-2 bg-gray-200 text-gray-800 text-sm font-medium rounded-lg hover:bg-gray-300 transition-colors",
656
+ className: "cnfy-btn-save-draft",
616
657
  children: "Save Draft"
617
658
  }
618
659
  ),
619
- /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
660
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
620
661
  "button",
621
662
  {
622
663
  onClick: () => onPost(content, keywords),
623
- className: "px-4 py-2 bg-emerald-600 text-white text-sm font-medium rounded-lg hover:bg-emerald-700 transition-colors",
664
+ className: "cnfy-btn-post-article",
624
665
  style: { backgroundColor: primaryColor, color: "#fff" },
625
666
  children: "Post"
626
667
  }
@@ -633,7 +674,7 @@ function EditModal({
633
674
  // components/news/NewsList.tsx
634
675
  var import_react5 = require("react");
635
676
  var import_lucide_react3 = require("lucide-react");
636
- var import_jsx_runtime5 = require("react/jsx-runtime");
677
+ var import_jsx_runtime4 = require("react/jsx-runtime");
637
678
  var dateFormatter = new Intl.DateTimeFormat("en-GB", {
638
679
  day: "2-digit",
639
680
  month: "short",
@@ -675,22 +716,22 @@ function NewsList({
675
716
  b = Math.round(b + (255 - b) * (percent / 100));
676
717
  return `rgb(${r}, ${g}, ${b})`;
677
718
  };
678
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "p-4 space-y-3", children: news.flatMap((item) => {
719
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "cnfy-news-list", children: news.flatMap((item) => {
679
720
  const publishedDate = new Date(item.publishedAt);
680
721
  const links = extractLinksFromContent(item.content);
681
722
  if (links.length > 0) {
682
- return links.map((link, idx) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
723
+ return links.map((link, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
683
724
  "div",
684
725
  {
685
- className: "flex items-start justify-between gap-3 rounded-lg border border-gray-200 bg-white p-3 text-sm hover:bg-gray-50 transition",
726
+ className: "cnfy-news-card",
686
727
  children: [
687
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "min-w-0", children: [
688
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "font-bold text-gray-900 line-clamp-2", children: link.title }),
689
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-2 mt-2 text-xs text-gray-500", children: [
690
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
728
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "cnfy-news-card-content", children: [
729
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "cnfy-news-card-title", children: link.title }),
730
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "cnfy-news-card-meta", children: [
731
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
691
732
  "span",
692
733
  {
693
- className: "inline-flex items-center rounded-full px-2 py-0.5 font-medium border",
734
+ className: "cnfy-news-badge",
694
735
  style: {
695
736
  backgroundColor: lightenColor(primaryColorState, 95),
696
737
  color: primaryColor,
@@ -699,38 +740,37 @@ function NewsList({
699
740
  children: link.source || item.sourceName
700
741
  }
701
742
  ),
702
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u2022" }),
703
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "capitalize", children: item.category }),
704
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u2022" }),
705
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
743
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u2022" }),
744
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "cnfy-news-card-category", children: item.category }),
745
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u2022" }),
746
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
706
747
  dateFormatter.format(publishedDate),
707
748
  " ",
708
749
  timeFormatter.format(publishedDate)
709
750
  ] })
710
751
  ] })
711
752
  ] }),
712
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-2 shrink-0", children: [
713
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
753
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "cnfy-news-card-actions", children: [
754
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
714
755
  "button",
715
756
  {
716
757
  onClick: () => window.open(link.url, "_blank"),
717
- className: "p-1 text-gray-400 hover:text-gray-700",
758
+ className: "cnfy-news-action-btn",
718
759
  title: "View",
719
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.Eye, { size: 16 })
760
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.Eye, { size: 16 })
720
761
  }
721
762
  ),
722
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
763
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
723
764
  "button",
724
765
  {
725
766
  onClick: () => onRecreate({
726
767
  title: link.title,
727
768
  content: link.title,
728
769
  id: item._id
729
- // Include article ID
730
770
  }),
731
- className: "p-1 text-gray-400 hover:text-gray-700",
771
+ className: "cnfy-news-action-btn",
732
772
  title: "Recreate",
733
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.RefreshCcw, { size: 16 })
773
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.RefreshCcw, { size: 16 })
734
774
  }
735
775
  )
736
776
  ] })
@@ -739,18 +779,18 @@ function NewsList({
739
779
  `${item._id}-link-${idx}`
740
780
  ));
741
781
  }
742
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
782
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
743
783
  "div",
744
784
  {
745
- className: "flex items-start justify-between gap-3 rounded-lg border border-gray-200 bg-white p-3 text-sm hover:bg-gray-50 transition",
785
+ className: "cnfy-news-card",
746
786
  children: [
747
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "min-w-0", children: [
748
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "font-bold text-gray-900 line-clamp-2", children: item.title }),
749
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-2 mt-2 text-xs text-gray-500", children: [
750
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
787
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "cnfy-news-card-content", children: [
788
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "cnfy-news-card-title", children: item.title }),
789
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "cnfy-news-card-meta", children: [
790
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
751
791
  "span",
752
792
  {
753
- className: "inline-flex items-center rounded-full px-2 py-0.5 font-medium border",
793
+ className: "cnfy-news-badge",
754
794
  style: {
755
795
  backgroundColor: lightenColor(primaryColorState, 95),
756
796
  color: primaryColor,
@@ -759,38 +799,37 @@ function NewsList({
759
799
  children: item.sourceName
760
800
  }
761
801
  ),
762
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u2022" }),
763
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "capitalize", children: item.category }),
764
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "\u2022" }),
765
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
802
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u2022" }),
803
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "cnfy-news-card-category", children: item.category }),
804
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "\u2022" }),
805
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { children: [
766
806
  dateFormatter.format(publishedDate),
767
807
  " ",
768
808
  timeFormatter.format(publishedDate)
769
809
  ] })
770
810
  ] })
771
811
  ] }),
772
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-col gap-2 shrink-0", children: [
773
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
812
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "cnfy-news-card-actions", children: [
813
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
774
814
  "button",
775
815
  {
776
816
  onClick: () => onView(item),
777
- className: "p-1 text-gray-400 hover:text-gray-700",
817
+ className: "cnfy-news-action-btn",
778
818
  title: "View",
779
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.Eye, { size: 16 })
819
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.Eye, { size: 16 })
780
820
  }
781
821
  ),
782
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
822
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
783
823
  "button",
784
824
  {
785
825
  onClick: () => onRecreate({
786
826
  title: item.title,
787
827
  content: item.content || item.title,
788
828
  id: item._id
789
- // Include article ID
790
829
  }),
791
- className: "p-1 text-gray-400 hover:text-gray-700",
830
+ className: "cnfy-news-action-btn",
792
831
  title: "Recreate",
793
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react3.RefreshCcw, { size: 16 })
832
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.RefreshCcw, { size: 16 })
794
833
  }
795
834
  )
796
835
  ] })
@@ -821,7 +860,7 @@ var getNewsBySource = async (sourceId) => {
821
860
 
822
861
  // components/chatbot/ChatWindow.tsx
823
862
  var import_react_select = __toESM(require("react-select"));
824
- var import_jsx_runtime6 = require("react/jsx-runtime");
863
+ var import_jsx_runtime5 = require("react/jsx-runtime");
825
864
  var ACTION_ICONS = {
826
865
  recreate_article: import_lucide_react4.RefreshCcw,
827
866
  create_summary: import_lucide_react4.ListChecks,
@@ -997,59 +1036,59 @@ function ChatWindow({
997
1036
  });
998
1037
  return { blocks, metaKeywords };
999
1038
  }
1000
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "h-full flex w-full flex-col", children: [
1001
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 px-4 py-6", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "max-w-3xl chat-scroll mx-auto space-y-6", children: [
1039
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-chat", children: [
1040
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-chat-area", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-chat-scroll", children: [
1002
1041
  messages.map((msg) => {
1003
1042
  var _a2;
1004
1043
  const parsed = formatAIContent(msg.content);
1005
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-3", children: [
1006
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1044
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-msg", children: [
1045
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-avatar-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1007
1046
  "div",
1008
1047
  {
1009
- className: "h-8 w-8 rounded-full flex items-center justify-center text-xs font-semibold text-white",
1048
+ className: "cnfy-msg-avatar",
1010
1049
  style: {
1011
1050
  backgroundColor: msg.role === "assistant" ? primaryColor : "#1f2937"
1012
1051
  },
1013
1052
  children: msg.role === "assistant" ? "AI" : "You"
1014
1053
  }
1015
1054
  ) }),
1016
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex-1 text-sm space-y-3 leading-relaxed", children: [
1017
- msg.role === "assistant" && parsed.blocks.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex justify-end -mt-1 mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1055
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-msg-body", children: [
1056
+ msg.role === "assistant" && parsed.blocks.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-copy-row", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1018
1057
  "button",
1019
1058
  {
1020
1059
  onClick: () => handleCopy(parsed.blocks, msg.id),
1021
- className: "p-1.5 rounded-md hover:bg-gray-100 transition-colors text-gray-400 hover:text-gray-600",
1060
+ className: "cnfy-copy-btn",
1022
1061
  title: "Copy to clipboard",
1023
- children: copiedId === msg.id ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Check, { size: 16, className: "text-emerald-600" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Copy, { size: 16 })
1062
+ children: copiedId === msg.id ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Check, { size: 16, className: "cnfy-copy-icon--copied" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Copy, { size: 16 })
1024
1063
  }
1025
1064
  ) }),
1026
1065
  parsed.blocks.map((block, idx) => {
1027
1066
  if (block.type === "h1") {
1028
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1067
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1029
1068
  "h1",
1030
1069
  {
1031
- className: "text-sm font-semibold",
1070
+ className: "cnfy-block-h1",
1032
1071
  children: block.text
1033
1072
  },
1034
1073
  idx
1035
1074
  );
1036
1075
  }
1037
1076
  if (block.type === "h2") {
1038
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1077
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1039
1078
  "h2",
1040
1079
  {
1041
- className: "text-base font-semibold mt-4",
1080
+ className: "cnfy-block-h2",
1042
1081
  children: block.text
1043
1082
  },
1044
1083
  idx
1045
1084
  );
1046
1085
  }
1047
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-gray-800", children: block.text }, idx);
1086
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "cnfy-block-p", children: block.text }, idx);
1048
1087
  }),
1049
- parsed.metaKeywords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "pt-4 border-t mt-6", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap gap-2", children: parsed.metaKeywords.map((tag, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1088
+ parsed.metaKeywords.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-msg-keywords-list", children: parsed.metaKeywords.map((tag, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1050
1089
  "span",
1051
1090
  {
1052
- className: "text-xs px-3 py-1 rounded-full bg-gray-100 text-gray-700",
1091
+ className: "cnfy-msg-keyword-tag",
1053
1092
  children: [
1054
1093
  "#",
1055
1094
  tag
@@ -1057,41 +1096,41 @@ function ChatWindow({
1057
1096
  },
1058
1097
  i
1059
1098
  )) }) }),
1060
- msg.role === "assistant" && (analyzedData == null ? void 0 : analyzedData.messageId) === msg.id && analyzedData.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex flex-wrap gap-2 pt-4 mt-2", children: analyzedData.options.map((option) => {
1099
+ msg.role === "assistant" && (analyzedData == null ? void 0 : analyzedData.messageId) === msg.id && analyzedData.options.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-action-options", children: analyzedData.options.map((option) => {
1061
1100
  const IconComponent = ACTION_ICONS[option.id] || import_lucide_react4.FileText;
1062
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1101
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1063
1102
  "button",
1064
1103
  {
1065
1104
  onClick: () => onSelectAction == null ? void 0 : onSelectAction(option.id, analyzedData.url, analyzedData.content),
1066
- className: "flex items-center gap-2 px-4 py-2 border border-gray-200 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-50 hover:border-gray-300 transition-colors",
1105
+ className: "cnfy-action-btn",
1067
1106
  children: [
1068
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconComponent, { size: 16 }),
1107
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconComponent, { size: 16 }),
1069
1108
  option.name
1070
1109
  ]
1071
1110
  },
1072
1111
  option.id
1073
1112
  );
1074
1113
  }) }),
1075
- msg.role === "assistant" && parsed.blocks.length > 0 && !(analyzedData == null ? void 0 : analyzedData.messageId) && (!isStreaming || msg.id !== ((_a2 = messages[messages.length - 1]) == null ? void 0 : _a2.id)) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex gap-3 pt-4 mt-2", children: [
1076
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1114
+ msg.role === "assistant" && parsed.blocks.length > 0 && !(analyzedData == null ? void 0 : analyzedData.messageId) && (!isStreaming || msg.id !== ((_a2 = messages[messages.length - 1]) == null ? void 0 : _a2.id)) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-msg-actions", children: [
1115
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1077
1116
  "button",
1078
1117
  {
1079
1118
  onClick: () => handleEdit(parsed.blocks, parsed.metaKeywords, msg.id),
1080
- className: "flex items-center gap-2 px-4 py-2 border border-gray-300 rounded-lg text-sm font-medium text-gray-700 hover:bg-gray-50 transition-colors",
1119
+ className: "cnfy-btn-edit",
1081
1120
  children: [
1082
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Edit3, { size: 16 }),
1121
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Edit3, { size: 16 }),
1083
1122
  "Edit"
1084
1123
  ]
1085
1124
  }
1086
1125
  ),
1087
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1126
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1088
1127
  "button",
1089
1128
  {
1090
1129
  onClick: () => handlePost(msg.content, parsed.metaKeywords),
1091
- className: "flex items-center gap-2 px-4 py-2 rounded-lg text-sm font-medium text-white hover:bg-emerald-700 transition-colors",
1130
+ className: "cnfy-btn-post",
1092
1131
  style: { backgroundColor: primaryColor, color: "#fff" },
1093
1132
  children: [
1094
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Send, { size: 16 }),
1133
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Send, { size: 16 }),
1095
1134
  "Post"
1096
1135
  ]
1097
1136
  }
@@ -1100,34 +1139,34 @@ function ChatWindow({
1100
1139
  ] })
1101
1140
  ] }, msg.id);
1102
1141
  }),
1103
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: bottomRef })
1142
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: bottomRef })
1104
1143
  ] }) }),
1105
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "shrink-0 bg-white px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "max-w-3xl mx-auto relative flex gap-2 items-end", children: [
1106
- !showNewsPanel && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: dropdownRef, className: "absolute left-3 top-1/2 -translate-y-1/2 z-10", children: [
1107
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1144
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-input-area", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-input-inner", children: [
1145
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { ref: dropdownRef, className: "cnfy-news-pulse-wrap", children: [
1146
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1108
1147
  "button",
1109
1148
  {
1110
1149
  onClick: handleOpenNewsDropdown,
1111
- className: "flex h-8 w-8 items-center justify-center rounded-full bg-gradient-to-r from-purple-500 to-pink-500 text-white hover:from-purple-600 hover:to-pink-600 transition-all animate-pulse hover:animate-none",
1150
+ className: "cnfy-news-pulse-btn cnfy-animate-pulse",
1112
1151
  title: "Select from trending news",
1113
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.Zap, { size: 16 })
1152
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Zap, { size: 16 })
1114
1153
  }
1115
1154
  ),
1116
- showNewsDropdown && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "absolute bottom-full left-0 mb-2 w-[600px] bg-white border border-gray-200 rounded-lg shadow-xl max-h-[600px] overflow-hidden", children: [
1117
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between px-3 py-2 border-b border-gray-100", style: { backgroundColor: primaryColor, color: "#fff" }, children: [
1118
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-sm font-medium text-white", children: "Select News" }),
1119
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1155
+ showNewsDropdown && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-news-dropdown", children: [
1156
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-news-dropdown-header", style: { backgroundColor: primaryColor, color: "#fff" }, children: [
1157
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "cnfy-news-dropdown-title", children: "Select News" }),
1158
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1120
1159
  "button",
1121
1160
  {
1122
1161
  onClick: () => setShowNewsDropdown(false),
1123
- className: "p-1 hover:bg-gray-200 rounded transition",
1162
+ className: "cnfy-news-dropdown-close",
1124
1163
  style: { backgroundColor: primaryColor, color: "#fff" },
1125
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.X, { size: 14, className: "text-white" })
1164
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.X, { size: 14 })
1126
1165
  }
1127
1166
  )
1128
1167
  ] }),
1129
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "px-3 py-2 border-b border-gray-100 flex items-center gap-2", children: [
1130
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex-1 min-w-[180px]", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1168
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-news-dropdown-source", children: [
1169
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-news-dropdown-select-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1131
1170
  import_react_select.default,
1132
1171
  {
1133
1172
  options: [
@@ -1173,36 +1212,36 @@ function ChatWindow({
1173
1212
  }
1174
1213
  }
1175
1214
  ) }),
1176
- selectedSource && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1215
+ selectedSource && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1177
1216
  "button",
1178
1217
  {
1179
1218
  onClick: handleScrape,
1180
1219
  disabled: scraping,
1181
- className: "flex items-center gap-1.5 px-3 py-2 bg-emerald-600 text-white rounded-lg text-sm font-medium hover:bg-emerald-700 transition disabled:opacity-50",
1220
+ className: "cnfy-scrape-btn",
1182
1221
  title: "Fetch latest news",
1183
1222
  children: [
1184
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.RefreshCcw, { size: 14, className: scraping ? "animate-spin" : "" }),
1223
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.RefreshCcw, { size: 14, className: scraping ? "cnfy-animate-spin" : "" }),
1185
1224
  scraping ? "Scraping..." : "Scrape"
1186
1225
  ]
1187
1226
  }
1188
1227
  ),
1189
- !selectedSource && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1228
+ !selectedSource && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1190
1229
  "button",
1191
1230
  {
1192
1231
  onClick: () => fetchNews(null),
1193
1232
  disabled: loadingNews,
1194
- className: "flex items-center gap-1 px-3 py-2 text-sm text-gray-600 hover:text-gray-900 border border-gray-200 rounded-lg transition",
1233
+ className: "cnfy-refresh-btn",
1195
1234
  children: [
1196
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.RefreshCcw, { size: 14, className: loadingNews ? "animate-spin" : "" }),
1235
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.RefreshCcw, { size: 14, className: loadingNews ? "cnfy-animate-spin" : "" }),
1197
1236
  "Refresh"
1198
1237
  ]
1199
1238
  }
1200
1239
  )
1201
1240
  ] }),
1202
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "overflow-y-auto max-h-[320px]", children: loadingNews ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-4 text-center text-sm text-gray-500", children: "Loading news..." }) : trendingNews.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "p-4 text-center text-sm text-gray-500", children: [
1203
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: "No news found." }),
1204
- selectedSource && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mt-1 text-xs", children: 'Click "Scrape" to fetch latest news.' })
1205
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1241
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-news-dropdown-list", children: loadingNews ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "cnfy-news-dropdown-msg", children: "Loading news..." }) : trendingNews.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cnfy-news-dropdown-msg", children: [
1242
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: "No news found." }),
1243
+ selectedSource && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "cnfy-news-dropdown-hint", children: 'Click "Scrape" to fetch latest news.' })
1244
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1206
1245
  NewsList,
1207
1246
  {
1208
1247
  news: trendingNews.slice(0, 10),
@@ -1215,7 +1254,7 @@ function ChatWindow({
1215
1254
  ) })
1216
1255
  ] })
1217
1256
  ] }),
1218
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1257
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1219
1258
  "textarea",
1220
1259
  {
1221
1260
  ref: textareaRef,
@@ -1229,21 +1268,21 @@ function ChatWindow({
1229
1268
  },
1230
1269
  rows: 1,
1231
1270
  placeholder: "Ask AI something\u2026",
1232
- className: `flex-1 resize-none overflow-hidden border border-gray-300 ${!showNewsPanel ? "!pl-14" : "!pl-5"} !pr-[50px] input_box_textarea`,
1271
+ className: `cnfy-chat-textarea ${!showNewsPanel ? "cnfy-chat-textarea--with-pulse" : ""}`,
1233
1272
  style: { maxHeight: "200px", overflowY: input.split("\n").length > 6 ? "auto" : "hidden" }
1234
1273
  }
1235
1274
  ),
1236
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1275
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1237
1276
  "button",
1238
1277
  {
1239
1278
  onClick: handleSend,
1240
- className: "flex h-10 w-10 absolute right-[10px] top-[5px] items-center justify-center rounded-full bg-emerald-600 text-white",
1279
+ className: "cnfy-send-btn",
1241
1280
  style: { backgroundColor: primaryColor, color: "#fff" },
1242
- children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react4.SendHorizontal, { size: 18 })
1281
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.SendHorizontal, { size: 18 })
1243
1282
  }
1244
1283
  )
1245
1284
  ] }) }),
1246
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1285
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1247
1286
  EditModal,
1248
1287
  {
1249
1288
  isOpen: editModal.isOpen,
@@ -1258,334 +1297,611 @@ function ChatWindow({
1258
1297
  }
1259
1298
 
1260
1299
  // components/chatbot/UserMenu.tsx
1261
- var import_react7 = require("react");
1262
1300
  var import_lucide_react5 = require("lucide-react");
1263
- var import_react_hot_toast = __toESM(require("react-hot-toast"));
1264
-
1265
- // services/auth.service.ts
1266
- var logoutUser = async () => {
1267
- const { data } = await api_default.post("/auth/logout");
1268
- return data;
1269
- };
1270
-
1271
- // components/chatbot/UserMenu.tsx
1272
- var import_jsx_runtime7 = require("react/jsx-runtime");
1301
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1273
1302
  function UserMenu({
1274
- onNavigate,
1275
- onLogout
1276
- }) {
1277
- const [open, setOpen] = (0, import_react7.useState)(false);
1278
- const ref = (0, import_react7.useRef)(null);
1279
- (0, import_react7.useEffect)(() => {
1280
- const handler = (e) => {
1281
- if (ref.current && !ref.current.contains(e.target)) {
1282
- setOpen(false);
1283
- }
1284
- };
1285
- document.addEventListener("mousedown", handler);
1286
- return () => document.removeEventListener("mousedown", handler);
1287
- }, []);
1288
- function go(path) {
1289
- setOpen(false);
1290
- onNavigate == null ? void 0 : onNavigate(path);
1291
- }
1292
- async function logout() {
1293
- setOpen(false);
1294
- if (onLogout) {
1295
- onLogout();
1296
- return;
1297
- }
1298
- try {
1299
- await logoutUser();
1300
- import_react_hot_toast.default.success("Logged out successfully");
1301
- onNavigate == null ? void 0 : onNavigate("/login");
1302
- } catch (err) {
1303
- import_react_hot_toast.default.error(err || "Logout failed");
1304
- }
1305
- }
1306
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { ref, className: "relative", children: [
1307
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1308
- "button",
1309
- {
1310
- onClick: () => setOpen((v) => !v),
1311
- className: "p-2 rounded-full hover:bg-gray-100 transition",
1312
- "aria-label": "Settings",
1313
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react5.Settings, { size: 20, className: "text-gray-600" })
1314
- }
1315
- ),
1316
- open && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "absolute right-0 top-full mb-2 w-52 bg-white border border-gray-200 rounded-lg shadow-lg z-50", children: [
1317
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuItem, { icon: import_lucide_react5.User, label: "Account", onClick: () => go("/dashboard/account") }),
1318
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuItem, { icon: import_lucide_react5.Settings, label: "Preferences", onClick: () => go("/dashboard/preferences") }),
1319
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuItem, { icon: import_lucide_react5.Palette, label: "Appearance", onClick: () => go("/dashboard/appearance") }),
1320
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuItem, { icon: import_lucide_react5.HelpCircle, label: "Settings", onClick: () => go("/dashboard/settings") }),
1321
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MenuItem, { icon: import_lucide_react5.HelpCircle, label: "Help & Support", onClick: () => go("/dashboard/help") }),
1322
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "border-t border-gray-300 my-1" }),
1323
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1324
- MenuItem,
1325
- {
1326
- icon: import_lucide_react5.LogOut,
1327
- label: "Logout",
1328
- danger: true,
1329
- onClick: logout
1330
- }
1331
- )
1332
- ] })
1333
- ] });
1334
- }
1335
- function MenuItem({
1336
- icon: Icon,
1337
- label,
1338
- onClick,
1339
- danger = false
1303
+ onOpenPreferences
1340
1304
  }) {
1341
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1305
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "cnfy-user-menu", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1342
1306
  "button",
1343
1307
  {
1344
- onClick,
1345
- className: `w-full flex items-center gap-2 px-4 py-2 text-sm transition ${danger ? "text-red-600 hover:bg-red-50" : "text-gray-700 hover:bg-gray-100"}`,
1346
- children: [
1347
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(Icon, { size: 16 }),
1348
- label
1349
- ]
1308
+ onClick: () => onOpenPreferences == null ? void 0 : onOpenPreferences(),
1309
+ className: "cnfy-user-menu-trigger",
1310
+ "aria-label": "Settings",
1311
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react5.Settings, { size: 20, className: "cnfy-user-menu-trigger-icon" })
1350
1312
  }
1351
- );
1313
+ ) });
1352
1314
  }
1353
1315
 
1354
1316
  // components/chatbot/headerBar.tsx
1355
- var import_jsx_runtime8 = require("react/jsx-runtime");
1317
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1356
1318
  function HeaderBar({
1357
- onNavigate,
1358
- onLogout
1319
+ onOpenPreferences
1359
1320
  }) {
1360
1321
  const { primaryColor, botName, logoUrl } = useTheme();
1361
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("header", { className: "sticky top-0 z-40 bg-white border-b border-gray-200", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mx-auto flex h-14 items-center justify-between px-4", children: [
1362
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-3 cursor-pointer", onClick: () => onNavigate == null ? void 0 : onNavigate("/"), children: [
1363
- logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("img", { src: logoUrl, alt: "Logo", className: "h-8 w-8 rounded-md object-cover" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1322
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("header", { className: "cnfy-header", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "cnfy-header-inner", children: [
1323
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "cnfy-header-left", children: [
1324
+ logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: logoUrl, alt: "Logo", className: "cnfy-header-logo-img" }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1364
1325
  "div",
1365
1326
  {
1366
- className: "h-8 w-8 rounded-md text-white flex items-center justify-center font-bold text-sm",
1327
+ className: "cnfy-header-logo-fallback",
1367
1328
  style: { backgroundColor: primaryColor },
1368
1329
  children: botName.charAt(0).toUpperCase()
1369
1330
  }
1370
1331
  ),
1371
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "font-semibold text-gray-900 text-base", children: botName.toUpperCase() })
1332
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "cnfy-header-brand", children: botName.toUpperCase() })
1372
1333
  ] }),
1373
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(UserMenu, { onNavigate, onLogout }) })
1334
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "cnfy-header-right", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(UserMenu, { onOpenPreferences }) })
1374
1335
  ] }) });
1375
1336
  }
1376
1337
 
1377
- // components/news/TrendingNews.tsx
1378
- var import_react8 = require("react");
1379
- var import_react_hot_toast2 = __toESM(require("react-hot-toast"));
1380
- var import_jsx_runtime9 = require("react/jsx-runtime");
1381
- function TrendingNews({
1382
- onRecreate,
1383
- selectedSource,
1384
- refreshKey,
1385
- news: externalNews,
1386
- isLoading: externalLoading
1338
+ // components/ui/Drawer.tsx
1339
+ var import_react7 = require("react");
1340
+ var import_lucide_react6 = require("lucide-react");
1341
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1342
+ function Drawer({
1343
+ open,
1344
+ onClose,
1345
+ title,
1346
+ children
1387
1347
  }) {
1388
- const [news, setNews] = (0, import_react8.useState)([]);
1389
- const [loading, setLoading] = (0, import_react8.useState)(false);
1390
- const displayNews = externalNews !== void 0 ? externalNews : news;
1391
- const isLoading = externalLoading !== void 0 ? externalLoading : loading;
1392
- const fetchNews = (0, import_react8.useCallback)(async () => {
1393
- if (externalNews !== void 0) {
1394
- return;
1395
- }
1396
- setLoading(true);
1397
- try {
1398
- let data;
1399
- if (selectedSource) {
1400
- data = await getNewsBySource(selectedSource);
1401
- } else {
1402
- data = await getTrendingNews();
1403
- }
1404
- setNews(data || []);
1405
- } catch (e) {
1406
- import_react_hot_toast2.default.error("Failed to load news");
1407
- } finally {
1408
- setLoading(false);
1409
- }
1410
- }, [selectedSource, externalNews]);
1411
- (0, import_react8.useEffect)(() => {
1412
- fetchNews();
1413
- }, [fetchNews, refreshKey]);
1414
- function handleView(item) {
1415
- window.open(item.sourceUrl || item.link, "_blank");
1416
- }
1417
- if (isLoading) {
1418
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "p-4 text-sm text-gray-500", children: "Loading news..." });
1419
- }
1420
- if (!displayNews || displayNews.length === 0) {
1421
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "p-4 text-sm text-gray-500 text-center", children: [
1422
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { children: "No news found for this source." }),
1423
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("p", { className: "mt-1 text-xs", children: 'Click "Scrape" to fetch latest news.' })
1424
- ] });
1425
- }
1426
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1427
- NewsList,
1428
- {
1429
- news: displayNews,
1430
- onView: handleView,
1431
- onRecreate
1348
+ (0, import_react7.useEffect)(() => {
1349
+ if (open) {
1350
+ document.body.style.overflow = "hidden";
1351
+ } else {
1352
+ document.body.style.overflow = "";
1432
1353
  }
1433
- );
1354
+ return () => {
1355
+ document.body.style.overflow = "";
1356
+ };
1357
+ }, [open]);
1358
+ if (!open) return null;
1359
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "cnfy-drawer-overlay", children: [
1360
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "cnfy-drawer-backdrop", onClick: onClose }),
1361
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "cnfy-drawer-panel", children: [
1362
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "cnfy-drawer-header", children: [
1363
+ title && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("h2", { className: "cnfy-drawer-title", children: title }),
1364
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("button", { onClick: onClose, className: "cnfy-drawer-close-btn", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react6.X, { size: 20 }) })
1365
+ ] }),
1366
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "cnfy-drawer-body", children })
1367
+ ] })
1368
+ ] });
1434
1369
  }
1435
1370
 
1436
- // components/news/SourceSelector.tsx
1371
+ // components/preferences/Preferences.tsx
1437
1372
  var import_react9 = require("react");
1438
- var import_lucide_react6 = require("lucide-react");
1439
- var import_react_select2 = __toESM(require("react-select"));
1440
- var import_react_hot_toast3 = __toESM(require("react-hot-toast"));
1373
+ var import_react_hot_toast = __toESM(require("react-hot-toast"));
1374
+
1375
+ // services/settings.service.ts
1376
+ var triggerScrape = async ({
1377
+ state,
1378
+ cities
1379
+ }) => {
1380
+ const { data } = await api_default.post("/scrape/trigger", {
1381
+ state,
1382
+ cities
1383
+ });
1384
+ return data;
1385
+ };
1386
+ var getScrapeStatus = async () => {
1387
+ const { data } = await api_default.get("/scrape/status");
1388
+ return data.data;
1389
+ };
1390
+
1391
+ // components/ClientSelect.tsx
1392
+ var import_react8 = require("react");
1393
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1394
+ var ReactSelect = null;
1395
+ var ClientSelect = (props) => {
1396
+ const [mounted, setMounted] = (0, import_react8.useState)(false);
1397
+ (0, import_react8.useEffect)(() => {
1398
+ setMounted(true);
1399
+ import("react-select").then((mod) => {
1400
+ ReactSelect = mod.default;
1401
+ });
1402
+ }, []);
1403
+ if (!mounted || !ReactSelect) return null;
1404
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(ReactSelect, __spreadValues({}, props));
1405
+ };
1406
+ var ClientSelect_default = ClientSelect;
1407
+
1408
+ // components/preferences/Preferences.tsx
1441
1409
  var import_jsx_runtime10 = require("react/jsx-runtime");
1442
- var ALL_SOURCES_VALUE = "__all__";
1443
- function SourceSelector({
1444
- selectedSource,
1445
- onSourceChange,
1446
- onScrapeComplete,
1447
- onNewsLoaded,
1448
- onLoadingChange
1449
- }) {
1450
- const [sources, setSources] = (0, import_react9.useState)([]);
1451
- const [loading, setLoading] = (0, import_react9.useState)(true);
1410
+ var STATE_OPTIONS = [
1411
+ { value: "Uttar Pradesh", label: "Uttar Pradesh" }
1412
+ ];
1413
+ var CITY_OPTIONS = [
1414
+ "Agra",
1415
+ "Aligarh",
1416
+ "Ayodhya",
1417
+ "Bareilly",
1418
+ "Bijnor",
1419
+ "Bulandshahr",
1420
+ "Etawah",
1421
+ "Firozabad",
1422
+ "Ghaziabad",
1423
+ "Gorakhpur",
1424
+ "Jhansi",
1425
+ "Kanpur",
1426
+ "Lucknow",
1427
+ "Mathura",
1428
+ "Meerut",
1429
+ "Moradabad",
1430
+ "Muzaffarnagar",
1431
+ "Noida",
1432
+ "Prayagraj",
1433
+ "Rampur",
1434
+ "Saharanpur",
1435
+ "Sitapur",
1436
+ "Unnao",
1437
+ "Varanasi"
1438
+ ].map((city) => ({ value: city, label: city }));
1439
+ var LANGUAGE_OPTIONS = [
1440
+ { value: "en", label: "English" },
1441
+ { value: "hi", label: "Hindi" }
1442
+ ];
1443
+ var TONE_OPTIONS = [
1444
+ { value: "formal", label: "Formal" },
1445
+ { value: "casual", label: "Casual" },
1446
+ { value: "engaging", label: "Engaging" },
1447
+ { value: "professional", label: "Professional" }
1448
+ ];
1449
+ var STYLE_OPTIONS = [
1450
+ { value: "news", label: "News Article" },
1451
+ { value: "blog", label: "Blog Post" },
1452
+ { value: "editorial", label: "Editorial" },
1453
+ { value: "summary", label: "Summary" }
1454
+ ];
1455
+ var WORD_COUNT_OPTIONS = [
1456
+ { value: "short", label: "Short (~300 words)" },
1457
+ { value: "medium", label: "Medium (~600 words)" },
1458
+ { value: "long", label: "Long (~1000+ words)" }
1459
+ ];
1460
+ function PreferencesPage() {
1461
+ var _a, _b, _c;
1462
+ const { preferences, loading, refreshPreferences, updatePreferences } = usePreferences();
1463
+ const primaryColor = ((_a = preferences == null ? void 0 : preferences.chatbot) == null ? void 0 : _a.primaryColor) || "#10b981";
1464
+ const [botName, setBotName] = (0, import_react9.useState)("");
1465
+ const [logo, setLogo] = (0, import_react9.useState)(null);
1466
+ const [logoUrl, setLogoUrl] = (0, import_react9.useState)(null);
1467
+ const [state, setState] = (0, import_react9.useState)(null);
1468
+ const [cities, setCities] = (0, import_react9.useState)([]);
1469
+ const [language, setLanguage] = (0, import_react9.useState)(null);
1470
+ const [tone, setTone] = (0, import_react9.useState)(null);
1471
+ const [style, setStyle] = (0, import_react9.useState)(null);
1472
+ const [wordCount, setWordCount] = (0, import_react9.useState)(null);
1473
+ const [includeQuotes, setIncludeQuotes] = (0, import_react9.useState)(true);
1474
+ const [includeFAQ, setIncludeFAQ] = (0, import_react9.useState)(false);
1475
+ const [targetAudience, setTargetAudience] = (0, import_react9.useState)("");
1476
+ const [saving, setSaving] = (0, import_react9.useState)(false);
1477
+ const [success, setSuccess] = (0, import_react9.useState)(false);
1452
1478
  const [scraping, setScraping] = (0, import_react9.useState)(false);
1453
- const [fetchingNews, setFetchingNews] = (0, import_react9.useState)(true);
1454
- const { primaryColor } = useTheme();
1455
- (0, import_react9.useEffect)(() => {
1456
- onLoadingChange == null ? void 0 : onLoadingChange(fetchingNews);
1457
- }, [fetchingNews, onLoadingChange]);
1479
+ const [scrapeStatus, setScrapeStatus] = (0, import_react9.useState)(null);
1480
+ const [loadingStatus, setLoadingStatus] = (0, import_react9.useState)(true);
1481
+ const [originalValues, setOriginalValues] = (0, import_react9.useState)({
1482
+ botName: "",
1483
+ state: void 0,
1484
+ cities: [],
1485
+ language: void 0,
1486
+ tone: void 0,
1487
+ style: void 0,
1488
+ wordCount: void 0,
1489
+ includeQuotes: true,
1490
+ includeFAQ: false,
1491
+ targetAudience: ""
1492
+ });
1458
1493
  (0, import_react9.useEffect)(() => {
1459
- const fetchSources = async () => {
1494
+ const fetchScrapeStatus = async () => {
1460
1495
  try {
1461
- const data = await getNewsSources();
1462
- setSources(data || []);
1463
- } catch (e) {
1464
- import_react_hot_toast3.default.error("Failed to load news sources");
1496
+ const data = await getScrapeStatus();
1497
+ setScrapeStatus(data);
1498
+ } catch (error) {
1499
+ console.log("Failed to fetch scrape status:", error);
1465
1500
  } finally {
1466
- setLoading(false);
1501
+ setLoadingStatus(false);
1467
1502
  }
1468
1503
  };
1469
- fetchSources();
1504
+ fetchScrapeStatus();
1470
1505
  }, []);
1471
- const fetchNews = (0, import_react9.useCallback)(async (sourceId) => {
1472
- setFetchingNews(true);
1506
+ const handleScrape = async () => {
1507
+ var _a2, _b2;
1508
+ setScraping(true);
1473
1509
  try {
1474
- let news;
1475
- if (sourceId) {
1476
- news = await getNewsBySource(sourceId);
1477
- } else {
1478
- news = await getTrendingNews();
1479
- }
1480
- onNewsLoaded == null ? void 0 : onNewsLoaded(news || []);
1481
- } catch (err) {
1482
- console.error("Failed to fetch news:", err);
1510
+ await triggerScrape({
1511
+ state: (_a2 = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _a2.state,
1512
+ cities: (_b2 = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _b2.cities
1513
+ });
1514
+ import_react_hot_toast.default.success("News scraping started successfully!");
1515
+ setTimeout(async () => {
1516
+ try {
1517
+ const data = await getScrapeStatus();
1518
+ setScrapeStatus(data);
1519
+ } catch (e) {
1520
+ console.log("Failed to refresh scrape status:", e);
1521
+ }
1522
+ }, 2e3);
1523
+ } catch (error) {
1524
+ console.error(error);
1525
+ import_react_hot_toast.default.error("Failed to trigger news scraping");
1483
1526
  } finally {
1484
- setFetchingNews(false);
1527
+ setScraping(false);
1485
1528
  }
1486
- }, []);
1487
- (0, import_react9.useEffect)(() => {
1488
- fetchNews(selectedSource);
1489
- }, [selectedSource, fetchNews]);
1490
- const handleSourceSelect = (option) => {
1491
- var _a;
1492
- const value = (option == null ? void 0 : option.value) === ALL_SOURCES_VALUE ? null : (_a = option == null ? void 0 : option.value) != null ? _a : null;
1493
- onSourceChange(value);
1494
1529
  };
1495
- const handleScrape = async () => {
1496
- if (!selectedSource) {
1497
- import_react_hot_toast3.default.error("Please select a source first");
1530
+ (0, import_react9.useEffect)(() => {
1531
+ var _a2, _b2, _c2, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m;
1532
+ if (preferences) {
1533
+ const name = ((_a2 = preferences.chatbot) == null ? void 0 : _a2.name) || "";
1534
+ const pState = (_b2 = preferences.localization) == null ? void 0 : _b2.state;
1535
+ const pCities = ((_c2 = preferences.localization) == null ? void 0 : _c2.cities) || [];
1536
+ const pLanguage = (_d = preferences.localization) == null ? void 0 : _d.language;
1537
+ setBotName(name);
1538
+ if ((_e = preferences.chatbot) == null ? void 0 : _e.logoUrl) setLogoUrl(preferences.chatbot.logoUrl);
1539
+ if (pState) {
1540
+ setState({ value: pState, label: pState });
1541
+ }
1542
+ if (Array.isArray(pCities)) {
1543
+ setCities(pCities.map((city) => ({ value: city, label: city })));
1544
+ }
1545
+ if (pLanguage) {
1546
+ const langOption = LANGUAGE_OPTIONS.find((opt) => opt.value === pLanguage);
1547
+ setLanguage(langOption || null);
1548
+ }
1549
+ const pTone = (_f = preferences.content) == null ? void 0 : _f.tone;
1550
+ const pStyle = (_g = preferences.content) == null ? void 0 : _g.style;
1551
+ const pWordCount = (_h = preferences.content) == null ? void 0 : _h.wordCount;
1552
+ const pIncludeQuotes = (_j = (_i = preferences.content) == null ? void 0 : _i.includeQuotes) != null ? _j : true;
1553
+ const pIncludeFAQ = (_l = (_k = preferences.content) == null ? void 0 : _k.includeFAQ) != null ? _l : false;
1554
+ const pTargetAudience = ((_m = preferences.content) == null ? void 0 : _m.targetAudience) || "";
1555
+ if (pTone) {
1556
+ const toneOption = TONE_OPTIONS.find((opt) => opt.value === pTone);
1557
+ setTone(toneOption || null);
1558
+ }
1559
+ if (pStyle) {
1560
+ const styleOption = STYLE_OPTIONS.find((opt) => opt.value === pStyle);
1561
+ setStyle(styleOption || null);
1562
+ }
1563
+ if (pWordCount) {
1564
+ const wordCountOption = WORD_COUNT_OPTIONS.find((opt) => opt.value === pWordCount);
1565
+ setWordCount(wordCountOption || null);
1566
+ }
1567
+ setIncludeQuotes(pIncludeQuotes);
1568
+ setIncludeFAQ(pIncludeFAQ);
1569
+ setTargetAudience(pTargetAudience);
1570
+ setOriginalValues({
1571
+ botName: name,
1572
+ state: pState,
1573
+ cities: pCities,
1574
+ language: pLanguage,
1575
+ tone: pTone,
1576
+ style: pStyle,
1577
+ wordCount: pWordCount,
1578
+ includeQuotes: pIncludeQuotes,
1579
+ includeFAQ: pIncludeFAQ,
1580
+ targetAudience: pTargetAudience
1581
+ });
1582
+ }
1583
+ }, [preferences]);
1584
+ const handleSave = async () => {
1585
+ if (!botName) {
1586
+ import_react_hot_toast.default.error("Chatbot name is required");
1498
1587
  return;
1499
1588
  }
1500
- setScraping(true);
1589
+ setSaving(true);
1590
+ setSuccess(false);
1501
1591
  try {
1502
- await scrapeNewsSource(selectedSource);
1503
- import_react_hot_toast3.default.success("News scraped successfully!");
1504
- onScrapeComplete == null ? void 0 : onScrapeComplete();
1505
- const news = await getNewsBySource(selectedSource);
1506
- onNewsLoaded == null ? void 0 : onNewsLoaded(news || []);
1507
- } catch (err) {
1508
- import_react_hot_toast3.default.error(err || "Failed to scrape news");
1592
+ const payload = {};
1593
+ if (botName !== originalValues.botName) {
1594
+ payload.botName = botName;
1595
+ }
1596
+ if (logo) {
1597
+ payload.logo = logo;
1598
+ }
1599
+ const currentState = state == null ? void 0 : state.value;
1600
+ if (currentState !== originalValues.state) {
1601
+ payload.state = currentState;
1602
+ }
1603
+ const currentCities = cities.map((c) => c.value);
1604
+ const citiesChanged = currentCities.length !== originalValues.cities.length || currentCities.some((city, index) => city !== originalValues.cities[index]);
1605
+ if (citiesChanged) {
1606
+ payload.cities = currentCities;
1607
+ }
1608
+ const currentLanguage = language == null ? void 0 : language.value;
1609
+ if (currentLanguage !== originalValues.language) {
1610
+ payload.language = currentLanguage;
1611
+ }
1612
+ const currentTone = tone == null ? void 0 : tone.value;
1613
+ if (currentTone !== originalValues.tone) {
1614
+ payload.tone = currentTone;
1615
+ }
1616
+ const currentStyle = style == null ? void 0 : style.value;
1617
+ if (currentStyle !== originalValues.style) {
1618
+ payload.style = currentStyle;
1619
+ }
1620
+ const currentWordCount = wordCount == null ? void 0 : wordCount.value;
1621
+ if (currentWordCount !== originalValues.wordCount) {
1622
+ payload.wordCount = currentWordCount;
1623
+ }
1624
+ if (includeQuotes !== originalValues.includeQuotes) {
1625
+ payload.includeQuotes = includeQuotes;
1626
+ }
1627
+ if (includeFAQ !== originalValues.includeFAQ) {
1628
+ payload.includeFAQ = includeFAQ;
1629
+ }
1630
+ if (targetAudience !== originalValues.targetAudience) {
1631
+ payload.targetAudience = targetAudience;
1632
+ }
1633
+ if (Object.keys(payload).length === 0) {
1634
+ import_react_hot_toast.default.error("No changes to save");
1635
+ setSaving(false);
1636
+ return;
1637
+ }
1638
+ const updatedPreferences = await savePreferencesApi(payload);
1639
+ if (updatedPreferences) {
1640
+ updatePreferences(updatedPreferences);
1641
+ } else {
1642
+ await refreshPreferences();
1643
+ }
1644
+ setSuccess(true);
1645
+ setLogo(null);
1646
+ import_react_hot_toast.default.success("Preferences saved successfully!");
1647
+ } catch (error) {
1648
+ console.error(error);
1649
+ import_react_hot_toast.default.error("Failed to save preferences");
1509
1650
  } finally {
1510
- setScraping(false);
1651
+ setSaving(false);
1511
1652
  }
1512
1653
  };
1513
- const options = [
1514
- { value: ALL_SOURCES_VALUE, label: "All Sources (Trending)" },
1515
- ...sources.map((source) => ({
1516
- value: source.id,
1517
- label: source.name
1518
- }))
1519
- ];
1520
- const selectedOption = options.find(
1521
- (opt) => selectedSource === null ? opt.value === ALL_SOURCES_VALUE : opt.value === selectedSource
1522
- ) || options[0];
1523
- return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "px-3 py-2 border-b border-gray-100 flex items-center gap-2", children: [
1524
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "flex-1 min-w-[180px]", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1525
- import_react_select2.default,
1526
- {
1527
- options,
1528
- value: selectedOption,
1529
- onChange: handleSourceSelect,
1530
- isLoading: loading,
1531
- isDisabled: loading,
1532
- placeholder: "Select source...",
1533
- classNamePrefix: "react-select",
1534
- menuPlacement: "bottom",
1535
- menuPosition: "fixed",
1536
- menuShouldScrollIntoView: false,
1537
- maxMenuHeight: 220,
1538
- menuPortalTarget: typeof window !== "undefined" ? document.body : null,
1539
- styles: {
1540
- container: (base) => __spreadProps(__spreadValues({}, base), {
1541
- width: "100%"
1542
- }),
1543
- control: (base) => __spreadProps(__spreadValues({}, base), {
1544
- minHeight: "38px",
1545
- borderColor: "#e5e7eb",
1546
- boxShadow: "none",
1547
- width: "100%"
1548
- }),
1549
- menu: (base) => __spreadProps(__spreadValues({}, base), {
1550
- width: "100%",
1551
- zIndex: 999999
1552
- }),
1553
- menuPortal: (base) => __spreadProps(__spreadValues({}, base), {
1554
- zIndex: 999999
1555
- }),
1556
- option: (base, state) => __spreadProps(__spreadValues({}, base), {
1557
- backgroundColor: state.isSelected ? primaryColor : state.isFocused ? "#f3f4f6" : "white",
1558
- color: state.isSelected ? "white" : "#374151",
1559
- cursor: "pointer"
1560
- })
1654
+ if (loading) {
1655
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "cnfy-dash-page", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-page-subtitle", children: "Loading settings..." }) });
1656
+ }
1657
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-page", children: [
1658
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
1659
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title", children: "Chatbot Settings" }),
1660
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1661
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Chatbot Name" }),
1662
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1663
+ "input",
1664
+ {
1665
+ value: botName,
1666
+ onChange: (e) => setBotName(e.target.value),
1667
+ className: "cnfy-dash-input",
1668
+ placeholder: "Contenify AI"
1669
+ }
1670
+ )
1671
+ ] }),
1672
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1673
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Chatbot Logo" }),
1674
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-logo-upload", children: [
1675
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "cnfy-logo-preview", children: logo ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1676
+ "img",
1677
+ {
1678
+ src: URL.createObjectURL(logo),
1679
+ alt: "Logo preview",
1680
+ className: "cnfy-logo-img"
1681
+ }
1682
+ ) : logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1683
+ "img",
1684
+ {
1685
+ src: logoUrl,
1686
+ alt: "Current logo",
1687
+ className: "cnfy-logo-img"
1688
+ }
1689
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "cnfy-logo-placeholder", children: "No logo" }) }),
1690
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1691
+ "input",
1692
+ {
1693
+ type: "file",
1694
+ accept: "image/*",
1695
+ onChange: (e) => {
1696
+ var _a2;
1697
+ return setLogo(((_a2 = e.target.files) == null ? void 0 : _a2[0]) || null);
1698
+ },
1699
+ className: "cnfy-file-input"
1700
+ }
1701
+ )
1702
+ ] })
1703
+ ] })
1704
+ ] }),
1705
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
1706
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title", children: "Localization Settings" }),
1707
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1708
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "State" }),
1709
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1710
+ ClientSelect_default,
1711
+ {
1712
+ options: STATE_OPTIONS,
1713
+ value: state,
1714
+ onChange: (option) => setState(option),
1715
+ placeholder: "Select state"
1716
+ }
1717
+ )
1718
+ ] }),
1719
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1720
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Cities" }),
1721
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1722
+ ClientSelect_default,
1723
+ {
1724
+ isMulti: true,
1725
+ options: CITY_OPTIONS,
1726
+ value: cities,
1727
+ onChange: (options) => setCities(options),
1728
+ placeholder: "Select cities",
1729
+ isDisabled: !state
1730
+ }
1731
+ )
1732
+ ] }),
1733
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1734
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Language" }),
1735
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1736
+ ClientSelect_default,
1737
+ {
1738
+ options: LANGUAGE_OPTIONS,
1739
+ value: language,
1740
+ onChange: (option) => setLanguage(option),
1741
+ placeholder: "Select language"
1742
+ }
1743
+ )
1744
+ ] })
1745
+ ] }),
1746
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
1747
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title", children: "Content Generation Settings" }),
1748
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1749
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Tone" }),
1750
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1751
+ ClientSelect_default,
1752
+ {
1753
+ options: TONE_OPTIONS,
1754
+ value: tone,
1755
+ onChange: (option) => setTone(option),
1756
+ placeholder: "Select tone"
1757
+ }
1758
+ ),
1759
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "The writing tone for generated content" })
1760
+ ] }),
1761
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1762
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Style" }),
1763
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1764
+ ClientSelect_default,
1765
+ {
1766
+ options: STYLE_OPTIONS,
1767
+ value: style,
1768
+ onChange: (option) => setStyle(option),
1769
+ placeholder: "Select style"
1770
+ }
1771
+ ),
1772
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "The format/style of generated articles" })
1773
+ ] }),
1774
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1775
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Word Count" }),
1776
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1777
+ ClientSelect_default,
1778
+ {
1779
+ options: WORD_COUNT_OPTIONS,
1780
+ value: wordCount,
1781
+ onChange: (option) => setWordCount(option),
1782
+ placeholder: "Select word count"
1783
+ }
1784
+ ),
1785
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "Target length for generated content" })
1786
+ ] }),
1787
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-field", children: [
1788
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("label", { className: "cnfy-dash-label", children: "Target Audience" }),
1789
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1790
+ "input",
1791
+ {
1792
+ value: targetAudience,
1793
+ onChange: (e) => setTargetAudience(e.target.value),
1794
+ className: "cnfy-dash-input",
1795
+ placeholder: "e.g. tech-savvy millennials, business professionals"
1796
+ }
1797
+ ),
1798
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-hint", children: "Describe your target audience for personalized content" })
1799
+ ] }),
1800
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-toggle-group", children: [
1801
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-toggle-row", children: [
1802
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1803
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-label", children: "Include Quotes" }),
1804
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-desc", children: "Add relevant quotes to generated articles" })
1805
+ ] }),
1806
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1807
+ "button",
1808
+ {
1809
+ type: "button",
1810
+ role: "switch",
1811
+ "aria-checked": includeQuotes,
1812
+ onClick: () => setIncludeQuotes(!includeQuotes),
1813
+ className: "cnfy-toggle",
1814
+ style: { backgroundColor: includeQuotes ? primaryColor : "#d1d5db" },
1815
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1816
+ "span",
1817
+ {
1818
+ className: `cnfy-toggle-thumb ${includeQuotes ? "cnfy-toggle-thumb--on" : ""}`
1819
+ }
1820
+ )
1821
+ }
1822
+ )
1823
+ ] }),
1824
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-toggle-row", children: [
1825
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1826
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-label", children: "Include FAQ Section" }),
1827
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-toggle-desc", children: "Add FAQ section at the end of articles" })
1828
+ ] }),
1829
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1830
+ "button",
1831
+ {
1832
+ type: "button",
1833
+ role: "switch",
1834
+ "aria-checked": includeFAQ,
1835
+ onClick: () => setIncludeFAQ(!includeFAQ),
1836
+ className: "cnfy-toggle",
1837
+ style: { backgroundColor: includeFAQ ? primaryColor : "#d1d5db" },
1838
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1839
+ "span",
1840
+ {
1841
+ className: `cnfy-toggle-thumb ${includeFAQ ? "cnfy-toggle-thumb--on" : ""}`
1842
+ }
1843
+ )
1844
+ }
1845
+ )
1846
+ ] })
1847
+ ] })
1848
+ ] }),
1849
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card", children: [
1850
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-card-header", children: [
1851
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h2", { className: "cnfy-dash-card-title-inline", children: "News Scraping" }),
1852
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-card-desc", children: "Scrape latest news from your configured locations" })
1853
+ ] }),
1854
+ !loadingStatus && scrapeStatus && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-grid cnfy-dash-grid--sm", children: [
1855
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1856
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "cnfy-dash-label-muted", children: "Status:" }),
1857
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-label-bold", children: scrapeStatus.isRunning ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "cnfy-dash-badge cnfy-dash-badge--yellow", children: "Running" }) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "cnfy-dash-badge cnfy-dash-badge--green", children: "Idle" }) })
1858
+ ] }),
1859
+ scrapeStatus.lastRun && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1860
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "cnfy-dash-label-muted", children: "Last Run:" }),
1861
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-label-bold", children: new Date(scrapeStatus.lastRun).toLocaleString() })
1862
+ ] }),
1863
+ scrapeStatus.totalScraped !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1864
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { className: "cnfy-dash-label-muted", children: "Total Scraped:" }),
1865
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "cnfy-dash-label-bold", children: [
1866
+ scrapeStatus.totalScraped.toLocaleString(),
1867
+ " articles"
1868
+ ] })
1869
+ ] })
1870
+ ] }),
1871
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
1872
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "cnfy-dash-info-text", children: [
1873
+ "Current configuration: ",
1874
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("strong", { children: (_b = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _b.state }),
1875
+ ((_c = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _c.cities) && preferences.localization.cities.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
1876
+ " - ",
1877
+ preferences.localization.cities.join(", ")
1878
+ ] })
1879
+ ] }),
1880
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1881
+ "button",
1882
+ {
1883
+ onClick: handleScrape,
1884
+ disabled: scraping || (scrapeStatus == null ? void 0 : scrapeStatus.isRunning),
1885
+ className: "cnfy-dash-btn-save",
1886
+ style: { backgroundColor: primaryColor },
1887
+ children: scraping ? "Starting Scrape..." : (scrapeStatus == null ? void 0 : scrapeStatus.isRunning) ? "Scraping in Progress..." : "Start Scraping"
1888
+ }
1889
+ )
1890
+ ] })
1891
+ ] }),
1892
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "cnfy-dash-actions", children: [
1893
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1894
+ "button",
1895
+ {
1896
+ onClick: handleSave,
1897
+ disabled: saving,
1898
+ className: "cnfy-dash-btn-save",
1899
+ style: { backgroundColor: primaryColor },
1900
+ children: saving ? "Saving..." : "Save Preferences"
1561
1901
  }
1562
- }
1563
- ) }),
1564
- selectedSource && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1565
- "button",
1566
- {
1567
- onClick: handleScrape,
1568
- disabled: scraping,
1569
- className: "flex items-center gap-1.5 px-3 py-2 bg-emerald-600 text-white rounded-lg text-sm font-medium hover:bg-emerald-700 transition disabled:opacity-50",
1570
- title: "Fetch latest news",
1571
- children: [
1572
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.RefreshCcw, { size: 14, className: scraping ? "animate-spin" : "" }),
1573
- scraping ? "Scraping..." : "Scrape"
1574
- ]
1575
- }
1576
- ),
1577
- !selectedSource && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
1578
- "button",
1579
- {
1580
- onClick: () => fetchNews(null),
1581
- disabled: fetchingNews,
1582
- className: "flex items-center gap-1 px-3 py-2 text-sm text-gray-600 hover:text-gray-900 border border-gray-200 rounded-lg transition",
1583
- children: [
1584
- /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_lucide_react6.RefreshCcw, { size: 14, className: fetchingNews ? "animate-spin" : "" }),
1585
- "Refresh"
1586
- ]
1587
- }
1588
- )
1902
+ ),
1903
+ success && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "cnfy-dash-success", style: { color: primaryColor }, children: "Preferences saved successfully \u2705" })
1904
+ ] })
1589
1905
  ] });
1590
1906
  }
1591
1907
 
@@ -1609,7 +1925,7 @@ var createContentStreamApi = async ({
1609
1925
  }) => {
1610
1926
  var _a;
1611
1927
  const API_BASE_URL = getApiBaseUrl();
1612
- const apiKey = process.env.NEXT_PUBLIC_API_KEY;
1928
+ const apiKey = getApiKey();
1613
1929
  const headers = {
1614
1930
  "Content-Type": "application/json"
1615
1931
  };
@@ -1702,7 +2018,7 @@ var rewriteNewsStreamApi = async ({
1702
2018
  if (targetAudience) payload.targetAudience = targetAudience;
1703
2019
  try {
1704
2020
  const API_BASE_URL = getApiBaseUrl();
1705
- const apiKey = process.env.NEXT_PUBLIC_API_KEY;
2021
+ const apiKey = getApiKey();
1706
2022
  console.log("\u{1F680} Starting stream request to:", `${API_BASE_URL}/chat/rewrite/stream`);
1707
2023
  console.log("\u{1F4E6} Payload:", payload);
1708
2024
  const headers = {
@@ -1831,32 +2147,18 @@ var rewriteNewsApi = async ({
1831
2147
  };
1832
2148
 
1833
2149
  // components/chatbot/ChatBot.tsx
1834
- var import_react_hot_toast4 = __toESM(require("react-hot-toast"));
2150
+ var import_react_hot_toast2 = __toESM(require("react-hot-toast"));
1835
2151
  var import_lucide_react7 = require("lucide-react");
1836
2152
  var import_jsx_runtime11 = require("react/jsx-runtime");
1837
- function ChatBot({
1838
- onNavigate,
1839
- onLogout
1840
- } = {}) {
1841
- const { loading, showNewsPanel } = useTheme();
2153
+ function ChatBot() {
2154
+ const { loading } = useTheme();
1842
2155
  const { preferences } = usePreferences();
1843
- const [selectedSource, setSelectedSource] = (0, import_react10.useState)(null);
1844
- const [news, setNews] = (0, import_react10.useState)([]);
1845
- const [newsLoading, setNewsLoading] = (0, import_react10.useState)(true);
1846
- const [selectedArticle, setSelectedArticle] = (0, import_react10.useState)(null);
2156
+ const [preferencesOpen, setPreferencesOpen] = (0, import_react10.useState)(false);
1847
2157
  const [messages, setMessages] = (0, import_react10.useState)([]);
1848
- const [showChatMobile, setShowChatMobile] = (0, import_react10.useState)(false);
1849
2158
  const [isStreaming, setIsStreaming] = (0, import_react10.useState)(false);
1850
2159
  const [analyzedData, setAnalyzedData] = (0, import_react10.useState)(null);
1851
- const handleNewsLoaded = (0, import_react10.useCallback)((loadedNews) => {
1852
- setNews(loadedNews);
1853
- }, []);
1854
- const handleLoadingChange = (0, import_react10.useCallback)((isLoading) => {
1855
- setNewsLoading(isLoading);
1856
- }, []);
1857
2160
  const handleRecreate = async ({ title, content, id }) => {
1858
2161
  var _a;
1859
- setShowChatMobile(true);
1860
2162
  const assistantId = crypto.randomUUID();
1861
2163
  setMessages((prev) => [
1862
2164
  ...prev,
@@ -1879,7 +2181,7 @@ ${title}`
1879
2181
  const lang = ((_a = preferences == null ? void 0 : preferences.localization) == null ? void 0 : _a.language) === "hi" ? "Hindi" : "English";
1880
2182
  try {
1881
2183
  await rewriteNewsStreamApi({
1882
- article: content,
2184
+ article: content || "",
1883
2185
  language: lang,
1884
2186
  articleId: id,
1885
2187
  tone: contentPrefs == null ? void 0 : contentPrefs.tone,
@@ -1899,7 +2201,7 @@ ${title}`
1899
2201
  },
1900
2202
  onComplete: () => {
1901
2203
  console.log("Streaming completed successfully");
1902
- import_react_hot_toast4.default.success("Article created successfully!");
2204
+ import_react_hot_toast2.default.success("Article created successfully!");
1903
2205
  },
1904
2206
  onError: async (error) => {
1905
2207
  console.error("Streaming error:", error);
@@ -1907,7 +2209,7 @@ ${title}`
1907
2209
  console.log("Falling back to regular API...");
1908
2210
  throw error;
1909
2211
  } else {
1910
- import_react_hot_toast4.default.error("Failed to complete article generation");
2212
+ import_react_hot_toast2.default.error("Failed to complete article generation");
1911
2213
  setMessages(
1912
2214
  (prev) => prev.map(
1913
2215
  (m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: accumulatedContent || "\u274C Failed to create article. Please try again." }) : m
@@ -1924,7 +2226,7 @@ ${title}`
1924
2226
  )
1925
2227
  );
1926
2228
  const result = await rewriteNewsApi({
1927
- article: content,
2229
+ article: content || "",
1928
2230
  language: lang,
1929
2231
  articleId: id,
1930
2232
  tone: contentPrefs == null ? void 0 : contentPrefs.tone,
@@ -1939,11 +2241,11 @@ ${title}`
1939
2241
  (m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: result.article || result }) : m
1940
2242
  )
1941
2243
  );
1942
- import_react_hot_toast4.default.success("Article created successfully!");
2244
+ import_react_hot_toast2.default.success("Article created successfully!");
1943
2245
  }
1944
2246
  } catch (err) {
1945
2247
  console.error("Complete Error:", err);
1946
- import_react_hot_toast4.default.error((err == null ? void 0 : err.message) || "An error occurred while creating the article");
2248
+ import_react_hot_toast2.default.error((err == null ? void 0 : err.message) || "An error occurred while creating the article");
1947
2249
  setMessages(
1948
2250
  (prev) => prev.map(
1949
2251
  (m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "\u274C Failed to create article. Please try again." }) : m
@@ -1994,7 +2296,7 @@ ${optionsList}`
1994
2296
  }
1995
2297
  } catch (err) {
1996
2298
  console.error("Analyze input error:", err);
1997
- import_react_hot_toast4.default.error("Failed to analyze the link");
2299
+ import_react_hot_toast2.default.error("Failed to analyze the link");
1998
2300
  setMessages(
1999
2301
  (prev) => prev.map(
2000
2302
  (m) => m.id === assistantId ? __spreadProps(__spreadValues({}, m), { content: "\u274C Failed to analyze the link. Please try again." }) : m
@@ -2030,12 +2332,12 @@ ${optionsList}`
2030
2332
  },
2031
2333
  onComplete: () => {
2032
2334
  setIsStreaming(false);
2033
- import_react_hot_toast4.default.success("Content generated!");
2335
+ import_react_hot_toast2.default.success("Content generated!");
2034
2336
  },
2035
2337
  onError: (error) => {
2036
2338
  console.error("Stream error:", error);
2037
2339
  setIsStreaming(false);
2038
- import_react_hot_toast4.default.error("Failed to generate content");
2340
+ import_react_hot_toast2.default.error("Failed to generate content");
2039
2341
  }
2040
2342
  });
2041
2343
  } catch (err) {
@@ -2083,12 +2385,12 @@ ${optionsList}`
2083
2385
  },
2084
2386
  onComplete: () => {
2085
2387
  setIsStreaming(false);
2086
- import_react_hot_toast4.default.success("Content created!");
2388
+ import_react_hot_toast2.default.success("Content created!");
2087
2389
  },
2088
2390
  onError: (error) => {
2089
2391
  console.error("Stream error:", error);
2090
2392
  setIsStreaming(false);
2091
- import_react_hot_toast4.default.error("Failed to create content");
2393
+ import_react_hot_toast2.default.error("Failed to create content");
2092
2394
  }
2093
2395
  });
2094
2396
  } catch (e) {
@@ -2103,7 +2405,7 @@ ${optionsList}`
2103
2405
  )
2104
2406
  );
2105
2407
  setIsStreaming(false);
2106
- import_react_hot_toast4.default.success("Content created!");
2408
+ import_react_hot_toast2.default.success("Content created!");
2107
2409
  }
2108
2410
  } catch (err) {
2109
2411
  console.error("Create content error:", err);
@@ -2116,93 +2418,54 @@ ${optionsList}`
2116
2418
  }
2117
2419
  };
2118
2420
  if (loading) {
2119
- return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-full h-screen flex items-center justify-center bg-white", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
2120
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react7.Loader2, { className: "h-8 w-8 animate-spin text-gray-400" }),
2121
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-sm text-gray-500", children: "Loading..." })
2421
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "cnfy-loading", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "cnfy-loading-inner", children: [
2422
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react7.Loader2, { className: "cnfy-loading-spinner cnfy-animate-spin" }),
2423
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "cnfy-loading-text", children: "Loading..." })
2122
2424
  ] }) });
2123
2425
  }
2124
- return (
2125
- // FULL SCREEN
2126
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "w-full h-screen flex flex-col bg-white", children: [
2127
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(HeaderBar, { onNavigate, onLogout }),
2128
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: `flex-1 min-h-0 md:grid ${showNewsPanel ? "md:grid-cols-12" : ""}`, children: [
2129
- showNewsPanel && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("aside", { className: "relative col-span-4 bg-gray-50/60 border-r border-gray-300 h-[90vh] overflow-y-auto", children: [
2130
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2131
- SourceSelector,
2132
- {
2133
- selectedSource,
2134
- onSourceChange: (value) => {
2135
- console.log("Selected source:", value);
2136
- setSelectedSource(value);
2137
- },
2138
- onNewsLoaded: handleNewsLoaded,
2139
- onLoadingChange: handleLoadingChange
2140
- }
2141
- ) }),
2142
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2143
- TrendingNews,
2144
- {
2145
- onRecreate: handleRecreate,
2146
- news,
2147
- isLoading: newsLoading
2148
- }
2149
- )
2150
- ] }),
2151
- /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
2152
- "section",
2153
- {
2154
- className: `
2155
- ${showNewsPanel ? "md:col-span-8" : "w-full"} bg-white flex flex-col h-full relative
2156
- ${showChatMobile ? "block" : "hidden md:block"}
2157
- `,
2158
- children: [
2159
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "md:hidden border-b border-gray-300 p-3", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2160
- "button",
2161
- {
2162
- onClick: () => setShowChatMobile(false),
2163
- className: "text-sm text-gray-600",
2164
- children: "\u2190 Back to news"
2165
- }
2166
- ) }),
2167
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "flex-1 min-h-0", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2168
- ChatWindow,
2169
- {
2170
- messages,
2171
- onSend: handleSendMessage,
2172
- onSelectNews: handleRecreate,
2173
- isStreaming,
2174
- analyzedData,
2175
- onSelectAction: handleSelectAction
2176
- }
2177
- ) }),
2178
- !messages.length && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center text-center text-gray-400 text-sm px-4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2179
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "font-medium", children: "AI News Assistant" }),
2180
- /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "mt-1", children: "Select a news article or type a message to begin" })
2181
- ] }) })
2182
- ]
2183
- }
2184
- )
2185
- ] }),
2186
- selectedArticle && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2187
- ArticleModal,
2426
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "cnfy-root", children: [
2427
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(HeaderBar, { onOpenPreferences: () => setPreferencesOpen(true) }),
2428
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "cnfy-main", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { className: "cnfy-chat-section cnfy-chat-section--full", children: [
2429
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "cnfy-chat-inner", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2430
+ ChatWindow,
2188
2431
  {
2189
- article: selectedArticle,
2190
- onClose: () => setSelectedArticle(null),
2191
- onRecreate: handleRecreate
2432
+ messages,
2433
+ onSend: handleSendMessage,
2434
+ onSelectNews: handleRecreate,
2435
+ isStreaming,
2436
+ analyzedData,
2437
+ onSelectAction: handleSelectAction
2192
2438
  }
2193
- )
2194
- ] })
2195
- );
2439
+ ) }),
2440
+ !messages.length && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "cnfy-empty-state", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
2441
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "cnfy-empty-state-title", children: "AI News Assistant" }),
2442
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "cnfy-empty-state-subtitle", children: "Type a message or paste a link to begin" })
2443
+ ] }) })
2444
+ ] }) }),
2445
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
2446
+ Drawer,
2447
+ {
2448
+ open: preferencesOpen,
2449
+ onClose: () => setPreferencesOpen(false),
2450
+ title: "Settings",
2451
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(PreferencesPage, {})
2452
+ }
2453
+ )
2454
+ ] });
2196
2455
  }
2197
2456
 
2198
2457
  // src/index.tsx
2199
2458
  var import_jsx_runtime12 = require("react/jsx-runtime");
2200
- function ContenifyChatBot({ onNavigate, onLogout }) {
2201
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PreferencesProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChatBot, { onNavigate, onLogout }) });
2459
+ function ContenifyChatBot({ apiUrl, apiKey, domain }) {
2460
+ (0, import_react11.useEffect)(() => {
2461
+ setConfig({ apiUrl, apiKey, domain });
2462
+ }, [apiUrl, apiKey, domain]);
2463
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(PreferencesProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChatBot, {}) });
2202
2464
  }
2203
2465
  var index_default = ContenifyChatBot;
2204
2466
  // Annotate the CommonJS export names for ESM import in node:
2205
2467
  0 && (module.exports = {
2206
- ContenifyChatBot
2468
+ ContenifyChatBot,
2469
+ setConfig
2207
2470
  });
2208
2471
  //# sourceMappingURL=index.js.map