Introduce team section with lawyers data; create reusable LawyerCard, LawyerProfile, LawyerModal, and Divider components; refactor Über Uns page layout and content.

This commit is contained in:
2025-06-23 00:52:18 +09:00
parent 9052cab43d
commit 83774715a0
6 changed files with 298 additions and 43 deletions

View File

@@ -0,0 +1,42 @@
export const lawyers = [
{
name: 'RA Dr. Max Mustermann',
image: '/images/lawyers/mustermann.jpg',
short: 'Fachanwalt für Arbeitsrecht und Vertragsrecht mit über 20 Jahren Erfahrung.',
biography: `RA Dr. Max Mustermann berät Sie umfassend im Arbeits- und Vertragsrecht. Als Fachanwalt steht er für eine rechtssichere Gestaltung und Durchsetzung Ihrer Interessen.`,
specialties: [
'Kündigungsschutzklagen',
'Arbeitsverträge und Aufhebungsverträge',
'Vertragsgestaltung für Unternehmen',
'Allgemeine Geschäftsbedingungen (AGB)',
'Durchsetzung von Ansprüchen aus Verträgen',
],
personal: [
'Jahrgang 1972',
'Studium der Rechtswissenschaft in Heidelberg',
'Zulassung seit 2000',
'Fachanwalt für Arbeitsrecht und Vertragsrecht',
'Mitglied im Deutschen Anwaltverein (DAV)',
],
},
{
name: 'RAin Lisa Künstler',
image: '/images/lawyers/kuenstler.jpg',
short: 'Fachanwältin für Familienrecht mit Fokus auf einvernehmliche Lösungen.',
biography: `RAin Lisa Künstler begleitet Sie empathisch und zielgerichtet in familiären Angelegenheiten. Ihr besonderes Augenmerk liegt auf tragfähigen Vereinbarungen für alle Beteiligten.`,
specialties: [
'Scheidung & Trennung',
'Unterhaltsrecht',
'Sorgerecht & Umgangsregelungen',
'Eheverträge & Partnerschaftsverträge',
'Vermögensauseinandersetzungen',
],
personal: [
'Jahrgang 1980',
'Studium in Freiburg und Basel',
'Zulassung seit 2007',
'Fachanwältin für Familienrecht',
'Mitglied der Arbeitsgemeinschaft Familienrecht im DAV',
],
},
];

View File

