158 lines
6.6 KiB
TypeScript
158 lines
6.6 KiB
TypeScript
import { Link } from "react-router-dom";
|
|
import {
|
|
Card, CardContent, CardFooter, CardHeader, CardTitle,
|
|
} from "@/components/ui/card";
|
|
import { Button } from "@/components/ui/button";
|
|
import { useMigrantsSearch } from "@/hooks/useMigrantsSearch";
|
|
import { formatDate } from "@/utils/date";
|
|
export default function SearchResults() {
|
|
const {
|
|
migrants,
|
|
loading,
|
|
error,
|
|
pagination,
|
|
hasActiveFilters,
|
|
handleNextPage,
|
|
handlePrevPage,
|
|
} = useMigrantsSearch(10);
|
|
const API_BASE_URL = import.meta.env.VITE_API_URL;
|
|
|
|
return (
|
|
<div className="flex flex-col min-h-screen">
|
|
{/* Header */}
|
|
<header className="border-b">
|
|
<div className="container flex h-16 items-center justify-between px-4 md:px-6">
|
|
<Link to="/" className="flex items-center gap-2">
|
|
<span className="text-xl font-bold text-[#9B2335]">Italian Migrants NT</span>
|
|
</Link>
|
|
<nav className="hidden md:flex gap-6">
|
|
{["home", "about", "search", "stories", "contact"].map((path) => (
|
|
<Link
|
|
key={path}
|
|
to={`/`}
|
|
className="text-sm font-medium hover:underline underline-offset-4 capitalize"
|
|
>
|
|
{path}
|
|
</Link>
|
|
))}
|
|
</nav>
|
|
</div>
|
|
</header>
|
|
|
|
{/* Hero Section */}
|
|
<main className="flex-1">
|
|
<section className="w-full py-12 md:py-16 lg:py-20 bg-[#E8DCCA]">
|
|
<div className="container px-4 md:px-6 text-center space-y-4">
|
|
<h1 className="text-3xl sm:text-4xl md:text-5xl font-serif font-bold tracking-tighter text-[#9B2335]">
|
|
Search Results
|
|
</h1>
|
|
<p className="max-w-[700px] mx-auto text-muted-foreground md:text-xl/relaxed">
|
|
Displaying results based on your search criteria.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
|
|
{/* Results Section */}
|
|
<section className="w-full py-8 md:py-12">
|
|
<div className="container px-4 md:px-6">
|
|
{error && (
|
|
<div className="p-3 bg-red-100 text-red-700 rounded mb-6">
|
|
{error}
|
|
</div>
|
|
)}
|
|
|
|
{loading ? (
|
|
<div className="flex justify-center my-8">
|
|
<div className="animate-spin rounded-full h-10 w-10 border-b-2 border-blue-500"></div>
|
|
</div>
|
|
) : (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
|
{migrants.length > 0 ? (
|
|
migrants.map((migrant) => (
|
|
<Card key={migrant.person_id} className="overflow-hidden pt-0">
|
|
<div className="aspect-square overflow-hidden">
|
|
<img
|
|
src={
|
|
migrant.profilePhoto
|
|
? `${API_BASE_URL}${migrant.profilePhoto.file_path}`
|
|
: `${import.meta.env.BASE_URL}assets/placeholder.svg?height=300&width=300`
|
|
}
|
|
alt={migrant.full_name || "Unknown"}
|
|
className="w-full h-full object-cover object-center transition-transform hover:scale-105"
|
|
/>
|
|
</div>
|
|
<CardHeader>
|
|
<CardTitle className="font-serif text-[#9B2335]">
|
|
{migrant.full_name || "Unknown"}
|
|
</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="text-sm space-y-2">
|
|
<div className="flex justify-between">
|
|
<span className="font-medium">Date of Birth:</span>
|
|
<span>{formatDate(migrant.date_of_birth) || "Unknown"}</span>
|
|
</div>
|
|
{migrant.place_of_birth && (
|
|
<div className="flex justify-between">
|
|
<span className="font-medium">Place of Birth:</span>
|
|
<span>{formatDate(migrant.place_of_birth) || "Unknown"}</span>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
<CardFooter>
|
|
<Button asChild className="w-full bg-[#01796F] hover:bg-[#015a54] text-white">
|
|
<Link to={`/migrant-profile/${migrant.person_id}`}>View Profile</Link>
|
|
</Button>
|
|
</CardFooter>
|
|
</Card>
|
|
))
|
|
) : (
|
|
<div className="col-span-3 text-center p-8 bg-gray-50 rounded-lg">
|
|
<p className="text-gray-500">
|
|
{hasActiveFilters
|
|
? "No migrants found matching your search criteria."
|
|
: "No migrants found."}
|
|
</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* Pagination */}
|
|
{migrants.length > 0 && (
|
|
<div className="flex justify-between items-center mt-8">
|
|
<div className="text-sm text-gray-700">
|
|
Showing <span className="font-medium">{migrants.length}</span> of{" "}
|
|
<span className="font-medium">{pagination.totalItems}</span> results
|
|
{hasActiveFilters && (
|
|
<span> • Page {pagination.currentPage} of {pagination.totalPages}</span>
|
|
)}
|
|
</div>
|
|
<div className="flex items-center gap-2">
|
|
<Button variant="outline" onClick={handlePrevPage} disabled={pagination.currentPage === 1}>
|
|
Previous
|
|
</Button>
|
|
<Button variant="outline" onClick={handleNextPage}>
|
|
Next
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
{/* Footer */}
|
|
<footer className="border-t bg-[#1A2A57] text-white">
|
|
<div className="container flex flex-col sm:flex-row items-center justify-between px-4 md:px-6 py-4 gap-2">
|
|
<p className="text-xs">© {new Date().getFullYear()} Italian Migrants NT. All rights reserved.</p>
|
|
<nav className="flex gap-4 sm:gap-6 text-xs">
|
|
<Link to="/terms" className="hover:underline underline-offset-4">Terms</Link>
|
|
<Link to="/privacy" className="hover:underline underline-offset-4">Privacy</Link>
|
|
<Link to="/admin" className="hover:underline underline-offset-4">Admin</Link>
|
|
</nav>
|
|
</div>
|
|
</footer>
|
|
</div>
|
|
);
|
|
}
|