import { Clock, Edit, Share, Trash, FileText, FileDown } from 'lucide-react'; import { Message } from './ChatWindow'; import { useEffect, useState, Fragment } from 'react'; import { formatTimeDifference } from '@/lib/utils'; import DeleteChat from './DeleteChat'; import { Popover, PopoverButton, PopoverPanel, Transition, } from '@headlessui/react'; import jsPDF from 'jspdf'; import { useChat, Section } from '@/lib/hooks/useChat'; const downloadFile = (filename: string, content: string, type: string) => { const blob = new Blob([content], { type }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); setTimeout(() => { document.body.removeChild(a); URL.revokeObjectURL(url); }, 0); }; const exportAsMarkdown = (sections: Section[], title: string) => { const date = new Date( sections[0]?.userMessage?.createdAt || Date.now(), ).toLocaleString(); let md = `# 💬 Chat Export: ${title}\n\n`; md += `*Exported on: ${date}*\n\n---\n`; sections.forEach((section, idx) => { if (section.userMessage) { md += `\n---\n`; md += `**🧑 User** `; md += `*${new Date(section.userMessage.createdAt).toLocaleString()}*\n\n`; md += `> ${section.userMessage.content.replace(/\n/g, '\n> ')}\n`; } if (section.assistantMessage) { md += `\n---\n`; md += `**🤖 Assistant** `; md += `*${new Date(section.assistantMessage.createdAt).toLocaleString()}*\n\n`; md += `> ${section.assistantMessage.content.replace(/\n/g, '\n> ')}\n`; } if ( section.sourceMessage && section.sourceMessage.sources && section.sourceMessage.sources.length > 0 ) { md += `\n**Citations:**\n`; section.sourceMessage.sources.forEach((src: any, i: number) => { const url = src.metadata?.url || ''; md += `- [${i + 1}] [${url}](${url})\n`; }); } }); md += '\n---\n'; downloadFile(`${title || 'chat'}.md`, md, 'text/markdown'); }; const exportAsPDF = (sections: Section[], title: string) => { const doc = new jsPDF(); const date = new Date( sections[0]?.userMessage?.createdAt || Date.now(), ).toLocaleString(); let y = 15; const pageHeight = doc.internal.pageSize.height; doc.setFontSize(18); doc.text(`Chat Export: ${title}`, 10, y); y += 8; doc.setFontSize(11); doc.setTextColor(100); doc.text(`Exported on: ${date}`, 10, y); y += 8; doc.setDrawColor(200); doc.line(10, y, 200, y); y += 6; doc.setTextColor(30); sections.forEach((section, idx) => { if (section.userMessage) { if (y > pageHeight - 30) { doc.addPage(); y = 15; } doc.setFont('helvetica', 'bold'); doc.text('User', 10, y); doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.setTextColor(120); doc.text( `${new Date(section.userMessage.createdAt).toLocaleString()}`, 40, y, ); y += 6; doc.setTextColor(30); doc.setFontSize(12); const userLines = doc.splitTextToSize(section.userMessage.content, 180); for (let i = 0; i < userLines.length; i++) { if (y > pageHeight - 20) { doc.addPage(); y = 15; } doc.text(userLines[i], 12, y); y += 6; } y += 6; doc.setDrawColor(230); if (y > pageHeight - 10) { doc.addPage(); y = 15; } doc.line(10, y, 200, y); y += 4; } if (section.assistantMessage) { if (y > pageHeight - 30) { doc.addPage(); y = 15; } doc.setFont('helvetica', 'bold'); doc.text('Assistant', 10, y); doc.setFont('helvetica', 'normal'); doc.setFontSize(10); doc.setTextColor(120); doc.text( `${new Date(section.assistantMessage.createdAt).toLocaleString()}`, 40, y, ); y += 6; doc.setTextColor(30); doc.setFontSize(12); const assistantLines = doc.splitTextToSize( section.assistantMessage.content, 180, ); for (let i = 0; i < assistantLines.length; i++) { if (y > pageHeight - 20) { doc.addPage(); y = 15; } doc.text(assistantLines[i], 12, y); y += 6; } if ( section.sourceMessage && section.sourceMessage.sources && section.sourceMessage.sources.length > 0 ) { doc.setFontSize(11); doc.setTextColor(80); if (y > pageHeight - 20) { doc.addPage(); y = 15; } doc.text('Citations:', 12, y); y += 5; section.sourceMessage.sources.forEach((src: any, i: number) => { const url = src.metadata?.url || ''; if (y > pageHeight - 15) { doc.addPage(); y = 15; } doc.text(`- [${i + 1}] ${url}`, 15, y); y += 5; }); doc.setTextColor(30); } y += 6; doc.setDrawColor(230); if (y > pageHeight - 10) { doc.addPage(); y = 15; } doc.line(10, y, 200, y); y += 4; } }); doc.save(`${title || 'chat'}.pdf`); }; const Navbar = () => { const [title, setTitle] = useState(''); const [timeAgo, setTimeAgo] = useState(''); const { sections, chatId } = useChat(); useEffect(() => { if (sections.length > 0 && sections[0].userMessage) { const newTitle = sections[0].userMessage.content.length > 20 ? `${sections[0].userMessage.content.substring(0, 20).trim()}...` : sections[0].userMessage.content; setTitle(newTitle); const newTimeAgo = formatTimeDifference( new Date(), sections[0].userMessage.createdAt, ); setTimeAgo(newTimeAgo); } }, [sections]); useEffect(() => { const intervalId = setInterval(() => { if (sections.length > 0 && sections[0].userMessage) { const newTimeAgo = formatTimeDifference( new Date(), sections[0].userMessage.createdAt, ); setTimeAgo(newTimeAgo); } }, 1000); return () => clearInterval(intervalId); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return (
{timeAgo} ago

{title || 'New Conversation'}

Export Chat

{}} />
); }; export default Navbar;