import React, { useState, useMemo } from 'react';
import { EBOOKS } from './constants';
import { Book, Category } from './types';
import { BookCard } from './components/BookCard';
import { FunnelSection } from './components/FunnelSection';
const App: React.FC = () => {
const [selectedCategory, setSelectedCategory] = useState<Category | 'All'>('All');
const [selectedAuthor, setSelectedAuthor] = useState<string>('All');
const [searchQuery, setSearchQuery] = useState<string>('');
const [activeBook, setActiveBook] = useState<Book | null>(null);
// Derive unique authors for filter
const authors = useMemo(() => {
const list = Array.from(new Set(EBOOKS.map(b => b.author)));
return ['All', ...list];
}, []);
const filteredBooks = useMemo(() => {
return EBOOKS.filter(book => {
const matchesCategory = selectedCategory === 'All' || book.category === selectedCategory;
const matchesAuthor = selectedAuthor === 'All' || book.author === selectedAuthor;
const search = searchQuery.toLowerCase();
const matchesSearch =
book.title.toLowerCase().includes(search) ||
book.description.toLowerCase().includes(search) ||
book.author.toLowerCase().includes(search) ||
book.category.toLowerCase().includes(search);
return matchesCategory && matchesAuthor && matchesSearch;
});
}, [selectedCategory, selectedAuthor, searchQuery]);
return (
<div className="min-h-screen flex flex-col">
{/* Navigation */}
<nav className="sticky top-0 z-40 bg-brand-blue text-white shadow-xl">
<div className="max-w-7xl mx-auto px-4 h-20 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="bg-brand-neon p-2 rounded-lg shadow-[0_0_15px_rgba(57,255,20,0.4)]">
<svg className="w-6 h-6 text-brand-blue" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
</svg>
</div>
<h1 className="font-display font-extrabold text-xl lg:text-2xl tracking-tight">
ENCOURAGING <span className="text-brand-neon">WORDS eBOOKS</span>
</h1>
</div>
<div className="hidden md:flex items-center gap-8 text-sm font-semibold">
<a href="#" className="hover:text-brand-neon transition-colors">Home</a>
<a href="#gallery" className="hover:text-brand-neon transition-colors">The Gallery</a>
<a href="#" className="hover:text-brand-neon transition-colors">Our Mission</a>
<button className="bg-brand-neon text-brand-blue px-6 py-2 rounded-full font-bold hover:bg-white transition-all transform hover:scale-105 shadow-lg">
My Library
</button>
</div>
</div>
</nav>
{/* Hero Section */}
<header className="relative py-20 lg:py-32 bg-slate-50 overflow-hidden">
<div className="absolute top-0 right-0 w-1/2 h-full bg-brand-blue skew-x-12 transform translate-x-20 z-0"></div>
<div className="max-w-7xl mx-auto px-4 relative z-10 grid lg:grid-cols-2 items-center gap-12">
<div className="space-y-8 animate-in slide-in-from-left duration-700">
<div>
<span className="bg-brand-neon/20 text-brand-blue font-bold px-4 py-1.5 rounded-full text-xs uppercase tracking-widest border border-brand-neon/30">
Ancient Biblical Wisdom for Modern Times
</span>
<h2 className="mt-6 font-display font-extrabold text-5xl lg:text-7xl text-slate-900 leading-[1.1]">
Inspiring <span className="text-brand-blue underline decoration-brand-neon decoration-8 underline-offset-4">Success</span> through Faith
</h2>
</div>
<p className="text-lg text-slate-600 max-w-lg leading-relaxed">
Discover a curated library dedicated to spiritual growth, church revitalization, and the art of biblical salesmanship.
</p>
<div className="flex flex-wrap gap-4">
<a href="#gallery" className="bg-brand-blue hover:bg-slate-900 text-white font-bold py-4 px-10 rounded-xl shadow-lg transition-all flex items-center gap-2">
Explore Library
</a>
<button className="bg-white hover:bg-slate-50 text-slate-900 border border-slate-200 font-bold py-4 px-10 rounded-xl shadow-sm transition-all">
The Mission
</button>
</div>
</div>
<div className="hidden lg:flex justify-center animate-in slide-in-from-right duration-700">
<div className="relative">
<div className="absolute -inset-10 bg-brand-neon/20 blur-[100px] rounded-full"></div>
<img
src="https://picsum.photos/seed/echobook/600/800"
alt="Featured Book"
className="w-80 h-auto rounded-2xl shadow-[0_50px_100px_rgba(0,0,0,0.3)] transform rotate-2 relative z-10 border-8 border-white"
/>
<div className="absolute -bottom-6 -right-10 bg-brand-neon p-6 rounded-2xl shadow-xl z-20 animate-bounce">
<p className="text-brand-blue font-black text-2xl">New Release</p>
<p className="text-xs text-brand-blue/70 uppercase font-bold tracking-tighter">Available Today</p>
</div>
</div>
</div>
</div>
</header>
{/* Book Gallery Section */}
<section id="gallery" className="py-24 bg-white">
<div className="max-w-7xl mx-auto px-4">
<div className="mb-12 space-y-8">
<div className="text-center max-w-3xl mx-auto space-y-4">
<h3 className="font-display font-black text-4xl lg:text-5xl text-slate-900">The Digital Shelf</h3>
<p className="text-slate-500 text-lg leading-relaxed">
Filter by genre or search keywords to find the exact wisdom your mission requires.
</p>
</div>
{/* Advanced Filter Bar */}
<div className="bg-slate-50 p-6 rounded-3xl border border-slate-200 shadow-sm space-y-6">
<div className="grid md:grid-cols-4 gap-4">
{/* Search Bar */}
<div className="md:col-span-2 relative">
<div className="absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none">
<svg className="h-5 w-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
</div>
<input
type="text"
placeholder="Search by title, description or keywords..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="block w-full pl-11 pr-4 py-4 bg-white border border-slate-200 rounded-2xl focus:ring-2 focus:ring-brand-neon focus:border-transparent transition-all outline-none text-slate-900 font-medium"
/>
</div>
{/* Author Filter */}
<div className="relative">
<select
value={selectedAuthor}
onChange={(e) => setSelectedAuthor(e.target.value)}
className="block w-full px-4 py-4 bg-white border border-slate-200 rounded-2xl appearance-none focus:ring-2 focus:ring-brand-neon outline-none text-slate-900 font-medium cursor-pointer"
>
<option value="All">All Authors</option>
{authors.filter(a => a !== 'All').map(a => (
<option key={a} value={a}>{a}</option>
))}
</select>
<div className="absolute inset-y-0 right-0 pr-4 flex items-center pointer-events-none text-slate-400">
<svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M19 9l-7 7-7-7" />
</svg>
</div>
</div>
{/* Reset Button */}
<button
onClick={() => {
setSearchQuery('');
setSelectedCategory('All');
setSelectedAuthor('All');
}}
className="px-4 py-4 bg-slate-200 hover:bg-slate-300 text-slate-700 font-bold rounded-2xl transition-all"
>
Clear All
</button>
</div>
{/* Genre Filter Chips */}
<div className="flex flex-wrap items-center gap-3">
<span className="text-xs font-bold text-slate-400 uppercase tracking-widest mr-2">Quick Genres:</span>
{['All', ...Object.values(Category)].map((cat) => (
<button
key={cat}
onClick={() => setSelectedCategory(cat as any)}
className={`px-6 py-2 rounded-xl text-xs font-black transition-all border-2 ${
selectedCategory === cat
? 'bg-brand-blue border-brand-blue text-white shadow-[0_5px_15px_rgba(30,64,175,0.3)]'
: 'bg-white border-slate-200 text-slate-600 hover:border-brand-neon'
}`}
>
{cat}
</button>
))}
</div>
</div>
</div>
{/* Results Summary */}
<div className="flex items-center justify-between mb-8 px-2">
<p className="text-sm font-medium text-slate-500">
Showing <span className="text-brand-blue font-bold">{filteredBooks.length}</span> eBooks
{searchQuery && <span> for "<span className="italic">{searchQuery}</span>"</span>}
</p>
</div>
{/* Gallery Grid */}
<div className="grid sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 gap-8">
{filteredBooks.map((book) => (
<BookCard
key={book.id}
book={book}
onSelect={setActiveBook}
/>
))}
</div>
{filteredBooks.length === 0 && (
<div className="text-center py-32 bg-slate-50 rounded-[3rem] border-2 border-dashed border-slate-200">
<div className="max-w-xs mx-auto space-y-4">
<div className="w-16 h-16 bg-slate-200 rounded-full flex items-center justify-center mx-auto text-slate-400">
<svg className="w-8 h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9.172 9.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</div>
<h4 className="font-display font-bold text-xl text-slate-900">No match found</h4>
<p className="text-slate-500 text-sm">
We couldn't find any books matching your current search criteria. Try broadening your filters.
</p>
<button
onClick={() => { setSearchQuery(''); setSelectedCategory('All'); setSelectedAuthor('All'); }}
className="text-brand-blue font-bold hover:underline"
>
Reset all filters
</button>
</div>
</div>
)}
</div>
</section>
{/* Funnel Modal */}
{activeBook && (
<FunnelSection
book={activeBook}
onClose={() => setActiveBook(null)}
/>
)}
{/* Footer (Condensed for space) */}
<footer className="bg-slate-900 text-white pt-24 pb-12 overflow-hidden relative">
<div className="absolute top-0 left-0 w-full h-1 bg-gradient-to-r from-brand-blue via-brand-neon to-brand-blue"></div>
<div className="max-w-7xl mx-auto px-4 grid md:grid-cols-4 gap-12 relative z-10">
<div className="md:col-span-2 space-y-6">
<h2 className="font-display font-extrabold text-3xl tracking-tight">
ENCOURAGING <span className="text-brand-neon">WORDS eBOOKS</span>
</h2>
<p className="text-slate-400 max-w-sm leading-relaxed">
Equipping Believers to lead with integrity, Churches to grow with purpose, and individuals to live with hope.
</p>
<div className="flex gap-4">
{['FB', 'TW', 'IG', 'LI'].map(social => (
<div key={social} className="w-10 h-10 rounded-xl bg-white/5 border border-white/10 flex items-center justify-center hover:bg-brand-neon hover:text-brand-blue transition-all cursor-pointer font-bold text-xs">
{social}
</div>
))}
</div>
</div>
<div className="space-y-6">
<h5 className="font-black text-brand-neon uppercase tracking-widest text-sm">Navigation</h5>
<ul className="space-y-4 text-slate-400 text-sm font-medium">
<li className="hover:text-white transition-colors cursor-pointer">Digital Gallery</li>
<li className="hover:text-white transition-colors cursor-pointer">Author Program</li>
<li className="hover:text-white transition-colors cursor-pointer">Bundle Deals</li>
<li className="hover:text-white transition-colors cursor-pointer">Corporate Licensing</li>
</ul>
</div>
<div className="space-y-6">
<h5 className="font-black text-brand-neon uppercase tracking-widest text-sm">Support</h5>
<ul className="space-y-4 text-slate-400 text-sm font-medium">
<li className="hover:text-white transition-colors cursor-pointer">Contact Mission</li>
<li className="hover:text-white transition-colors cursor-pointer">Affiliate Program</li>
<li className="hover:text-white transition-colors cursor-pointer">Redeem Access Code</li>
<li className="hover:text-white transition-colors cursor-pointer">Secure Checkout</li>
</ul>
</div>
</div>
<div className="max-w-7xl mx-auto px-4 mt-24 pt-8 border-t border-white/5 text-center flex flex-col md:flex-row justify-between items-center gap-4 text-slate-500 text-[10px] uppercase tracking-widest">
<span>© {new Date().getFullYear()} Echouraging Words eBooks. Kingdom Built.</span>
<div className="flex gap-8">
<span className="cursor-pointer hover:text-white transition-colors">Privacy</span>
<span className="cursor-pointer hover:text-white transition-colors">Terms</span>
<span className="cursor-pointer hover:text-white transition-colors">Stripe Secure</span>
</div>
</div>
</footer>
</div>
);
};
export default App;