ReactAnunaki / components /ReflectionView.tsx
Lukeetah's picture
Rename ReflectionView.tsx to components/ReflectionView.tsx
53a8aa1 verified
import React, { useState, useCallback, useRef, useEffect } from 'react';
import type { AlchemicalResult, ChatMessage } from '../types';
import { getSocraticResponse } from '../services/hermeticEngine';
import Spinner from './ui/Spinner';
type Tab = 'mirror' | 'quintessence' | 'dialogue';
interface Props {
result: AlchemicalResult;
}
const TabButton: React.FC<{ active: boolean; onClick: () => void; children: React.ReactNode }> = ({ active, onClick, children }) => (
<button
onClick={onClick}
className={`font-serif px-4 py-2 text-lg transition-all duration-300 border-b-2 ${
active
? 'text-white border-[#a9a3f4]'
: 'text-gray-500 border-transparent hover:text-white'
}`}
>
{children}
</button>
);
const DialogueTab: React.FC<{ result: AlchemicalResult }> = ({ result }) => {
const [history, setHistory] = useState<ChatMessage[]>([]);
const [userInput, setUserInput] = useState('');
const [isThinking, setIsThinking] = useState(false);
const chatEndRef = useRef<HTMLDivElement>(null);
useEffect(() => {
chatEndRef.current?.scrollIntoView({ behavior: 'smooth' });
}, [history]);
const handleSend = useCallback(() => {
if (!userInput.trim() && history.length > 0) return;
const userMessage: ChatMessage = { sender: 'user', text: userInput };
setHistory(prev => [...prev, userMessage]);
setUserInput('');
setIsThinking(true);
setTimeout(() => {
const aethelredResponse = getSocraticResponse(result, history);
setHistory(prev => [...prev, aethelredResponse]);
setIsThinking(false);
}, 1500 + Math.random() * 500);
}, [userInput, result, history]);
useEffect(() => {
// Initial message from Aethelred
setIsThinking(true);
setTimeout(() => {
const initialQuestion = getSocraticResponse(result, []);
setHistory([initialQuestion]);
setIsThinking(false);
}, 1000);
}, [result]);
return (
<div className="flex flex-col h-[500px] bg-[#111111] p-4 rounded-b-lg">
<div className="flex-grow overflow-y-auto pr-2">
{history.map((msg, index) => (
<div key={index} className={`flex ${msg.sender === 'user' ? 'justify-end' : 'justify-start'} mb-4`}>
<div className={`max-w-xs md:max-w-md p-3 rounded-lg ${msg.sender === 'user' ? 'bg-[#a9a3f4] text-black' : 'bg-[#2a2a2a] text-gray-300'}`}>
<p className="font-serif text-lg">{msg.text}</p>
</div>
</div>
))}
{isThinking && (
<div className="flex justify-start mb-4">
<div className="max-w-xs md:max-w-md p-3 rounded-lg bg-[#2a2a2a] text-gray-300 flex items-center">
<Spinner/>
</div>
</div>
)}
<div ref={chatEndRef} />
</div>
<div className="mt-4 flex">
<input
type="text"
value={userInput}
onChange={(e) => setUserInput(e.target.value)}
onKeyPress={(e) => e.key === 'Enter' && !isThinking && handleSend()}
placeholder="Responde o pregunta..."
className="flex-grow p-3 bg-[#181818] border border-gray-700 rounded-l-md focus:outline-none focus:ring-1 focus:ring-[#a9a3f4] text-white"
disabled={isThinking}
/>
<button onClick={handleSend} disabled={isThinking} className="px-6 py-2 bg-[#a9a3f4] text-black rounded-r-md font-bold hover:bg-white disabled:bg-gray-600 transition-colors">
Enviar
</button>
</div>
</div>
);
};
export default function ReflectionView({ result }: Props) {
const [activeTab, setActiveTab] = useState<Tab>('mirror');
return (
<div className="w-full bg-[#181818] rounded-lg shadow-2xl shadow-black/30">
<nav className="flex justify-around border-b border-gray-700">
<TabButton active={activeTab === 'mirror'} onClick={() => setActiveTab('mirror')}>El Espejo Hermético</TabButton>
<TabButton active={activeTab === 'quintessence'} onClick={() => setActiveTab('quintessence')}>La Quintaesencia</TabButton>
<TabButton active={activeTab === 'dialogue'} onClick={() => setActiveTab('dialogue')}>El Diálogo Alquímico</TabButton>
</nav>
<div className="p-4 md:p-8 min-h-[500px]">
{activeTab === 'mirror' && (
<div className="text-center animate-fade-in">
<h3 className="font-serif text-3xl text-[#a9a3f4] mb-4">{result.mirror.archetype}</h3>
<div className="grid md:grid-cols-2 gap-8 mt-8">
<div>
<h4 className="font-serif text-2xl text-white border-b-2 border-green-400 pb-2 mb-3">Principio en Luz</h4>
<p className="text-xl font-bold mb-2">{result.mirror.principleInLight.name}</p>
<p className="text-gray-400 italic">{result.mirror.principleInLight.description}</p>
</div>
<div>
<h4 className="font-serif text-2xl text-white border-b-2 border-red-400 pb-2 mb-3">Principio en Sombra</h4>
<p className="text-xl font-bold mb-2">{result.mirror.principleInShadow.name}</p>
<p className="text-gray-400 italic">{result.mirror.principleInShadow.description}</p>
</div>
</div>
</div>
)}
{activeTab === 'quintessence' && (
<div className="flex items-center justify-center h-full min-h-[400px] animate-fade-in">
<p className="font-serif text-2xl md:text-3xl text-center max-w-2xl leading-relaxed italic text-gray-300">
"{result.quintessence}"
</p>
</div>
)}
{activeTab === 'dialogue' && <DialogueTab result={result} />}
</div>
</div>
);
}