diff --git a/app/[locale]/chat/page.tsx b/app/[locale]/chat/page.tsx deleted file mode 100644 index cc0e538..0000000 --- a/app/[locale]/chat/page.tsx +++ /dev/null @@ -1,333 +0,0 @@ -'use client' -import { - Container, - Grid, - Card, - CardContent, - Typography, - Box, - TextField, - Button, - Paper, - List, - ListItem, - Avatar, - Chip, - IconButton, - Divider, - useTheme, - CircularProgress, - Skeleton, -} from '@mui/material' -import { - Chat, - Send, - Person, - SmartToy, - ContentCopy, - ThumbUp, - ThumbDown, - Refresh, -} from '@mui/icons-material' -import { useState, useRef, useEffect } from 'react' -import { useTranslations, useLocale } from 'next-intl' - -interface ChatMessage { - id: string - role: 'user' | 'assistant' - content: string - timestamp: Date -} - -export default function ChatPage() { - const theme = useTheme() - const t = useTranslations('chat') - const locale = useLocale() - const [messages, setMessages] = useState([ - { - id: '1', - role: 'assistant', - content: t('subtitle'), - timestamp: new Date(), - } - ]) - const [inputMessage, setInputMessage] = useState('') - const [isLoading, setIsLoading] = useState(false) - const messagesEndRef = useRef(null) - - const scrollToBottom = () => { - messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) - } - - useEffect(() => { - scrollToBottom() - }, [messages]) - - const handleSendMessage = async () => { - if (!inputMessage.trim() || isLoading) return - - const userMessage: ChatMessage = { - id: Date.now().toString(), - role: 'user', - content: inputMessage, - timestamp: new Date(), - } - - setMessages(prev => [...prev, userMessage]) - setInputMessage('') - setIsLoading(true) - - try { - const response = await fetch('/api/chat', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - message: inputMessage, - locale, - history: messages.slice(-5).map(m => ({ - id: m.id, - role: m.role, - content: m.content, - timestamp: m.timestamp.toISOString(), - })), - }), - }) - - if (!response.ok) { - throw new Error('Failed to get response') - } - - const data = await response.json() - - const assistantMessage: ChatMessage = { - id: (Date.now() + 1).toString(), - role: 'assistant', - content: data.response || t('error') || 'Error', - timestamp: new Date(), - } - - setMessages(prev => [...prev, assistantMessage]) - } catch (error) { - console.error('Error sending message:', error) - const errorMessage: ChatMessage = { - id: (Date.now() + 1).toString(), - role: 'assistant', - content: t('error') || 'Error', - timestamp: new Date(), - } - setMessages(prev => [...prev, errorMessage]) - } finally { - setIsLoading(false) - } - } - - const handleKeyPress = (event: React.KeyboardEvent) => { - if (event.key === 'Enter' && !event.shiftKey) { - event.preventDefault() - handleSendMessage() - } - } - - const copyToClipboard = (text: string) => { - navigator.clipboard.writeText(text) - } - - const suggestedQuestions = [ - 'Ce spune Biblia despre iubire?', - 'Explică-mi parabola semănătorului', - 'Care sunt fructele Duhului?', - 'Ce înseamnă să fii născut din nou?', - 'Cum pot să mă rog mai bine?', - ] - - return ( - - - - {/* Header */} - - - - {t('title')} - - - {t('subtitle')} - - - - - {/* Suggested Questions Sidebar */} - - - - - {t('suggestions.title')} - - - {t('suggestions.title')} - - { (t.raw('suggestions.questions') as string[]).map((question, index) => ( - setInputMessage(question)} - sx={{ - mb: 1, - mr: 1, - cursor: 'pointer', - '&:hover': { - bgcolor: 'primary.light', - color: 'white', - }, - }} - variant="outlined" - size="small" - /> - ))} - - - - {/* Tips section can be localized later via messages */} - - - - - {/* Main Chat Area */} - - - {/* Chat Messages */} - - {messages.map((message) => ( - - - - {message.role === 'user' ? : } - - - - - {message.content} - - - {message.role === 'assistant' && ( - - copyToClipboard(message.content)} - title="Copiază răspunsul" - > - - - - - - - - - - )} - - - {message.timestamp.toLocaleTimeString(locale === 'en' ? 'en-US' : 'ro-RO', { - hour: '2-digit', - minute: '2-digit', - })} - - - - - ))} - - {isLoading && ( - - - - - - - - - - {t('loading')} - - - - - - )} - -
- - - {/* Message Input */} - - - setInputMessage(e.target.value)} - onKeyPress={handleKeyPress} - disabled={isLoading} - variant="outlined" - /> - - - - - {t('enterToSend')} - - - - - - - - ) -} diff --git a/app/[locale]/page.tsx b/app/[locale]/page.tsx index 4bd24b4..be07589 100644 --- a/app/[locale]/page.tsx +++ b/app/[locale]/page.tsx @@ -39,7 +39,7 @@ export default function Home() { title: t('features.chat.title'), description: t('features.chat.description'), icon: , - path: '/chat', + path: '/__open-chat__', color: theme.palette.secondary.main, }, { @@ -106,7 +106,9 @@ export default function Home() { }, }} startIcon={} - onClick={() => router.push(`/${locale}/chat`)} + onClick={() => { + window.dispatchEvent(new CustomEvent('floating-chat:open', { detail: { fullscreen: true } })) + }} > {t('hero.cta.askAI')} @@ -152,7 +154,13 @@ export default function Home() { boxShadow: 4, }, }} - onClick={() => router.push(`/${locale}${feature.path}`)} + onClick={() => { + if (feature.path === '/__open-chat__') { + window.dispatchEvent(new CustomEvent('floating-chat:open', { detail: { fullscreen: true } })) + } else { + router.push(`/${locale}${feature.path}`) + } + }} > ) -} \ No newline at end of file +} diff --git a/components/chat/floating-chat.tsx b/components/chat/floating-chat.tsx index 07b9f42..0317285 100644 --- a/components/chat/floating-chat.tsx +++ b/components/chat/floating-chat.tsx @@ -47,6 +47,7 @@ export default function FloatingChat() { const locale = useLocale() const [isOpen, setIsOpen] = useState(false) const [isMinimized, setIsMinimized] = useState(false) + const [isFullscreen, setIsFullscreen] = useState(false) const [messages, setMessages] = useState([ { id: '1', @@ -69,6 +70,18 @@ export default function FloatingChat() { scrollToBottom() }, [messages]) + // Allow external triggers to open the chat (optionally fullscreen) + useEffect(() => { + const handler = (e: Event) => { + const detail = (e as CustomEvent).detail || {} + setIsOpen(true) + setIsMinimized(false) + if (typeof detail.fullscreen === 'boolean') setIsFullscreen(detail.fullscreen) + } + window.addEventListener('floating-chat:open', handler as EventListener) + return () => window.removeEventListener('floating-chat:open', handler as EventListener) + }, []) + const handleSendMessage = async () => { if (!inputMessage.trim() || isLoading) return @@ -151,9 +164,7 @@ export default function FloatingChat() { setIsMinimized(!isMinimized) } - const openFullChat = () => { - window.open('/chat', '_blank') - } + const toggleFullscreen = () => setIsFullscreen(prev => !prev) return ( <> @@ -185,10 +196,12 @@ export default function FloatingChat() { position: 'fixed', bottom: 0, right: 0, - width: { xs: '100vw', sm: '50vw', md: '40vw' }, + top: isFullscreen ? 0 : 'auto', + left: isFullscreen ? 0 : 'auto', + width: isFullscreen ? '100vw' : { xs: '100vw', sm: '50vw', md: '40vw' }, height: isMinimized ? 'auto' : '100vh', zIndex: 1200, - borderRadius: { xs: 0, sm: '12px 0 0 0' }, + borderRadius: isFullscreen ? 0 : { xs: 0, sm: '12px 0 0 0' }, overflow: 'hidden', display: 'flex', flexDirection: 'column', @@ -229,7 +242,7 @@ export default function FloatingChat() { @@ -354,7 +367,7 @@ export default function FloatingChat() { opacity: 0.7, }} > - {message.timestamp.toLocaleTimeString('ro-RO', { + {message.timestamp.toLocaleTimeString(locale === 'en' ? 'en-US' : 'ro-RO', { hour: '2-digit', minute: '2-digit', })} @@ -428,4 +441,4 @@ export default function FloatingChat() { ) -} \ No newline at end of file +}