95 lines
3.1 KiB
TypeScript
95 lines
3.1 KiB
TypeScript
import { cookies } from "next/headers";
|
|
import { getMe, search, lookupRemoteActor, User } from "@/lib/api";
|
|
import { UserListCard } from "@/components/user-list-card";
|
|
import { RemoteUserCard } from "@/components/remote-user-card";
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
|
|
import { ThoughtList } from "@/components/thought-list";
|
|
|
|
const HANDLE_RE = /^@[\w.-]+@[\w.-]+\.\w+$/;
|
|
|
|
interface SearchPageProps {
|
|
searchParams: Promise<{ q?: string }>;
|
|
}
|
|
|
|
export default async function SearchPage({ searchParams }: SearchPageProps) {
|
|
const { q } = await searchParams;
|
|
const query = q || "";
|
|
const token = (await cookies()).get("auth_token")?.value ?? null;
|
|
|
|
if (!query) {
|
|
return (
|
|
<div className="container mx-auto max-w-2xl p-4 sm:p-6 text-center">
|
|
<h1 className="text-2xl font-bold mt-8">Search Thoughts</h1>
|
|
<p className="text-muted-foreground">
|
|
Find users and thoughts across the platform.
|
|
</p>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
const isHandle = HANDLE_RE.test(query);
|
|
|
|
const [results, remoteActor, me] = await Promise.all([
|
|
isHandle ? null : search(query, token).catch(() => null),
|
|
isHandle ? lookupRemoteActor(query, token).catch(() => null) : null,
|
|
token ? getMe(token).catch(() => null) : null,
|
|
]);
|
|
|
|
const authorDetails = new Map<string, { avatarUrl?: string | null }>();
|
|
if (results) {
|
|
results.users.forEach((user: User) => {
|
|
authorDetails.set(user.username, { avatarUrl: user.avatarUrl });
|
|
});
|
|
}
|
|
|
|
return (
|
|
<div className="container mx-auto max-w-2xl p-4 sm:p-6">
|
|
<header className="my-6">
|
|
<h1 className="text-3xl font-bold">Search Results</h1>
|
|
<p className="text-muted-foreground">
|
|
Showing results for: "{query}"
|
|
</p>
|
|
</header>
|
|
<main>
|
|
{isHandle ? (
|
|
remoteActor ? (
|
|
<div className="space-y-4">
|
|
<h2 className="text-lg font-semibold">Remote user</h2>
|
|
<RemoteUserCard actor={remoteActor} />
|
|
</div>
|
|
) : (
|
|
<p className="text-center text-muted-foreground pt-8">
|
|
No user found at {query}
|
|
</p>
|
|
)
|
|
) : results ? (
|
|
<Tabs defaultValue="thoughts" className="w-full">
|
|
<TabsList>
|
|
<TabsTrigger value="thoughts">
|
|
Thoughts ({results.thoughts.length})
|
|
</TabsTrigger>
|
|
<TabsTrigger value="users">
|
|
Users ({results.users.length})
|
|
</TabsTrigger>
|
|
</TabsList>
|
|
<TabsContent value="thoughts">
|
|
<ThoughtList
|
|
thoughts={results.thoughts}
|
|
authorDetails={authorDetails}
|
|
currentUser={me}
|
|
/>
|
|
</TabsContent>
|
|
<TabsContent value="users">
|
|
<UserListCard users={results.users} />
|
|
</TabsContent>
|
|
</Tabs>
|
|
) : (
|
|
<p className="text-center text-muted-foreground pt-8">
|
|
No results found or an error occurred.
|
|
</p>
|
|
)}
|
|
</main>
|
|
</div>
|
|
);
|
|
}
|