@@ -1,49 +1,91 @@
import React from 'react'; 'use client';
export default function About() { import {lawyers} from '@/app/ueber-uns/lawyers';
import Divider from '@/components/Divider';
import SubpageHero from '@/components/SubpageHero';
export default function UeberUnsPage() {
return ( return (
<div className="container mx-auto px-4 py-8"> <>
<h1 className="text-4xl font-bold mb-6">Über Uns</h1> <SubpageHero
title="Über uns"
subtitle="Persönlich. Kompetent. Engagiert das Team der Kanzlei Mustermann & Künstler."
/>
<section className="mb-8"> <main className="bg-white pt-16 pb-32 px-6 md:px-16 lg:px-36 text-gray-900 space-y-24">
<p className="text-lg mb-4"> {/* Kanzlei-Intro */}
Willkommen in unserer Anwaltskanzlei. Seit über 20 Jahren setzen wir uns für die Rechte unserer <section className="max-w-3xl space-y-4">
Mandanten ein und bieten erstklassige juristische Beratung in verschiedenen Rechtsbereichen. <p className="text-lg text-gray-700">
</p> Die Kanzlei Mustermann & Künstler steht für rechtliche Exzellenz, persönliche Beratung und
<p className="text-lg mb-4"> langjährige Erfahrung. Wir vereinen spezialisierte Fachkenntnisse mit menschlichem Gespür für
Unsere Expertise umfasst unter anderem Wirtschaftsrecht, Arbeitsrecht, Familienrecht und individuelle Lebenssituationen.
Immobilienrecht. Mit unserem engagierten Team von Fachanwälten stehen wir Ihnen bei allen </p>
rechtlichen Angelegenheiten zur Seite. <p className="text-lg text-gray-700">
</p> Unser Anspruch ist es, Sie transparent, ehrlich und effizient zu beraten und zu vertreten
</section> unabhängig davon, ob es sich um eine komplexe Nachlassregelung, eine arbeitsrechtliche
Auseinandersetzung oder familiäre Fragestellungen handelt.
</p>
</section>
<section className="mb-8"> {/* Anwälte */}
<h2 className="text-2xl font-semibold mb-4">Unser Team</h2> {lawyers.map((lawyer, i) => (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> <div key={i}>
<div className="p-4 border rounded-lg"> <section
<h3 className="text-xl font-medium">Dr. Maria Schmidt</h3> className={`flex flex-col md:flex-row ${
<p>Fachanwältin für Wirtschaftsrecht</p> i % 2 === 1 ? 'md:flex-row-reverse' : ''
</div> } gap-8 md:items-start`}
<div className="p-4 border rounded-lg"> >
<h3 className="text-xl font-medium">Thomas Weber</h3> {/* image */}
<p>Fachanwalt für Arbeitsrecht</p> <div className="w-full md:w-1/3">
</div> <img
<div className="p-4 border rounded-lg"> src={lawyer.image}
<h3 className="text-xl font-medium">Lisa Müller</h3> alt={lawyer.name}
<p>Fachanwältin für Familienrecht</p> className="w-full h-auto rounded-xl shadow-sm object-cover"
</div> />
</div> </div>
</section>
<section> {/* content */}
<h2 className="text-2xl font-semibold mb-4">Standort</h2> <div className="w-full md:w-2/3 space-y-4">
<p className="text-lg"> <h2 className="text-2xl font-bold text-red-700">{lawyer.name}</h2>
Musterstraße 123<br/> <p className="text-base text-gray-800">{lawyer.short}</p>
12345 Berlin<br/>
Tel: +49 (0) 30 123456789<br/> {lawyer.biography && (
E-Mail: info@musterkanzlei.de <div>
</p> <h3 className="font-semibold mb-1">Über</h3>
</section> <p className="text-sm text-gray-700 whitespace-pre-line">
</div> {lawyer.biography}
</p>
</div>
)}
{lawyer.specialties?.length > 0 && (
<div>
<h3 className="font-semibold mb-1">Fachgebiete</h3>
<ul className="list-disc pl-5 text-sm text-gray-700 space-y-1">
{lawyer.specialties.map((s, idx) => (
<li key={idx}>{s}</li>
))}
</ul>
</div>
)}
{lawyer.personal?.length > 0 && (
<div>
<h3 className="font-semibold mb-1">Zur Person</h3>
<ul className="list-disc pl-5 text-sm text-gray-700 space-y-1">
{lawyer.personal.map((p, idx) => (
<li key={idx}>{p}</li>
))}
</ul>
</div>
)}
</div>
</section>
{i < lawyers.length - 1 && <Divider/>}
</div>
))}
</main>
</>
); );
} }

View File

@@ -0,0 +1,3 @@
export default function Divider() {
return <div className="w-full h-px bg-gray-200 my-16"/>;
}

View File

@@ -0,0 +1,18 @@
'use client';
export default function LawyerCard({ lawyer, onClick }: { lawyer: any; onClick: () => void }) {
return (
<button
onClick={onClick}
className="bg-neutral-100 hover:bg-neutral-200 transition p-6 rounded-xl shadow-sm text-left text-gray-800"
>
<img
src={lawyer.image}
alt={lawyer.name}
className="w-full h-48 object-cover rounded-md mb-4"
/>
<h3 className="text-xl font-bold text-red-700 mb-2">{lawyer.name}</h3>
<p className="text-sm text-gray-700">{lawyer.short}</p>
</button>
);
}

View File

