Spaces:
Paused
Paused
| import { useState } from 'react'; | |
| import { motion, AnimatePresence } from 'framer-motion'; | |
| import { Sparkles, MessageSquare, BookOpen, ArrowRight, History, Settings, LogOut } from 'lucide-react'; | |
| import { clsx, type ClassValue } from 'clsx'; | |
| import { twMerge } from 'tailwind-merge'; | |
| import { AuraOrb } from './components/AuraOrb'; | |
| import { AuraChat } from './components/AuraChat'; | |
| // --- Utils --- | |
| function cn(...inputs: ClassValue[]) { | |
| return twMerge(clsx(inputs)); | |
| } | |
| // --- Components --- | |
| const Navbar = ({ onStart }: { onStart: () => void }) => ( | |
| <nav className="fixed top-0 w-full z-50 border-b border-white/5 bg-background/50 backdrop-blur-md"> | |
| <div className="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between"> | |
| <div className="flex items-center gap-2"> | |
| <div className="w-8 h-8 rounded-full bg-gradient-to-tr from-cyan-500 to-emerald-500 flex items-center justify-center"> | |
| <Sparkles className="w-4 h-4 text-white" /> | |
| </div> | |
| <span className="font-bold text-lg tracking-tight">ORA</span> | |
| </div> | |
| <div className="flex gap-6 text-sm text-secondary"> | |
| <a href="#features" className="hover:text-white transition-colors">Features</a> | |
| <a href="#vision" className="hover:text-white transition-colors">Vision</a> | |
| <a href="#api" className="hover:text-white transition-colors">API</a> | |
| </div> | |
| <button | |
| onClick={onStart} | |
| className="px-4 py-2 bg-white text-black text-sm font-medium rounded-full hover:bg-zinc-200 transition-colors"> | |
| Get Started | |
| </button> | |
| </div> | |
| </nav> | |
| ); | |
| const Sidebar = ({ onViewChange, currentView }: { onViewChange: (v: string) => void, currentView: string }) => ( | |
| <div className="w-20 md:w-64 h-screen border-r border-white/5 bg-zinc-950 flex flex-col p-4 fixed left-0 top-0 z-40"> | |
| <div className="flex items-center gap-3 px-2 mb-10 mt-2"> | |
| <div className="w-8 h-8 rounded-lg bg-cyan-500 flex items-center justify-center shrink-0"> | |
| <Sparkles className="w-5 h-5 text-white" /> | |
| </div> | |
| <span className="font-bold hidden md:block">ORA AURA</span> | |
| </div> | |
| <div className="flex-1 space-y-2"> | |
| {[ | |
| { id: 'chat', label: 'Spiritual Study', icon: MessageSquare }, | |
| { id: 'memory', label: 'Episodic Memory', icon: History }, | |
| { id: 'journal', label: 'Growth Journal', icon: BookOpen }, | |
| ].map(item => ( | |
| <button | |
| key={item.id} | |
| onClick={() => onViewChange(item.id)} | |
| className={cn( | |
| "w-full flex items-center gap-3 p-3 rounded-xl transition-all group", | |
| currentView === item.id ? "bg-white/10 text-white" : "text-zinc-500 hover:bg-white/5 hover:text-zinc-300" | |
| )} | |
| > | |
| <item.icon className={cn("w-5 h-5", currentView === item.id ? "text-cyan-400" : "text-zinc-500 group-hover:text-zinc-300")} /> | |
| <span className="hidden md:block font-medium text-sm">{item.label}</span> | |
| </button> | |
| ))} | |
| </div> | |
| <div className="pt-4 border-t border-white/5 space-y-2"> | |
| <button className="w-full flex items-center gap-3 p-3 text-zinc-500 hover:text-zinc-300 transition-colors"> | |
| <Settings className="w-5 h-5" /> | |
| <span className="hidden md:block text-sm">Settings</span> | |
| </button> | |
| <button | |
| onClick={() => window.location.reload()} | |
| className="w-full flex items-center gap-3 p-3 text-zinc-500 hover:text-red-400 transition-colors" | |
| > | |
| <LogOut className="w-5 h-5" /> | |
| <span className="hidden md:block text-sm">Exit</span> | |
| </button> | |
| </div> | |
| </div> | |
| ); | |
| const Hero = ({ onStart }: { onStart: () => void }) => { | |
| return ( | |
| <section className="relative min-h-screen flex flex-col items-center justify-center pt-20 overflow-hidden"> | |
| {/* Background Glow */} | |
| <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[600px] h-[600px] bg-cyan-500/20 rounded-full blur-[120px] pointer-events-none" /> | |
| <div className="relative z-10 text-center px-6 max-w-4xl mx-auto space-y-8"> | |
| <motion.div | |
| initial={{ opacity: 0, y: 20 }} | |
| animate={{ opacity: 1, y: 0 }} | |
| transition={{ duration: 0.8 }} | |
| className="space-y-4" | |
| > | |
| <div className="inline-flex items-center gap-2 px-3 py-1 rounded-full border border-white/10 bg-white/5 text-xs text-cyan-400 font-mono mb-4"> | |
| <span className="relative flex h-2 w-2"> | |
| <span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-cyan-400 opacity-75"></span> | |
| <span className="relative inline-flex rounded-full h-2 w-2 bg-cyan-500"></span> | |
| </span> | |
| SYSTEM ONLINE: v1.0.0 | |
| </div> | |
| <h1 className="text-5xl md:text-7xl font-bold tracking-tighter leading-tight bg-gradient-to-b from-white to-white/50 bg-clip-text text-transparent"> | |
| Your AI Spiritual <br /> Companion. | |
| </h1> | |
| <p className="text-xl text-secondary max-w-xl mx-auto leading-relaxed"> | |
| Observe. Reflect. Act. <br /> | |
| ORA uses advanced intelligence to guide your spiritual journey, grounded in biblical wisdom. | |
| </p> | |
| </motion.div> | |
| <motion.div | |
| initial={{ opacity: 0, scale: 0.95 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| transition={{ delay: 0.2, duration: 0.5 }} | |
| className="flex flex-col sm:flex-row gap-4 justify-center" | |
| > | |
| <button | |
| onClick={onStart} | |
| className="px-8 py-3 bg-white text-black font-semibold rounded-full hover:scale-105 transition-transform flex items-center gap-2"> | |
| Try ORA Chat <ArrowRight className="w-4 h-4" /> | |
| </button> | |
| <button className="px-8 py-3 ring-1 ring-white/20 bg-white/5 backdrop-blur-sm text-white font-medium rounded-full hover:bg-white/10 transition-colors"> | |
| View Documentation | |
| </button> | |
| </motion.div> | |
| </div> | |
| </section> | |
| ); | |
| }; | |
| const FeatureCard = ({ icon: Icon, title, desc }: { icon: any, title: string, desc: string }) => ( | |
| <div className="p-6 rounded-2xl bg-zinc-900/50 border border-white/5 hover:border-cyan-500/30 transition-colors group"> | |
| <div className="w-12 h-12 rounded-lg bg-zinc-800 flex items-center justify-center mb-4 group-hover:bg-cyan-500/20 transition-colors"> | |
| <Icon className="w-6 h-6 text-cyan-400" /> | |
| </div> | |
| <h3 className="text-xl font-bold mb-2 text-white">{title}</h3> | |
| <p className="text-secondary leading-relaxed">{desc}</p> | |
| </div> | |
| ); | |
| const Features = () => ( | |
| <section id="features" className="py-24 px-6 border-t border-white/5 bg-surface"> | |
| <div className="max-w-7xl mx-auto"> | |
| <div className="grid md:grid-cols-3 gap-8"> | |
| <FeatureCard | |
| icon={BookOpen} | |
| title="Biblical Wisdom" | |
| desc="Grounded in scripture. ORA helps you find relevant verses and context for your daily life." | |
| /> | |
| <FeatureCard | |
| icon={MessageSquare} | |
| title="Spiritual Dialogue" | |
| desc="A safe, judgment-free space to ask tough questions and explore your faith journey." | |
| /> | |
| <FeatureCard | |
| icon={Sparkles} | |
| title="Sovereign AI" | |
| desc="Runs locally or on your private cloud. Your data and prayers never leave your ecosystem." | |
| /> | |
| </div> | |
| </div> | |
| </section> | |
| ); | |
| function App() { | |
| const [view, setView] = useState<'landing' | 'dashboard'>('landing'); | |
| const [dashView, setDashView] = useState('chat'); | |
| return ( | |
| <div className="min-h-screen bg-background text-white selection:bg-cyan-500/30 font-sans"> | |
| <AnimatePresence mode="wait"> | |
| {view === 'landing' ? ( | |
| <motion.div | |
| key="landing" | |
| exit={{ opacity: 0, y: -20 }} | |
| transition={{ duration: 0.5 }} | |
| > | |
| <Navbar onStart={() => setView('dashboard')} /> | |
| <Hero onStart={() => setView('dashboard')} /> | |
| <Features /> | |
| <footer className="py-12 text-center text-sm text-zinc-600 border-t border-white/5"> | |
| <p>© 2025 SoapBox Super App. Powered by ORA Intelligence.</p> | |
| </footer> | |
| </motion.div> | |
| ) : ( | |
| <motion.div | |
| key="dashboard" | |
| initial={{ opacity: 0, scale: 0.98 }} | |
| animate={{ opacity: 1, scale: 1 }} | |
| className="flex min-h-screen pl-20 md:pl-64" | |
| > | |
| <Sidebar onViewChange={setDashView} currentView={dashView} /> | |
| <main className="flex-1 relative flex flex-col md:flex-row h-screen overflow-hidden"> | |
| {/* Dashboard Background */} | |
| <div className="absolute top-0 right-0 w-[500px] h-[500px] bg-cyan-500/5 rounded-full blur-[100px] pointer-events-none" /> | |
| {/* Left Side: Aura Orb */} | |
| <div className="hidden lg:flex flex-1 flex-col items-center justify-center p-12 border-r border-white/5"> | |
| <div className="text-center space-y-4 mb-8"> | |
| <h2 className="text-3xl font-bold tracking-tight">The Presence</h2> | |
| <p className="text-zinc-500 text-sm max-w-xs">ORA's focused state. Watch the aura shift as we reason together.</p> | |
| </div> | |
| <AuraOrb state="idle" /> | |
| </div> | |
| {/* Right Side: Chat */} | |
| <div className="flex-[1.5] flex flex-col p-4 md:p-8 h-full"> | |
| <AuraChat /> | |
| </div> | |
| </main> | |
| </motion.div> | |
| )} | |
| </AnimatePresence> | |
| </div> | |
| ); | |
| } | |
| export default App; | |