xertica-ui 1.2.10 → 1.3.0

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.
@@ -32,15 +32,36 @@ import {
32
32
  BarChart3,
33
33
  Bookmark,
34
34
  Maximize2,
35
- AlertCircle
35
+ AlertCircle,
36
+ ThumbsUp,
37
+ ThumbsDown,
38
+ BookOpen,
39
+ ArrowLeft,
40
+ Table as TableIcon
36
41
  } from 'lucide-react';
37
42
  import { Button } from './ui/button';
38
43
  import { ScrollArea } from './ui/scroll-area';
39
- import { ModernChatInput, ActionType } from './ModernChatInput';
40
44
  import { Separator } from './ui/separator';
41
45
  import { DocumentEditor } from './DocumentEditor';
42
- import { FormattedDocument } from './FormattedDocument';
43
46
  import { MarkdownMessage } from './MarkdownMessage';
47
+ import { FormattedDocument } from './FormattedDocument';
48
+ import { ModernChatInput, ActionType } from './ModernChatInput';
49
+ import {
50
+ DropdownMenu,
51
+ DropdownMenuContent,
52
+ DropdownMenuItem,
53
+ DropdownMenuTrigger,
54
+ } from "./ui/dropdown-menu";
55
+ import {
56
+ Dialog,
57
+ DialogContent,
58
+ DialogDescription,
59
+ DialogFooter,
60
+ DialogHeader,
61
+ DialogTitle,
62
+ } from "./ui/dialog";
63
+ import { Textarea } from "./ui/textarea";
64
+ import { Alert, AlertDescription, AlertTitle } from "./ui/alert";
44
65
  import { XerticaOrbe } from './XerticaOrbe';
45
66
  import { useApiKey } from '../contexts/ApiKeyContext';
46
67
  import { useAssistente } from '../contexts/AssistenteContext';
@@ -50,6 +71,18 @@ import { Tooltip, TooltipTrigger } from './ui/tooltip';
50
71
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
51
72
  import { cn } from './ui/utils';
52
73
  import { ASSISTANT_EXPANDED_WIDTH, ASSISTANT_COLLAPSED_WIDTH } from './layout-constants';
74
+ // Import Chart Components
75
+ import { Bar, BarChart, CartesianGrid, XAxis, Tooltip as RechartsTooltip, ResponsiveContainer } from "recharts";
76
+ import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent } from "./ui/chart";
77
+ import {
78
+ Table,
79
+ TableBody,
80
+ TableCaption,
81
+ TableCell,
82
+ TableHead,
83
+ TableHeader,
84
+ TableRow,
85
+ } from "./ui/table";
53
86
 
54
87
  // Tooltip customizado estilo sidebar (branco)
