Files
lcbp3/frontend/app/(dashboard)/search/page.tsx
T
admin 17afe3e392
Build and Deploy / deploy (push) Successful in 7m56s
260319:1246 Fix fronend UUID #01
2026-03-19 12:46:33 +07:00

82 lines
2.5 KiB
TypeScript

"use client";
import { useState, Suspense } from "react";
import { useSearchParams } from "next/navigation";
import { SearchFilters } from "@/components/search/filters";
import { SearchResults } from "@/components/search/results";
import { SearchFilters as FilterType } from "@/types/search";
import { useSearch } from "@/hooks/use-search";
import { Loader2 } from "lucide-react";
function SearchContent() {
const searchParams = useSearchParams();
// URL Params state
const query = searchParams.get("q") || "";
const typeParam = searchParams.get("type");
const statusParam = searchParams.get("status");
// Local Filter State (synced with URL initially, but can be independent before apply)
// For simplicity, we'll keep filters in sync with valid search params or local state that pushes to URL
const [filters, setFilters] = useState<FilterType>({
types: typeParam ? [typeParam] : [],
statuses: statusParam ? [statusParam] : [],
});
// Construct search DTO — only send fields recognized by backend SearchQueryDto
// Backend uses forbidNonWhitelisted: true, so unknown fields (types[], statuses[]) cause 400
const searchDto = {
q: query,
type: filters.types?.length ? filters.types[0] : undefined,
};
const { data: results, isLoading, isError } = useSearch(searchDto);
const handleFilterChange = (newFilters: FilterType) => {
setFilters(newFilters);
// Optional: Update URL to reflect filters?
};
return (
<>
<div>
<h1 className="text-3xl font-bold">Search Results</h1>
<p className="text-muted-foreground mt-1">
{isLoading
? "Searching..."
: `Found ${results?.meta?.total ?? results?.data?.length ?? 0} results for "${query}"`
}
</p>
</div>
<div className="grid grid-cols-1 lg:grid-cols-4 gap-6">
<div className="lg:col-span-1">
<SearchFilters onFilterChange={handleFilterChange} />
</div>
<div className="lg:col-span-3">
{isError ? (
<div className="text-red-500 py-8 text-center">Failed to load search results.</div>
) : (
<SearchResults results={results?.data || []} query={query} loading={isLoading} />
)}
</div>
</div>
</>
);
}
export default function SearchPage() {
return (
<div className="space-y-6">
<Suspense fallback={
<div className="flex justify-center py-8">
<Loader2 className="h-8 w-8 animate-spin" />
</div>
}>
<SearchContent />
</Suspense>
</div>
);
}