Files
demo-websites/lawfirm-demos/demo-1/app/rechtsanwaelte/page.tsx

147 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
'use client';
import {team} from '@/data/team';
import {useState} from 'react';
import Image from 'next/image';
import {motion, AnimatePresence} from 'framer-motion';
import SubpageHero from '@/components/SubpageHero';
type Lawyer = {
name: string;
image: string;
role?: string;
specialties?: string[];
biography?: string;
personal?: string[];
isLawyer: boolean;
};
const fadeIn = {
hidden: {opacity: 0, y: 40},
visible: (i: number) => ({
opacity: 1,
y: 0,
transition: {delay: i * 0.05, duration: 0.4},
}),
};
export default function AnwaltOverviewPage() {
const lawyers: Lawyer[] = team.filter((person) => person.isLawyer);
const [selected, setSelected] = useState<Lawyer | null>(null);
return (
<>
<SubpageHero title="Unsere Anwälte"/>
<main className="bg-white py-20 px-6 md:px-16 lg:px-36 text-gray-900">
<div className="max-w-6xl mx-auto">
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-12">
{lawyers.map((lawyer, i) => (
<motion.div
key={lawyer.name}
custom={i}
initial="hidden"
whileInView="visible"
viewport={{once: true}}
variants={fadeIn}
>
<div
onClick={() => setSelected(lawyer)}
className="group rounded-xl overflow-hidden shadow-md border border-gray-200 hover:shadow-lg transition hover:scale-[1.015] cursor-pointer ring-0 hover:ring-2 hover:ring-red-200 bg-white"
>
<div className="relative w-full h-64 bg-gray-100 flex items-center justify-center">
<Image
src={lawyer.image}
alt={lawyer.name}
fill
className="object-contain p-2 transition group-hover:opacity-90"
/>
</div>
<div className="p-4">
<h2 className="text-lg font-semibold text-gray-900">{lawyer.name}</h2>
<p className="text-sm text-gray-600">{lawyer.role}</p>
{Array.isArray(lawyer.specialties) && lawyer.specialties.length > 0 && (
<ul className="mt-2 text-sm text-gray-700 space-y-1">
{lawyer.specialties.map((s, i) => (
<li key={i}> {s}</li>
))}
</ul>
)}
</div>
</div>
</motion.div>
))}
</div>
</div>
{/* Modal */}
<AnimatePresence>
{selected && (
<motion.div
className="fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 px-4"
initial={{opacity: 0}}
animate={{opacity: 1}}
exit={{opacity: 0}}
onClick={() => setSelected(null)}
>
<motion.div
className="bg-white max-w-2xl w-full max-h-[90vh] overflow-y-auto rounded-xl shadow-lg relative"
initial={{scale: 0.9, y: 40, opacity: 0}}
animate={{scale: 1, y: 0, opacity: 1}}
exit={{scale: 0.9, y: 40, opacity: 0}}
transition={{type: 'spring', stiffness: 260, damping: 20}}
onClick={(e) => e.stopPropagation()}
>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 p-6">
<div className="relative w-full h-64 bg-gray-100 flex items-center justify-center">
<Image
src={selected.image}
alt={selected.name}
fill
className="object-contain p-2"
/>
</div>
<div className="space-y-4">
<h3 className="text-2xl font-bold">{selected.name}</h3>
<p className="text-sm text-gray-600">{selected.role}</p>
{selected.biography && (
<p className="text-sm text-gray-700 whitespace-pre-line">{selected.biography}</p>
)}
{Array.isArray(selected.specialties) && selected.specialties.length > 0 && (
<>
<h4 className="font-semibold mt-4">Fachgebiete</h4>
<ul className="list-disc pl-5 text-sm text-gray-700 space-y-1">
{selected.specialties.map((s, i) => (
<li key={i}>{s}</li>
))}
</ul>
</>
)}
{Array.isArray(selected.personal) && selected.personal.length > 0 && (
<>
<h4 className="font-semibold mt-4">Zur Person</h4>
<ul className="list-disc pl-5 text-sm text-gray-700 space-y-1">
{selected.personal.map((p, i) => (
<li key={i}>{p}</li>
))}
</ul>
</>
)}
</div>
</div>
<button
className="absolute top-4 right-4 text-gray-500 hover:text-gray-800 text-xl"
onClick={() => setSelected(null)}
>
×
</button>
</motion.div>
</motion.div>
)}
</AnimatePresence>
</main>
</>
);
}