55
88
  function AssistantTooltipContent({
@@ -87,12 +120,7 @@ interface AssistenteXerticaProps {
87
120
  isFullPage?: boolean;
88
121
  }
89
122
 
90
- import type { Message, Conversa, SearchResult, SearchSource, SearchCommand } from '../contexts/AssistenteContext';
91
-
92
- interface Sugestao {
93
- id: string;
94
- texto: string;
95
- }
123
+ import type { Message, Conversa, SearchResult, SearchSource, SearchCommand, Sugestao } from '../contexts/AssistenteContext';
96
124
 
97
125
  const sugestoesPadrao: Sugestao[] = [
98
126
  { id: '1', texto: 'O que posso pedir para você fazer?' },
@@ -102,6 +130,13 @@ const sugestoesPadrao: Sugestao[] = [
102
130
  { id: '5', texto: 'Qual projetos está tendo o melhor desempenho?' }
103
131
  ];
104
132
 
133
+ const sugestoesRicas: Sugestao[] = [
134
+ { id: 'rich-1', texto: 'Ver exemplo de Gráfico', icon: <BarChart3 className="w-4 h-4 mr-2" /> },
135
+ { id: 'rich-2', texto: 'Ver exemplo de Imagem', icon: <ImageIcon className="w-4 h-4 mr-2" /> },
136
+ { id: 'rich-3', texto: 'Ver exemplo de Tabela', icon: <TableIcon className="w-4 h-4 mr-2" /> },
137
+ { id: 'rich-4', texto: 'Ver exemplo de Documento', icon: <FileText className="w-4 h-4 mr-2" /> }
138
+ ];
139
+
105
140
  // Respostas simuladas da IA
106
141
  const gerarResposta = (mensagemUsuario: string): string => {
107
142
  const mensagemLower = mensagemUsuario.toLowerCase();
@@ -188,13 +223,164 @@ export function AssistenteXertica({ isExpanded, onToggle, onToggleWithTab, isFul
188
223
 
189
224
  const [mensagem, setMensagem] = useState('');
190
225
  const [sugestoes] = useState<Sugestao[]>(sugestoesPadrao);
226
+ const [showMoreSuggestions, setShowMoreSuggestions] = useState(false);
191
227
  const [copiedId, setCopiedId] = useState<string | null>(null);
192
228
  const [generatingPodcastId, setGeneratingPodcastId] = useState<string | null>(null);
193
229
  const [executingCommand, setExecutingCommand] = useState<string | null>(null);
230
+ const [feedbackDialogOpen, setFeedbackDialogOpen] = useState(false);
231
+ const [feedbackMessageId, setFeedbackMessageId] = useState<string | null>(null);
232
+ const [feedbackCategory, setFeedbackCategory] = useState<string | null>(null);
233
+ const [feedbackReason, setFeedbackReason] = useState("");
194
234
  const messagesEndRef = useRef<HTMLDivElement>(null);
195
235
  const fileInputRef = useRef<HTMLInputElement>(null);
196
236
  const audioInputRef = useRef<HTMLInputElement>(null);
197
237
 
238
+ const handleRichResponse = (suggestionId: string, suggestionText: string) => {
239
+ setIsTyping(true);
240
+ setMensagem(''); // Clear input if any
241
+
242
+ // Simulate network delay
243
+ setTimeout(() => {
244
+ let novaMensagem: Message = {
245
+ id: Date.now().toString() + '-ia-rich',
246
+ type: 'assistant',
247
+ content: '',
248
+ timestamp: new Date(),
249
+ isFavorite: false
250
+ };
251
+
252
+ if (suggestionId === 'rich-1') { // Gráfico
253
+ const chartData = [
254
+ { month: "Jan", desktop: 186, mobile: 80 },
255
+ { month: "Feb", desktop: 305, mobile: 200 },
256
+ { month: "Mar", desktop: 237, mobile: 120 },
257
+ { month: "Apr", desktop: 73, mobile: 190 },
258
+ { month: "May", desktop: 209, mobile: 130 },
259
+ { month: "Jun", desktop: 214, mobile: 140 },
260
+ ];
261
+ const chartConfig = {
262
+ desktop: {
263
+ label: "Desktop",
264
+ color: "hsl(var(--chart-1))",
265
+ },
266
+ mobile: {
267
+ label: "Mobile",
268
+ color: "hsl(var(--chart-2))",
269
+ },
270
+ } satisfies ChartConfig;
271
+
272
+ novaMensagem = {
273
+ ...novaMensagem,
274
+ content: 'Aqui está o gráfico de desempenho do projeto nos últimos 6 meses, comparando acessos Desktop vs Mobile.',
275
+ chartData: chartData,
276
+ chartConfig: chartConfig
277
+ };
278
+ } else if (suggestionId === 'rich-2') { // Imagem
279
+ novaMensagem = {
280
+ ...novaMensagem,
281
+ content: 'Aqui está a imagem prévia do novo layout do dashboard que você solicitou.',
282
+ attachmentType: 'image',
283
+ attachmentName: 'dashboard-preview-v2.jpg',
284
+ // Placeholder image URL
285
+ documentContent: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?q=80&w=2070&auto=format&fit=crop'
286
+ };
287
+ } else if (suggestionId === 'rich-3') { // Tabela
288
+ novaMensagem = {
289
+ ...novaMensagem,
290
+ content: 'Aqui está a tabela com os status dos servidores:',
291
+ tableData: {
292
+ caption: "Status dos Servidores em Tempo Real",
293
+ headers: ["Servidor", "Status", "Uptime", "Link"],
294
+ rows: [
295
+ ["Alpha-1", "✅ Online", "99.9%", <a href="https://example.com/log1" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline flex items-center gap-1">Log <ExternalLink size={12} /></a>],
296
+ ["Beta-2", "⚠️ Warning", "98.5%", <a href="https://example.com/log2" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline flex items-center gap-1">Log <ExternalLink size={12} /></a>],
297
+ ["Gamma-3", "❌ Offline", "0%", <a href="https://example.com/log3" target="_blank" rel="noopener noreferrer" className="text-blue-500 hover:underline flex items-center gap-1">Log <ExternalLink size={12} /></a>]
298
+ ]
299
+ }
300
+ };
301
+ } else if (suggestionId === 'rich-4') { // Documento para Download
302
+ novaMensagem = {
303
+ ...novaMensagem,
304
+ content: 'Gerei o relatório completo de auditoria de segurança. Você pode baixá-lo ou editá-lo abaixo.',
305
+ attachmentType: 'document',
306
+ attachmentName: 'auditoria-seguranca-2024.md',
307
+ documentTitle: 'Relatório de Auditoria de Segurança',
308
+ documentContent: '# Auditoria de Segurança 2024\n\n## Resumo Executivo\nForam encontradas 3 vulnerabilidades de nível baixo...'
309
+ };
310
+ }
311
+
312
+ setConversas(prev => prev.map(conv => {
313
+ if (conv.id === conversaAtual) {
314
+ return {
315
+ ...conv,
316
+ mensagens: [...conv.mensagens,
317
+ { // User message triggers the response
318
+ id: Date.now().toString() + '-user',
319
+ type: 'user',
320
+ content: suggestionText,
321
+ timestamp: new Date()
322
+ },
323
+ novaMensagem
324
+ ],
325
+ ultimaMensagem: suggestionText,
326
+ timestamp: new Date().toLocaleString('pt-BR')
327
+ };
328
+ }
329
+ return conv;
330
+ }));
331
+
332
+ setIsTyping(false);
333
+ setShowMoreSuggestions(false); // Close suggestions
334
+ }, 1500);
335
+ };
336
+
337
+ const handleEvaluation = (messageId: string, evaluation: 'like' | 'dislike', reason?: string) => {
338
+ setConversas(prev => prev.map(conv => {
339
+ if (conv.id === conversaAtual) {
340
+ return {
341
+ ...conv,
342
+ mensagens: conv.mensagens.map(msg =>
343
+ msg.id === messageId ? { ...msg, evaluation, evaluationReason: reason } : msg
344
+ )
345
+ };
346
+ }
347
+ return conv;
348
+ }));
349
+
350
+ if (evaluation === 'like') {
351
+ toast.success("Obrigado por avaliar positivamente!");
352
+ } else if (evaluation === 'dislike' && reason) {
353
+ toast.success("Obrigado pelo seu feedback. Vamos melhorar.");
354
+ }
355
+ };
356
+
357
+ const openFeedbackDialog = (messageId: string, category: string | null = null) => {
358
+ setFeedbackMessageId(messageId);
359
+ setFeedbackCategory(category);
360
+ setFeedbackReason("");
361
+ setFeedbackDialogOpen(true);
362
+ };
363
+
364
+ const submitFeedbackDialog = () => {
365
+ if (!feedbackMessageId) return;
366
+
367
+ let finalReason = "";
368
+ if (feedbackCategory) {
369
+ // Se tem categoria pré-definida, o comentário é opcional
370
+ finalReason = feedbackReason.trim() ? `${feedbackCategory}: ${feedbackReason}` : feedbackCategory;
371
+ } else {
372
+ // Se é "Outros", o motivo é obrigatório
373
+ if (!feedbackReason.trim()) return;
374
+ finalReason = feedbackReason;
375
+ }
376
+
377
+ handleEvaluation(feedbackMessageId, 'dislike', finalReason);
378
+ setFeedbackDialogOpen(false);
379
+ setFeedbackMessageId(null);
380
+ setFeedbackReason("");
381
+ setFeedbackCategory(null);
382
+ };
383
+
198
384
  const conversaAtiva = conversas.find(c => c.id === conversaAtual);
199
385
  const mensagens = conversaAtiva?.mensagens || [];
200
386
 
@@ -1489,24 +1675,55 @@ Este documento fornece uma base sólida para entender e trabalhar com ${temaLimp
1489
1675
 
1490
1676
  {/* Suggestions */}
1491
1677
  <div className="px-4 pb-4 space-y-2">
1492
- {sugestoes.map((sugestao) => (
1493
- <button
1494
- key={sugestao.id}
1495
- onClick={() => setMensagem(sugestao.texto)}
1496
- className="w-full p-3 text-left bg-muted hover:bg-accent rounded-lg transition-colors duration-200 text-foreground"
1497
- >
1498
- {sugestao.texto}
1499
- </button>
1500
- ))}
1678
+ {!showMoreSuggestions ? (
1679
+ <>
1680
+ {sugestoes.map((sugestao) => (
1681
+ <button
1682
+ key={sugestao.id}
1683
+ onClick={() => setMensagem(sugestao.texto)}
1684
+ className="w-full p-3 text-left bg-muted hover:bg-accent rounded-lg transition-colors duration-200 text-foreground"
1685
+ >
1686
+ {sugestao.texto}
1687
+ </button>
1688
+ ))}
1689
+
1690
+ <Button
1691
+ variant="ghost"
1692
+ size="sm"
1693
+ onClick={() => setShowMoreSuggestions(true)}
1694
+ className="w-full justify-start text-muted-foreground hover:text-foreground"
1695
+ >
1696
+ <MoreHorizontal className="w-4 h-4 mr-2" />
1697
+ Mais sugestões
1698
+ </Button>
1699
+ </>
1700
+ ) : (
1701
+ <>
1702
+ <div className="flex items-center gap-2 mb-2 px-2">
1703
+ <span className="text-xs font-medium text-muted-foreground">Exemplos de respostas ricas</span>
1704
+ </div>
1705
+ {sugestoesRicas.map((sugestao) => (
1706
+ <button
1707
+ key={sugestao.id}
1708
+ onClick={() => handleRichResponse(sugestao.id, sugestao.texto)}
1709
+ className="w-full p-3 text-left bg-muted hover:bg-accent rounded-lg transition-colors duration-200 text-foreground flex items-center"
1710
+ >
1711
+ {sugestao.icon}
1712
+ {sugestao.texto}
1713
+ </button>
1714
+ ))}
1501
1715
 
1502
- <Button
1503
- variant="ghost"
1504
- size="sm"
1505
- className="w-full justify-start text-muted-foreground hover:text-foreground"
1506
- >
1507
- <MoreHorizontal className="w-4 h-4 mr-2" />
1508
- Mais sugestões
1509
- </Button>
1716
+ <Button
1717
+ variant="ghost"
1718
+ size="sm"
1719
+ onClick={() => setShowMoreSuggestions(false)}
1720
+ className="w-full justify-start text-muted-foreground hover:text-foreground"
1721
+ >
1722
+ <ArrowLeft className="w-4 h-4 mr-2" />
1723
+ Voltar
1724
+ </Button>
1725
+ </>
1726
+ )}
1510
1727
  </div>
1511
1728
  </div>
1512
1729
  ) : (
@@ -1607,8 +1824,70 @@ Este documento fornece uma base sólida para entender e trabalhar com ${temaLimp
1607
1824
  </>
1608
1825
  )}
1609
1826
 
1610
- {/* Document Preview - Mostrar documento formatado */}
1611
- {msg.attachmentType === 'document' && msg.documentContent && (
1827
+ {/* Image Attachment */}
1828
+ {msg.attachmentType === 'image' && msg.documentContent && (
1829
+ <div className="mt-3 rounded-lg overflow-hidden border border-border">
1830
+ <img
1831
+ src={msg.documentContent}
1832
+ alt={msg.attachmentName || 'Image'}
1833
+ className="w-full h-auto max-h-[300px] object-cover"
1834
+ />
1835
+ </div>
1836
+ )}
1837
+
1838
+ {/* Chart Rendering */}
1839
+ {msg.chartData && msg.chartConfig && (
1840
+ <div className="mt-4 mb-2 p-2 bg-background/50 rounded-lg border border-border">
1841
+ <ChartContainer config={msg.chartConfig}>
1842
+ <BarChart accessibilityLayer data={msg.chartData}>
1843
+ <CartesianGrid vertical={false} />
1844
+ <XAxis
1845
+ dataKey="month"
1846
+ tickLine={false}
1847
+ tickMargin={10}
1848
+ axisLine={false}
1849
+ tickFormatter={(value) => value.slice(0, 3)}
1850
+ />
1851
+ <ChartTooltip
1852
+ cursor={false}
1853
+ content={<ChartTooltipContent indicator="dashed" />}
1854
+ />
1855
+ <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
1856
+ <Bar dataKey="mobile" fill="var(--color-mobile)" radius={4} />
1857
+ </BarChart>
1858
+ </ChartContainer>
1859
+ </div>
1860
+ )}
1861
+
1862
+ {/* Table Rendering */}
1863
+ {msg.tableData && (
1864
+ <div className="mt-4 mb-2 rounded-md border">
1865
+ <Table>
1866
+ {msg.tableData.caption && <TableCaption>{msg.tableData.caption}</TableCaption>}
1867
+ <TableHeader>
1868
+ <TableRow>
1869
+ {msg.tableData.headers.map((header, index) => (
1870
+ <TableHead key={index}>{header}</TableHead>
1871
+ ))}
1872
+ </TableRow>
1873
+ </TableHeader>
1874
+ <TableBody>
1875
+ {msg.tableData.rows.map((row, rowIndex) => (
1876
+ <TableRow key={rowIndex}>
1877
+ {row.map((cell, cellIndex) => (
1878
+ <TableCell key={cellIndex} className="font-medium">
1879
+ {cell}
1880
+ </TableCell>
1881
+ ))}
1882
+ </TableRow>
1883
+ ))}
1884
+ </TableBody>
1885
+ </Table>
1886
+ </div>
1887
+ )}
1888
+
1889
+ {/* Document Preview */}
1890
+ {msg.attachmentType === 'document' && msg.documentContent && !msg.chartData && (
1612
1891
  <div className="mt-3 pt-3 border-t border-border overflow-hidden">
1613
1892
  <FormattedDocument
1614
1893
  content={msg.documentContent}
@@ -1818,6 +2097,57 @@ Este documento fornece uma base sólida para entender e trabalhar com ${temaLimp
1818
2097
  )}
1819
2098
  </Button>
1820
2099
  </div>
2100
+
2101
+ {/* Feedback UI */}
2102
+ {msg.type === 'assistant' && (
2103
+ <div className="px-2 pb-2">
2104
+ <div className="flex items-center gap-1 mt-2">
2105
+ <span className="text-xs text-muted-foreground mr-2">Essa resposta foi útil?</span>
2106
+ <Button
2107
+ variant="ghost"
2108
+ size="icon"
2109
+ className={cn(
2110
+ "h-6 w-6 rounded-full hover:bg-green-100 dark:hover:bg-green-900/20 hover:text-green-600",
2111
+ msg.evaluation === 'like' && "text-green-600 bg-green-100 dark:bg-green-900/20"
2112
+ )}
2113
+ onClick={() => handleEvaluation(msg.id, 'like')}
2114
+ title="Gostei"
2115
+ >
2116
+ <ThumbsUp className="h-3.5 w-3.5" />
2117
+ </Button>
2118
+
2119
+ <DropdownMenu>
2120
+ <DropdownMenuTrigger asChild>
2121
+ <Button
2122
+ variant="ghost"
2123
+ size="icon"
2124
+ className={cn(
2125
+ "h-6 w-6 rounded-full hover:bg-red-100 dark:hover:bg-red-900/20 hover:text-red-600",
2126
+ msg.evaluation === 'dislike' && "text-red-600 bg-red-100 dark:bg-red-900/20"
2127
+ )}
2128
+ title="Não gostei"
2129
+ >
2130
+ <ThumbsDown className="h-3.5 w-3.5" />
2131
+ </Button>
2132
+ </DropdownMenuTrigger>
2133
+ <DropdownMenuContent align="start">
2134
+ <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, 'Não era o que eu procurava')}>
2135
+ Não era o que eu procurava
2136
+ </DropdownMenuItem>
2137
+ <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, 'Informação incorreta')}>
2138
+ Informação incorreta
2139
+ </DropdownMenuItem>
2140
+ <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, 'Resposta incompleta')}>
2141
+ Resposta incompleta
2142
+ </DropdownMenuItem>
2143
+ <DropdownMenuItem onClick={() => openFeedbackDialog(msg.id, null)}>
2144
+ Outros...
2145
+ </DropdownMenuItem>
2146
+ </DropdownMenuContent>
2147
+ </DropdownMenu>
2148
+ </div>
2149
+ </div>
2150
+ )}
1821
2151
  </div>
1822
2152
  </motion.div>
1823
2153
  ))}
@@ -1863,6 +2193,38 @@ Este documento fornece uma base sólida para entender e trabalhar com ${temaLimp
1863
2193
  </div>
1864
2194
  )}
1865
2195
 
2196
+ <Dialog open={feedbackDialogOpen} onOpenChange={setFeedbackDialogOpen}>
2197
+ <DialogContent className="sm:max-w-[600px]">
2198
+ <DialogHeader>
2199
+ <DialogTitle className="pr-8">
2200
+ {feedbackCategory ? `Enviar feedback: ${feedbackCategory}` : 'Enviar feedback'}
2201
+ </DialogTitle>
2202
+ <DialogDescription>
2203
+ {feedbackCategory
2204
+ ? "Gostaria de adicionar algum comentário? (Opcional)"
2205
+ : "Conte-nos por que essa resposta não foi útil para que possamos melhorar."}
2206
+ </DialogDescription>
2207
+ </DialogHeader>
2208
+ <div className="grid gap-4 py-4 px-6">
2209
+ <Textarea
2210
+ className="min-h-[100px]"
2211
+ placeholder={feedbackCategory ? "Comentário adicional..." : "Descreva o motivo..."}
2212
+ value={feedbackReason}
2213
+ onChange={(e) => setFeedbackReason(e.target.value)}
2214
+ />
2215
+ </div>
2216
+ <DialogFooter>
2217
+ <Button variant="outline" onClick={() => setFeedbackDialogOpen(false)}>Cancelar</Button>
2218
+ <Button
2219
+ onClick={submitFeedbackDialog}
2220
+ disabled={!feedbackCategory && !feedbackReason.trim()}
2221
+ >
2222
+ {feedbackCategory ? 'Confirmar e Enviar' : 'Enviar feedback'}
2223
+ </Button>
2224
+ </DialogFooter>
2225
+ </DialogContent>
2226
+ </Dialog>
2227
+
1866
2228
  {(abaSelecionada === 'historico' || abaSelecionada === 'favoritos') && (
1867
2229
  <ScrollArea className="flex-1 min-h-0">
1868
2230
  <div className={`p-4 ${isFullPage ? 'mx-auto w-full max-w-6xl' : ''}`}>
@@ -1,20 +1,36 @@
1
1
  import React, { createContext, useContext, useState, ReactNode } from 'react';
2
2
 
3
+
4
+
5
+ export interface Sugestao {
6
+ id: string;
7
+ texto: string;
8
+ icon?: ReactNode;
9
+ }
10
+
3
11
  export interface Message {
4
12
  id: string;
5
- type: 'user' | 'assistant';
13
+ type: 'user' | 'assistant' | 'system';
6
14
  content: string;
7
15
  timestamp: Date;
8
16
  isFavorite?: boolean;
9
- attachmentType?: 'file' | 'audio' | 'image' | 'podcast' | 'document' | 'search';
17
+ chartData?: any[];
18
+ chartConfig?: any;
19
+ attachmentType?: 'image' | 'video' | 'audio' | 'file' | 'document' | 'podcast' | 'search';
10
20
  attachmentName?: string;
11
- audioUrl?: string;
12
- isPodcastGenerating?: boolean;
13
21
  documentContent?: string;
14
22
  documentTitle?: string;
23
+ tableData?: {
24
+ caption?: string;
25
+ headers: string[];
26
+ rows: (string | ReactNode)[][];
27
+ };
28
+ audioUrl?: string;
15
29
  searchResults?: SearchResult[];
16
30
  searchSources?: SearchSource[];
17
31
  searchCommands?: SearchCommand[];
32
+ evaluation?: 'like' | 'dislike';
33
+ evaluationReason?: string;
18
34
  }
19
35
 
20
36
  export interface Conversa {
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const alertVariants: (props?: ({
4
- variant?: "default" | "error" | "success" | "warning" | "info" | null | undefined;
4
+ variant?: "default" | "error" | "success" | "info" | "warning" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  declare function Alert({ className, variant, children, ...props }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>): import("react/jsx-runtime").JSX.Element;
7
7
  declare function AlertTitle({ className, ...props }: React.ComponentProps<"div">): import("react/jsx-runtime").JSX.Element;
@@ -1,7 +1,7 @@
1
1
  import * as React from "react";
2
2
  import { type VariantProps } from "class-variance-authority";
3
3
  declare const badgeVariants: (props?: ({
4
- variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "warning" | "info" | null | undefined;
4
+ variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "info" | "warning" | null | undefined;
5
5
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
6
6
  export declare function Badge({ className, variant, asChild, children, ...props }: React.ComponentProps<"span"> & VariantProps<typeof badgeVariants> & {
7
7
  asChild?: boolean;
@@ -1,19 +1,32 @@
1
1
  import React, { ReactNode } from 'react';
2
+ export interface Sugestao {
3
+ id: string;
4
+ texto: string;
5
+ icon?: ReactNode;
6
+ }
2
7
  export interface Message {
3
8
  id: string;
4
- type: 'user' | 'assistant';
9
+ type: 'user' | 'assistant' | 'system';
5
10
  content: string;
6
11
  timestamp: Date;
7
12
  isFavorite?: boolean;
8
- attachmentType?: 'file' | 'audio' | 'image' | 'podcast' | 'document' | 'search';
13
+ chartData?: any[];
14
+ chartConfig?: any;
15
+ attachmentType?: 'image' | 'video' | 'audio' | 'file' | 'document' | 'podcast' | 'search';
9
16
  attachmentName?: string;
10
- audioUrl?: string;
11
- isPodcastGenerating?: boolean;
12
17
  documentContent?: string;
13
18
  documentTitle?: string;
19
+ tableData?: {
20
+ caption?: string;
21
+ headers: string[];
22
+ rows: (string | ReactNode)[][];
23
+ };
24
+ audioUrl?: string;
14
25
  searchResults?: SearchResult[];
15
26
  searchSources?: SearchSource[];
16
27
  searchCommands?: SearchCommand[];
28
+ evaluation?: 'like' | 'dislike';
29
+ evaluationReason?: string;
17
30
  }
18
31
  export interface Conversa {
19
32
  id: string;