Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 22s
Build & Deploy / 🧪 QA (push) Failing after 1m5s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
- Refactor app/[locale]/[slug]/page.tsx to handle fullBleed layouts cleanly - Fix heading styling on 'About Us' and other MDX pages - Implement staggered Framer Motion animations across all core blocks - Resolve InteractiveGermanyMap reference error - Standardize typography tokens for prose and custom headings - Consolidate support CTA placement
105 lines
6.5 KiB
TypeScript
105 lines
6.5 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { motion } from 'framer-motion';
|
|
import Image from 'next/image';
|
|
import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay';
|
|
|
|
export interface TeamMember {
|
|
id: string;
|
|
name: string;
|
|
position: string;
|
|
email?: string | null;
|
|
phone?: string | null;
|
|
image?: {
|
|
url: string;
|
|
alt?: string;
|
|
} | string | null;
|
|
branch: string;
|
|
}
|
|
|
|
interface TeamGridProps {
|
|
members: TeamMember[];
|
|
}
|
|
|
|
export function TeamGrid({ members }: TeamGridProps) {
|
|
if (!members || members.length === 0) return null;
|
|
|
|
return (
|
|
<section className="py-24 bg-white relative overflow-hidden">
|
|
<div className="container relative z-10">
|
|
<div className="mb-12">
|
|
<h2 className="text-primary font-bold tracking-wider uppercase text-sm mb-3">Persönliche Beratung</h2>
|
|
<h3 className="font-heading text-4xl font-extrabold text-neutral-dark mb-4">Ihre Ansprechpartner</h3>
|
|
<p className="text-text-secondary max-w-2xl text-lg">
|
|
Sprechen Sie direkt mit unseren Experten für Ihr regionales Projekt.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
|
{members.map((member, i) => (
|
|
<motion.div
|
|
key={member.id}
|
|
initial={{ opacity: 0, y: 30 }}
|
|
whileInView={{ opacity: 1, y: 0 }}
|
|
viewport={{ once: true, margin: "-50px" }}
|
|
transition={{ delay: i * 0.1, duration: 0.6, ease: [0.16, 1, 0.3, 1] }}
|
|
className="group relative bg-neutral-50 rounded-[2rem] p-8 border border-neutral-200/60 transition-all duration-500 hover:bg-white hover:border-primary/30 hover:shadow-[0_20px_40px_-15px_rgba(0,0,0,0.05)] hover:-translate-y-2 overflow-hidden"
|
|
>
|
|
<HoverShineOverlay shineColor="via-primary/5" />
|
|
|
|
<div className="relative z-10 flex flex-col h-full">
|
|
<div className="flex items-center gap-6 mb-6">
|
|
<div className="relative w-24 h-24 flex-shrink-0 rounded-[1.25rem] overflow-hidden bg-neutral-200 border border-neutral-100 shadow-sm group-hover:shadow-md transition-shadow duration-500">
|
|
{member.image && typeof member.image === 'object' && member.image.url ? (
|
|
<Image
|
|
src={member.image.url}
|
|
alt={member.name}
|
|
fill
|
|
sizes="96px"
|
|
className="object-cover group-hover:scale-110 transition-transform duration-700 ease-in-out"
|
|
/>
|
|
) : (
|
|
<div className="absolute inset-0 flex items-center justify-center text-neutral-400">
|
|
<svg className="w-10 h-10" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"></path><circle cx="12" cy="7" r="4"></circle></svg>
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div>
|
|
<h4 className="font-heading font-bold text-2xl text-neutral-dark mb-1 leading-tight group-hover:text-primary transition-colors duration-300">{member.name}</h4>
|
|
<p className="text-primary font-medium text-sm mb-1">{member.position}</p>
|
|
<p className="inline-block px-2 py-0.5 mt-1 bg-neutral-100 text-neutral-600 rounded-md text-xs uppercase tracking-widest font-semibold border border-neutral-200/60">
|
|
{member.branch === 'e-tib' ? 'E-TIB GmbH' : member.branch === 'ing' ? 'Ingenieurgesellschaft' : 'Bohrtechnik'}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="mt-auto pt-6 border-t border-neutral-200/60 space-y-3">
|
|
{member.email && (
|
|
<a href={`mailto:${member.email}`} className="group/link flex items-center gap-3 text-text-secondary hover:text-primary transition-colors text-sm font-medium">
|
|
<div className="w-8 h-8 rounded-full bg-neutral-100 flex items-center justify-center text-neutral-500 group-hover/link:bg-primary/10 group-hover/link:text-primary transition-colors">
|
|
<svg className="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
|
|
</div>
|
|
<span className="truncate">{member.email}</span>
|
|
<svg className="w-4 h-4 ml-auto opacity-0 -translate-x-2 group-hover/link:opacity-100 group-hover/link:translate-x-0 transition-all duration-300" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
|
</a>
|
|
)}
|
|
{member.phone && (
|
|
<a href={`tel:${member.phone}`} className="group/link flex items-center gap-3 text-text-secondary hover:text-primary transition-colors text-sm font-medium">
|
|
<div className="w-8 h-8 rounded-full bg-neutral-100 flex items-center justify-center text-neutral-500 group-hover/link:bg-primary/10 group-hover/link:text-primary transition-colors">
|
|
<svg className="w-4 h-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z"></path></svg>
|
|
</div>
|
|
<span>{member.phone}</span>
|
|
<svg className="w-4 h-4 ml-auto opacity-0 -translate-x-2 group-hover/link:opacity-100 group-hover/link:translate-x-0 transition-all duration-300" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>
|
|
</a>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</motion.div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|