import React, { useState, useEffect } from 'react'; import { ChevronDown, Plus, Info, MessageSquare, BookOpen, LogOut, PanelLeftClose, MessageCircle, AlertTriangle, Menu, PanelRightClose, RefreshCw } from 'lucide-react'; import SimulationGraph from './SimulationGraph'; import { GradioService } from '../services/gradioService'; interface SimulationPageProps { onBack: () => void; onOpenConversation: () => void; onOpenChat: () => void; user?: any; onLogin?: () => void; simulationResult: any; setSimulationResult: (res: any) => void; } // Define the data structure for filters const VIEW_FILTERS: Record> = { 'Country': [ { label: "United States", color: "bg-blue-600" }, { label: "United Kingdom", color: "bg-purple-600" }, { label: "Netherlands", color: "bg-teal-600" }, { label: "France", color: "bg-orange-600" }, { label: "India", color: "bg-pink-600" } ], 'Job Title': [ { label: "Founder", color: "bg-indigo-500" }, { label: "Product Manager", color: "bg-emerald-500" }, { label: "Engineer", color: "bg-rose-500" }, { label: "Investor", color: "bg-amber-500" }, { label: "Designer", color: "bg-fuchsia-500" } ], 'Sentiment': [ { label: "Positive", color: "bg-green-500" }, { label: "Neutral", color: "bg-gray-500" }, { label: "Negative", color: "bg-red-500" }, { label: "Mixed", color: "bg-yellow-500" } ], 'Activity Level': [ { label: "Power User", color: "bg-red-600" }, { label: "Daily Active", color: "bg-orange-500" }, { label: "Weekly Active", color: "bg-blue-500" }, { label: "Lurker", color: "bg-slate-600" } ] }; const SimulationPage: React.FC = ({ onBack, onOpenConversation, onOpenChat, user, onLogin, simulationResult, setSimulationResult }) => { const [society, setSociety] = useState(''); const [societies, setSocieties] = useState([]); const [viewMode, setViewMode] = useState('Job Title'); const [isRefreshing, setIsRefreshing] = useState(false); const [isBuilding, setIsBuilding] = useState(false); const [isRightPanelOpen, setIsRightPanelOpen] = useState(window.innerWidth > 1200); const [isLeftPanelOpen, setIsLeftPanelOpen] = useState(window.innerWidth > 768); // Handle window resize for mobile responsiveness useEffect(() => { const handleResize = () => { if (window.innerWidth < 768) { setIsLeftPanelOpen(false); setIsRightPanelOpen(false); } }; window.addEventListener('resize', handleResize); // Fetch real focus groups const fetchSocieties = async () => { try { const result = await GradioService.listSimulations(); // Handle both direct array and Gradio data wrap const list = Array.isArray(result) ? result : (result?.data?.[0] || []); if (Array.isArray(list)) { const names = list .map((s: any) => { if (typeof s === 'string') return s; if (typeof s === 'object' && s !== null) return s.id || s.name || ''; return ''; }) .filter(name => name.length > 0 && !name.toLowerCase().includes('default') && !name.toLowerCase().includes('template')); setSocieties(names); if (names.length > 0 && (!society || !names.includes(society))) { setSociety(names[0]); } } } catch (e) { console.error("Failed to fetch focus groups", e); } }; fetchSocieties(); return () => window.removeEventListener('resize', handleResize); }, []); // Function to simulate rebuilding the graph when settings change const handleSettingChange = (setter: (val: string) => void, value: string) => { if (value === society || (value === viewMode && setter === setViewMode)) return; // No change setter(value); setIsBuilding(true); // Simulate network delay setTimeout(() => { setIsBuilding(false); }, 1500); }; const currentFilters = VIEW_FILTERS[viewMode] || VIEW_FILTERS['Country']; return (
{/* Sidebar */} {/* Main Content Area */}
{/* Top Navigation Overlay */}
{/* Left Toggle (when sidebar closed) */} {/* Right Toggle (when output closed) */}
{/* Legend / Filter Chips */}
{currentFilters.map((filter, idx) => ( ))}
{/* Graph Container */}
{/* Floating Chat Button (Bottom) */}
{/* Right Sidebar (Output) */}
); }; // Helper Components interface MenuItemProps { icon: React.ReactNode; label: string; highlight?: boolean; } const MenuItem: React.FC = ({ icon, label, highlight = false }) => ( ); interface FilterChipProps { color: string; label: string; } const FilterChip: React.FC = ({ color, label }) => ( ); export default SimulationPage;