@@ -0,0 +1,97 @@
'use client';
import {motion, AnimatePresence} from 'framer-motion';
import {useEffect} from 'react';
export default function LawyerModal({
lawyer,
onClose,
}: Readonly<{
lawyer: any;
onClose: () => void;
}>) {
// Close with Escape
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
document.addEventListener('keydown', handleKeyDown);
return () => document.removeEventListener('keydown', handleKeyDown);
}, [onClose]);
return (
<AnimatePresence>
<motion.div
initial={{opacity: 0}}
animate={{opacity: 1}}
exit={{opacity: 0}}
className="fixed inset-0 z-50 bg-black/60 backdrop-blur-sm flex justify-center items-center p-4 overflow-y-auto"
onClick={onClose}
>
<motion.div
initial={{y: 40, opacity: 0}}
animate={{y: 0, opacity: 1}}
exit={{y: 30, opacity: 0}}
transition={{duration: 0.3, ease: 'easeOut'}}
onClick={(e) => e.stopPropagation()}
className="bg-white rounded-xl max-w-3xl w-full p-8 relative text-gray-800 shadow-xl"
>
<button
onClick={onClose}
className="absolute top-4 right-4 text-gray-500 hover:text-gray-700 text-2xl font-bold"
>
×
</button>
<div className="flex flex-col md:flex-row gap-6">
{lawyer.image && (
<img
src={lawyer.image}
alt={lawyer.name}
className="w-full md:w-1/3 h-auto object-cover rounded-md"
/>
)}
<div className="flex-1 space-y-4">
<div>
<h2 className="text-2xl font-bold text-red-700">{lawyer.name}</h2>
<p className="text-sm text-gray-500">{lawyer.short}</p>
</div>
{lawyer.specialties?.length > 0 && (
<div>
<h3 className="font-semibold text-gray-800">Fachgebiete</h3>
<ul className="list-disc pl-5 text-sm text-gray-700">
{lawyer.specialties.map((s: string, i: number) => (
<li key={i}>{s}</li>
))}
</ul>
</div>
)}
{lawyer.biography && (
<div>
<h3 className="font-semibold text-gray-800">Über</h3>
<p className="text-sm leading-relaxed text-gray-700 whitespace-pre-line">
{lawyer.biography}
</p>
</div>
)}
{lawyer.personal?.length > 0 && (
<div>
<h3 className="font-semibold text-gray-800">Zur Person</h3>
<ul className="list-disc pl-5 text-sm text-gray-700">
{lawyer.personal.map((p: string, i: number) => (
<li key={i}>{p}</li>
))}
</ul>
</div>
)}
</div>
</div>
</motion.div>
</motion.div>
</AnimatePresence>
);
}

View File

@@ -0,0 +1,53 @@
'use client';
export default function LawyerProfile({lawyer, reverse = false}: Readonly<{ lawyer: any; reverse?: boolean }>) {
return (
<section className={`flex flex-col md:flex-row ${reverse ? 'md:flex-row-reverse' : ''} gap-10 md:items-start`}>
{/* image */}
<div className="w-full md:w-1/3">
<img
src={lawyer.image}
alt={lawyer.name}
className="w-full h-auto rounded-xl shadow-sm object-cover"
/>
</div>
{/* content */}
<div className="w-full md:w-2/3 space-y-6 text-[17px] text-gray-800 leading-relaxed">
<div>
<h2 className="text-2xl font-bold text-red-700">{lawyer.name}</h2>
<p>{lawyer.short}</p>
</div>
{lawyer.biography && (
<div>
<h3 className="font-semibold mb-1">Zur Person</h3>
<p className="whitespace-pre-line">{lawyer.biography}</p>
</div>
)}
{lawyer.specialties?.length > 0 && (
<div>
<h3 className="font-semibold mb-1">Fachgebiete</h3>
<ul className="list-disc pl-5 space-y-1">
{lawyer.specialties.map((s: string, i: number) => (
<li key={i}>{s}</li>
))}
</ul>
</div>
)}
{lawyer.personal?.length > 0 && (
<div>
<h3 className="font-semibold mb-1">Ausbildung & Mitgliedschaften</h3>
<ul className="list-disc pl-5 space-y-1">
{lawyer.personal.map((p: string, i: number) => (
<li key={i}>{p}</li>
))}
</ul>
</div>
)}
</div>
</section>
);
}