Add AnwaltOverviewPage for lawyer overview; adjust team data and images; refactor Links structure; update affected components.
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import {motion} from 'framer-motion';
|
import {motion} from 'framer-motion';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Links from "@/app/Links";
|
import Links from "@/data/Links";
|
||||||
|
|
||||||
const services = [
|
const services = [
|
||||||
{
|
{
|
||||||
|
|||||||
146
lawfirm-demos/demo-1/app/rechtsanwaelte/page.tsx
Normal file
146
lawfirm-demos/demo-1/app/rechtsanwaelte/page.tsx
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
'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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Links from "@/app/Links";
|
import Links from "@/data/Links";
|
||||||
|
|
||||||
export default function Footer() {
|
export default function Footer() {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import {useEffect, useState} from 'react';
|
import {useEffect, useState} from 'react';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import Links from '@/app/Links';
|
import Links from '@/data/Links';
|
||||||
import {usePathname} from 'next/navigation';
|
import {usePathname} from 'next/navigation';
|
||||||
|
|
||||||
export default function Navbar() {
|
export default function Navbar() {
|
||||||
@@ -35,7 +35,7 @@ export default function Navbar() {
|
|||||||
</Link>
|
</Link>
|
||||||
<div className="space-x-6 text-base md:text-lg font-semibold">
|
<div className="space-x-6 text-base md:text-lg font-semibold">
|
||||||
<Link href={Links.about}>Über uns</Link>
|
<Link href={Links.about}>Über uns</Link>
|
||||||
<Link href={Links.legalFields}>Rechtsgebiete</Link>
|
<Link href={Links.lawyers}>Rechtsanwälte</Link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
const Links = {
|
const Links = {
|
||||||
home: '/',
|
home: '/',
|
||||||
lawfirm: 'kanzlei',
|
lawfirm: 'kanzlei',
|
||||||
|
lawyers: 'rechtsanwaelte',
|
||||||
legalFields: 'rechtsbereiche',
|
legalFields: 'rechtsbereiche',
|
||||||
about: '/ueber-uns/',
|
about: '/ueber-uns/',
|
||||||
imprint: '/impressum/',
|
imprint: '/impressum/',
|
||||||
@@ -2,7 +2,8 @@ export const team = [
|
|||||||
{
|
{
|
||||||
name: 'Dr. Max Mustermann',
|
name: 'Dr. Max Mustermann',
|
||||||
role: "Rechtsanwalt",
|
role: "Rechtsanwalt",
|
||||||
image: '/images/lawyers/mustermann.jpg',
|
image: '/images/team/mustermann.jpg',
|
||||||
|
isLawyer: true,
|
||||||
short: 'Fachanwalt für Arbeitsrecht und Vertragsrecht mit über 20 Jahren Erfahrung.',
|
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.`,
|
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: [
|
specialties: [
|
||||||
@@ -22,8 +23,9 @@ export const team = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Lisa Künstler',
|
name: 'Lisa Künstler',
|
||||||
role: "Rechtsanwalt",
|
role: "Rechtsanwältin",
|
||||||
image: '/images/lawyers/kuenstler.jpg',
|
image: '/images/team/kuenstler.jpg',
|
||||||
|
isLawyer: true,
|
||||||
short: 'Fachanwältin für Familienrecht mit Fokus auf einvernehmliche Lösungen.',
|
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.`,
|
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: [
|
specialties: [
|
||||||
|
|||||||
BIN
lawfirm-demos/demo-1/public/images/team/kuenstler.jpg
Normal file
BIN
lawfirm-demos/demo-1/public/images/team/kuenstler.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
BIN
lawfirm-demos/demo-1/public/images/team/mustermann.jpg
Normal file
BIN
lawfirm-demos/demo-1/public/images/team/mustermann.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 88 KiB |
Reference in New Issue
Block a user