Require user authentication for AI chat functionality

- Update chat API to require valid authentication tokens for all requests
- Add authentication requirement screens to both chat components
- Show "Create Account / Sign In" prompts for unauthenticated users
- Hide chat input and functionality until user is logged in
- Return 401 errors with clear messages when authentication is missing
- Maintain bilingual support (Romanian/English) for auth prompts

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-28 20:22:57 +00:00
parent e4b815cb40
commit 83a981cabc
3 changed files with 182 additions and 83 deletions

View File

@@ -1,13 +1,14 @@
'use client'
import { useState, useRef, useEffect } from 'react'
import { Send } from 'lucide-react'
import { Send, User } from 'lucide-react'
import ReactMarkdown from 'react-markdown'
export function ChatInterface() {
const [messages, setMessages] = useState<Array<{ role: string; content: string }>>([])
const [input, setInput] = useState('')
const [loading, setLoading] = useState(false)
const [isAuthenticated, setIsAuthenticated] = useState(false)
const messagesEndRef = useRef<HTMLDivElement>(null)
const scrollToBottom = () => {
@@ -16,6 +17,24 @@ export function ChatInterface() {
useEffect(scrollToBottom, [messages])
// Check authentication status on mount
useEffect(() => {
const checkAuth = async () => {
try {
const token = localStorage.getItem('authToken')
if (token) {
const response = await fetch('/api/auth/me', {
headers: { 'Authorization': `Bearer ${token}` }
})
setIsAuthenticated(response.ok)
}
} catch (error) {
setIsAuthenticated(false)
}
}
checkAuth()
}, [])
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault()
if (!input.trim() || loading) return
@@ -64,14 +83,32 @@ export function ChatInterface() {
</div>
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.length === 0 && (
<div className="text-center text-gray-500 mt-12">
<p>Bună ziua! Sunt aici ajut cu întrebările despre Biblie.</p>
<p className="text-sm mt-2">Puteți începe prin a întreba ceva despre un verset sau o temă biblică.</p>
{!isAuthenticated ? (
<div className="flex flex-col items-center justify-center h-full text-center p-6">
<User className="w-16 h-16 text-gray-400 mb-4" />
<h3 className="text-lg font-semibold mb-2">Bun venit la AI Chat Biblic!</h3>
<p className="text-gray-600 mb-4 max-w-md">
Pentru a accesa chat-ul AI și a salva conversațiile tale, te rugăm îți creezi un cont sau te conectezi.
</p>
<button
onClick={() => {
window.dispatchEvent(new CustomEvent('auth:sign-in-required'))
}}
className="px-6 py-3 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
>
Creează Cont / Conectează-te
</button>
</div>
)}
) : (
<>
{messages.length === 0 && (
<div className="text-center text-gray-500 mt-12">
<p>Bună ziua! Sunt aici ajut cu întrebările despre Biblie.</p>
<p className="text-sm mt-2">Puteți începe prin a întreba ceva despre un verset sau o temă biblică.</p>
</div>
)}
{messages.map((msg, idx) => (
{messages.map((msg, idx) => (
<div
key={idx}
className={`flex ${msg.role === 'user' ? 'justify-end' : 'justify-start'}`}
@@ -106,29 +143,33 @@ export function ChatInterface() {
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</>
)}
<div ref={messagesEndRef} />
</div>
<form onSubmit={handleSubmit} className="p-4 border-t">
<div className="flex space-x-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Întreabă despre Biblie..."
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
disabled={loading}
/>
<button
type="submit"
disabled={loading || !input.trim()}
className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<Send className="w-5 h-5" />
</button>
</div>
</form>
{isAuthenticated && (
<form onSubmit={handleSubmit} className="p-4 border-t">
<div className="flex space-x-2">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
placeholder="Întreabă despre Biblie..."
className="flex-1 px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
disabled={loading}
/>
<button
type="submit"
disabled={loading || !input.trim()}
className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
>
<Send className="w-5 h-5" />
</button>
</div>
</form>
)}
</div>
)
}