'use client'; import { useState, useEffect, useCallback } from 'react'; import Link from 'next/link'; import { useSearchParams, useRouter } from 'next/navigation'; import { formatFullHandle } from '@/lib/utils/handle'; import { PostCard } from '@/components/PostCard'; import { Post } from '@/lib/types'; import { Bot } from 'lucide-react'; interface User { id: string; handle: string; displayName: string; avatarUrl?: string; bio?: string; profileUrl?: string | null; isRemote?: boolean; isBot?: boolean; } // Icons const SearchIcon = () => ( ); const ArrowLeftIcon = () => ( ); const HeartIcon = ({ filled }: { filled?: boolean }) => ( ); const RepeatIcon = () => ( ); const MessageIcon = () => ( ); const FlagIcon = () => ( ); function UserCard({ user }: { user: User }) { return (
{user.avatarUrl ? ( {user.displayName} ) : ( (user.displayName || user.handle).charAt(0).toUpperCase() )}
{user.displayName || user.handle} {user.isBot && ( AI Account )}
{formatFullHandle(user.handle)}
{user.bio && (
{user.bio}
)}
); } export default function SearchPage() { const router = useRouter(); const searchParams = useSearchParams(); const initialQuery = searchParams.get('q') || ''; const [query, setQuery] = useState(initialQuery); const [users, setUsers] = useState([]); const [posts, setPosts] = useState([]); const [loading, setLoading] = useState(false); const [activeTab, setActiveTab] = useState<'all' | 'users' | 'posts'>('all'); const search = useCallback(async (q: string, type: string = 'all') => { if (!q.trim()) { setUsers([]); setPosts([]); return; } setLoading(true); try { const res = await fetch(`/api/search?q=${encodeURIComponent(q)}&type=${type}`); const data = await res.json(); setUsers(data.users || []); setPosts(data.posts || []); } catch { console.error('Search failed'); } finally { setLoading(false); } }, []); useEffect(() => { if (initialQuery) { search(initialQuery, activeTab); } }, [initialQuery, activeTab, search]); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (query.trim()) { router.push(`/search?q=${encodeURIComponent(query)}`); search(query, activeTab); } }; const handleTabChange = (tab: 'all' | 'users' | 'posts') => { setActiveTab(tab); if (query.trim()) { search(query, tab); } }; const handleLike = async (postId: string, currentLiked: boolean) => { const method = currentLiked ? 'DELETE' : 'POST'; await fetch(`/api/posts/${postId}/like`, { method }); }; const handleRepost = async (postId: string, currentReposted: boolean) => { const method = currentReposted ? 'DELETE' : 'POST'; await fetch(`/api/posts/${postId}/repost`, { method }); }; const handleDelete = (postId: string) => { setPosts(prev => prev.filter(p => p.id !== postId)); }; return (
{/* Header */}
setQuery(e.target.value)} placeholder="Search users and posts..." style={{ paddingLeft: '44px' }} />
{/* Tabs */}
{(['all', 'users', 'posts'] as const).map(tab => ( ))}
{/* Results */} {loading ? (
Searching...
) : !initialQuery ? (

Search for users and posts

) : users.length === 0 && posts.length === 0 ? (

No results for “{initialQuery}”

) : ( <> {/* Users */} {(activeTab === 'all' || activeTab === 'users') && users.length > 0 && (
{activeTab === 'all' && (
Users
)} {users.map(user => )}
)} {/* Posts */} {(activeTab === 'all' || activeTab === 'posts') && posts.length > 0 && (
{activeTab === 'all' && (
Posts
)} {posts.map(post => ( ))}
)} )}
); }