'use client'; import { useState, useMemo } from 'react'; import { Search, User, Share2, Users, Check, X, ExternalLink } from 'lucide-react'; import Link from 'next/link'; interface Split { id: string; public_slug: string; host_id: string; total_volume: number; host_share: number; price_bottle: number; is_active: boolean; created_at: string; host: { username: string; display_name: string | null }; bottle: { id: string; name: string; distillery: string | null; image_url: string | null } | null; participantCount: number; totalReserved: number; } interface AdminSplitsListProps { splits: Split[]; } export default function AdminSplitsList({ splits }: AdminSplitsListProps) { const [search, setSearch] = useState(''); const [filterHost, setFilterHost] = useState(null); const [filterStatus, setFilterStatus] = useState<'all' | 'active' | 'closed'>('all'); // Get unique hosts for filter const hosts = useMemo(() => { const hostMap = new Map(); splits.forEach(s => { hostMap.set(s.host_id, s.host.display_name || s.host.username); }); return Array.from(hostMap.entries()).sort((a, b) => a[1].localeCompare(b[1])); }, [splits]); // Filter splits const filteredSplits = useMemo(() => { let result = splits; if (search) { const searchLower = search.toLowerCase(); result = result.filter(s => s.bottle?.name?.toLowerCase().includes(searchLower) || s.bottle?.distillery?.toLowerCase().includes(searchLower) || s.host.username.toLowerCase().includes(searchLower) || s.public_slug.toLowerCase().includes(searchLower) ); } if (filterHost) { result = result.filter(s => s.host_id === filterHost); } if (filterStatus === 'active') { result = result.filter(s => s.is_active); } else if (filterStatus === 'closed') { result = result.filter(s => !s.is_active); } return result; }, [splits, search, filterHost, filterStatus]); return (
{/* Filters */}
setSearch(e.target.value)} placeholder="Search bottles, hosts, or slugs..." className="w-full pl-12 pr-4 py-3 bg-zinc-900 border border-zinc-800 rounded-xl text-white placeholder-zinc-600 focus:outline-hidden focus:border-orange-600" />
{/* Results */}
Showing {filteredSplits.length} of {splits.length} splits
{/* Splits Grid */}
{filteredSplits.map(split => { const available = split.total_volume - split.host_share; const remaining = available - split.totalReserved; const fillPercent = Math.min(100, (split.totalReserved / available) * 100); return (
{/* Image */}
{split.bottle?.image_url ? ( {split.bottle.name ) : (
)} {/* Status Badge */} {split.is_active ? : } {split.is_active ? 'Active' : 'Closed'} {/* Participants Badge */} {split.participantCount}
{/* Info */}

{split.bottle?.name || 'Unknown Bottle'}

{split.bottle?.distillery || 'Unknown Distillery'}

{/* Progress Bar */}
{split.totalReserved}cl reserved {remaining}cl left
{/* Details */}
{split.host.display_name || split.host.username} {new Date(split.created_at).toLocaleDateString('de-DE')}
{/* Price & Link */}
{split.price_bottle.toFixed(2)}€ {split.public_slug}
); })}
{/* Empty State */} {filteredSplits.length === 0 && (

No Splits Found

No bottle splits match your filters.

)}
); }