ORA / landing_legacy /src /App.tsx
Abdalkaderdev's picture
Initial ORA deployment
5e0532d
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;