229 lines
9.1 KiB
TypeScript
229 lines
9.1 KiB
TypeScript
"use client";
|
|
|
|
import { motion } from "framer-motion";
|
|
import { Link } from "react-router-dom";
|
|
import { ArrowLeft } from "lucide-react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Card, CardContent } from "@/components/ui/card";
|
|
import PhotoGallery from "@/components/home/PhotoGallery";
|
|
import RelatedMigrants from "@/components/home/RelatedMigrants";
|
|
import HistoricalContext from "@/components/home/HistoricalContext";
|
|
import AnimatedImage from "@/components/ui/animated-image";
|
|
import type { MigrantProfile as MigrantProfileType } from "@/types/migrant";
|
|
|
|
interface MigrantProfileProps {
|
|
migrant: MigrantProfileType;
|
|
}
|
|
|
|
export default function MigrantProfile({ migrant }: MigrantProfileProps) {
|
|
return (
|
|
<main className="min-h-screen bg-gray-50 pb-16">
|
|
{/* Hero section with main photo */}
|
|
<div className="relative w-full h-[50vh] md:h-[60vh] overflow-hidden bg-gray-900">
|
|
<AnimatedImage
|
|
src={migrant.mainPhoto || "/placeholder.svg?height=1080&width=1920"}
|
|
alt={`${migrant.firstName} ${migrant.lastName}`}
|
|
fill
|
|
className="opacity-80"
|
|
/>
|
|
<div className="absolute inset-0 bg-gradient-to-t from-black/80 to-transparent" />
|
|
<motion.div
|
|
className="absolute bottom-0 left-0 right-0 p-6 md:p-10 text-white"
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.8, delay: 0.2 }}
|
|
>
|
|
<div className="flex space-x-2 mb-4">
|
|
<div className="h-8 w-3 bg-green-600" />
|
|
<div className="h-8 w-3 bg-white" />
|
|
<div className="h-8 w-3 bg-red-600" />
|
|
</div>
|
|
<h1 className="text-3xl md:text-5xl font-bold mb-2 font-serif">
|
|
{migrant.firstName} {migrant.lastName}
|
|
</h1>
|
|
<p className="text-xl md:text-2xl opacity-90">
|
|
{migrant.yearOfArrival} • {migrant.regionOfOrigin}, Italy →{" "}
|
|
{migrant.settlementLocation}, NT
|
|
</p>
|
|
</motion.div>
|
|
</div>
|
|
|
|
{/* Back button */}
|
|
<div className="max-w-6xl mx-auto px-4 md:px-8 mt-6">
|
|
<motion.div
|
|
initial={{ opacity: 0, x: -20 }}
|
|
animate={{ opacity: 1, x: 0 }}
|
|
transition={{ duration: 0.5 }}
|
|
>
|
|
<Button variant="ghost" asChild className="mb-6 hover:bg-gray-100">
|
|
<Link to="/" className="flex items-center gap-2">
|
|
<ArrowLeft size={16} />
|
|
Back to Search
|
|
</Link>
|
|
</Button>
|
|
</motion.div>
|
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
{/* Main content - 2/3 width on desktop */}
|
|
<div className="lg:col-span-2 space-y-8">
|
|
{/* Biographical information */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.1 }}
|
|
>
|
|
<Card className="overflow-hidden border border-gray-200 shadow-none rounded-md bg-white shadow-none rounded-md bg-white">
|
|
<CardContent className="">
|
|
<h2 className="text-2xl font-bold mb-4 font-serif text-gray-800">
|
|
Biographical Information
|
|
</h2>
|
|
<div className="h-1 w-20 bg-gradient-to-r from-green-600 via-white to-red-600 mb-6" />
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-y-4 gap-x-8">
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Full Name
|
|
</h3>
|
|
<p className="text-lg">
|
|
{migrant.firstName}{" "}
|
|
{migrant.middleName ? migrant.middleName + " " : ""}
|
|
{migrant.lastName}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Birth Date
|
|
</h3>
|
|
<p className="text-lg">
|
|
{migrant.birthDate || "Unknown"}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Birth Place
|
|
</h3>
|
|
<p className="text-lg">
|
|
{migrant.birthPlace || "Unknown"}
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Age at Migration
|
|
</h3>
|
|
<p className="text-lg">{migrant.ageAtMigration} years</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Year of Arrival
|
|
</h3>
|
|
<p className="text-lg">{migrant.yearOfArrival}</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Region of Origin
|
|
</h3>
|
|
<p className="text-lg">{migrant.regionOfOrigin}, Italy</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Settlement Location
|
|
</h3>
|
|
<p className="text-lg">
|
|
{migrant.settlementLocation}, NT
|
|
</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Occupation
|
|
</h3>
|
|
<p className="text-lg">
|
|
{migrant.occupation || "Unknown"}
|
|
</p>
|
|
</div>
|
|
{migrant.deathDate && (
|
|
<>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Date of Death
|
|
</h3>
|
|
<p className="text-lg">{migrant.deathDate}</p>
|
|
</div>
|
|
<div>
|
|
<h3 className="text-sm font-medium text-gray-500">
|
|
Place of Death
|
|
</h3>
|
|
<p className="text-lg">
|
|
{migrant.deathPlace || "Unknown"}
|
|
</p>
|
|
</div>
|
|
</>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
|
|
{/* Life story */}
|
|
{migrant.biography && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.2 }}
|
|
>
|
|
<Card className="overflow-hidden border border-gray-200 shadow-none rounded-md bg-white">
|
|
<CardContent className="">
|
|
<h2 className="text-2xl font-bold mb-4 font-serif text-gray-800">
|
|
La Storia di Vita
|
|
</h2>
|
|
<div className="h-1 w-20 bg-gradient-to-r from-green-600 via-white to-red-600 mb-6" />
|
|
<div className="prose max-w-none">
|
|
{migrant.biography.split("\n").map((paragraph, index) => (
|
|
<p key={index} className="mb-4">
|
|
{paragraph}
|
|
</p>
|
|
))}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
</motion.div>
|
|
)}
|
|
|
|
{/* Photo gallery - only show if there are additional photos */}
|
|
{migrant.photos && migrant.photos.length > 0 && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.3 }}
|
|
>
|
|
<PhotoGallery photos={migrant.photos} />
|
|
</motion.div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Sidebar - 1/3 width on desktop */}
|
|
<div className="space-y-8">
|
|
{/* Historical context */}
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.4 }}
|
|
>
|
|
<HistoricalContext year={migrant.yearOfArrival} />
|
|
</motion.div>
|
|
|
|
{/* Related migrants */}
|
|
{migrant.relatedMigrants && migrant.relatedMigrants.length > 0 && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: 20 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
transition={{ duration: 0.6, delay: 0.5 }}
|
|
>
|
|
<RelatedMigrants migrants={migrant.relatedMigrants} />
|
|
</motion.div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|