85 lines
3.6 KiB
TypeScript
85 lines
3.6 KiB
TypeScript
import { useState, useMemo } from 'react';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import { Leader } from './types';
|
|
import { leaders } from './mock';
|
|
import Header from './header';
|
|
import Filter from './filter';
|
|
import LeaderCard from './LeaderCard';
|
|
|
|
|
|
|
|
export default function WriteLetterPage() {
|
|
const [selectedLeader, setSelectedLeader] = useState<Leader | null>(null);
|
|
const [searchQuery, setSearchQuery] = useState('');
|
|
const [selectedDivision, setSelectedDivision] = useState<string>('all');
|
|
|
|
const divisions = useMemo(() => {
|
|
return ['all', ...new Set(leaders.map(leader => leader.division))];
|
|
}, []);
|
|
|
|
const filteredLeaders = useMemo(() => {
|
|
return leaders.filter(leader => {
|
|
const matchesSearch = leader.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
|
|
leader.rank.toLowerCase().includes(searchQuery.toLowerCase());
|
|
const matchesDivision = selectedDivision === 'all' || leader.division === selectedDivision;
|
|
return matchesSearch && matchesDivision;
|
|
});
|
|
}, [searchQuery, selectedDivision]);
|
|
|
|
return (
|
|
<div className="min-h-screen bg-gradient-to-b from-slate-50 to-slate-100">
|
|
<Header />
|
|
|
|
<div className="container mx-auto px-4 py-8">
|
|
<Filter />
|
|
|
|
<AnimatePresence>
|
|
{filteredLeaders.length > 0 ? (
|
|
<motion.div
|
|
className="grid grid-cols-1 gap-6"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
>
|
|
{filteredLeaders.map((leader) => (
|
|
<LeaderCard
|
|
key={leader.id}
|
|
leader={leader}
|
|
isSelected={selectedLeader?.id === leader.id}
|
|
onSelect={() => setSelectedLeader(leader)}
|
|
/>
|
|
))}
|
|
</motion.div>
|
|
) : (
|
|
<motion.div
|
|
className="text-center py-12"
|
|
initial={{ opacity: 0 }}
|
|
animate={{ opacity: 1 }}
|
|
exit={{ opacity: 0 }}
|
|
>
|
|
<div className="inline-flex flex-col items-center gap-4">
|
|
<svg
|
|
className="w-16 h-16 text-gray-400"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
strokeWidth={2}
|
|
d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
<p className="text-gray-600 text-lg">
|
|
No leaders found matching your search criteria
|
|
</p>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|