Files
e-tib.com/app/[locale]/referenzen/page.tsx
Marc Mintel 84f035a9fd
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 37s
Build & Deploy / 🧪 QA (push) Failing after 1m31s
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 4s
chore: optimize reference gallery, add typography plugin, fix SEO and map animations
2026-05-13 22:14:47 +02:00

173 lines
8.4 KiB
TypeScript

import { Container, Heading, Badge } from '@/components/ui';
import { getTranslations, setRequestLocale } from 'next-intl/server';
import { Metadata } from 'next';
import { getAllReferences } from '@/lib/references';
import TrackedLink from '@/components/analytics/TrackedLink';
import { MapPin, Calendar, Briefcase, ArrowUpRight } from 'lucide-react';
import { getButtonClasses, ButtonOverlay } from '@/components/ui/Button';
import { SITE_URL } from '@/lib/schema';
import Image from 'next/image';
import { InteractiveGermanyMap } from '@/components/blocks/InteractiveGermanyMap';
import { defaultLocations } from '@/lib/map-data';
interface PageProps {
params: Promise<{
locale: string;
}>;
}
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
const { locale } = await params;
if (locale !== 'de' && locale !== 'en') return {};
return {
title: 'Referenzen | E-TIB Gruppe',
description: 'Erfolgreich abgeschlossene Projekte der E-TIB Gruppe im Bereich Kabeltiefbau, Spülbohrtechnik und Netzinfrastruktur.',
alternates: {
canonical: `${SITE_URL}/${locale}/referenzen`,
languages: {
de: `${SITE_URL}/de/referenzen`,
en: `${SITE_URL}/en/referenzen`,
'x-default': `${SITE_URL}/en/referenzen`,
},
},
};
}
export default async function ReferenzenOverview(props: { params: Promise<{ locale: string }> }) {
const { locale } = await props.params;
setRequestLocale(locale);
const t = await getTranslations('StandardPage');
const references = await getAllReferences(locale);
// Enrich the static map locations with dynamic project data (images, details)
const enrichedLocations = defaultLocations.map(loc => {
if (loc.type === 'project') {
const ref = references.find(r => r.slug === loc.id);
if (ref) {
return {
...loc,
featuredImage: ref.frontmatter.featuredImage,
details: [
ref.frontmatter.client || 'Kunde',
ref.frontmatter.dateString || new Date(ref.frontmatter.date).getFullYear().toString(),
],
};
}
}
return loc;
});
return (
<div className="flex flex-col min-h-screen bg-neutral-50 pb-16 md:pb-24">
{/* Map Hero Section */}
<InteractiveGermanyMap
isHero={true}
badge="Unsere Referenzen"
title={<>Erfolgreich umgesetzte<br/>Projekte.</>}
description="Vom Breitbandausbau bis zur komplexen 110kV-Trasse: Ein Auszug unserer bundesweiten Projekte, bei denen wir Infrastruktur für die Zukunft geschaffen haben. Entdecken Sie unsere Standorte."
locations={enrichedLocations}
/>
{/* Main Content Area */}
<Container className="relative z-20 mt-16 md:mt-24">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8">
{references.map((ref) => (
<TrackedLink
key={ref.slug}
href={`/${locale}/referenzen/${ref.slug}`}
className="group flex flex-col bg-white border border-neutral-100 rounded-3xl overflow-hidden shadow-sm hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2"
eventProperties={{
location: 'referenzen_grid',
target_slug: ref.slug,
}}
>
<div className="flex flex-col h-full relative">
{/* Image Section */}
<div className="relative h-64 w-full bg-[#f4f4f5] overflow-hidden shrink-0 border-b border-neutral-100">
{ref.frontmatter.featuredImage ? (
<Image
src={ref.frontmatter.featuredImage}
alt={ref.frontmatter.title}
fill
className="object-cover group-hover:scale-105 transition-transform duration-1000 ease-[cubic-bezier(0.16,1,0.3,1)] filter grayscale-[20%] group-hover:grayscale-0"
/>
) : (
<div className="absolute inset-0 bg-[#f4f4f5] flex items-center justify-center">
<Image src="/assets/logo.png" alt="E-TIB Logo" width={80} height={80} className="opacity-20 grayscale" />
</div>
)}
<div className="absolute inset-0 bg-black/5 group-hover:bg-transparent transition-colors duration-500" />
{/* Location Badge */}
<div className="absolute top-4 left-4 z-10">
<span className="bg-white/95 backdrop-blur-md text-neutral-dark px-3 py-1.5 rounded-sm text-[10px] font-bold uppercase tracking-widest flex items-center gap-1.5 shadow-sm border border-neutral-200">
<MapPin className="w-3 h-3 text-primary" />
{ref.frontmatter.location}
</span>
</div>
</div>
{/* Content Section */}
<div className="flex flex-col flex-grow p-6 md:p-8 bg-white">
<h3 className="text-xl md:text-2xl font-bold font-heading text-neutral-dark mb-6 group-hover:text-primary transition-colors line-clamp-3 leading-[1.2]">
{ref.frontmatter.title}
</h3>
{/* Technical Meta Data */}
<div className="grid grid-cols-[1fr_1fr] gap-4 mt-auto border-t border-neutral-100 pt-6 pr-16 md:pr-20 relative z-10">
<div className="min-w-0">
<span className="block text-[10px] uppercase tracking-widest text-neutral-400 font-bold mb-1">Kunde</span>
<span className="flex items-center gap-1.5 text-sm font-semibold text-neutral-700">
<Briefcase className="w-3.5 h-3.5 text-primary shrink-0" />
<span className="truncate">{ref.frontmatter.client}</span>
</span>
</div>
<div className="min-w-0">
<span className="block text-[10px] uppercase tracking-widest text-neutral-400 font-bold mb-1">Zeitraum</span>
<span className="flex items-center gap-1.5 text-sm font-semibold text-neutral-700">
<Calendar className="w-3.5 h-3.5 text-primary shrink-0" />
<span className="truncate">{ref.frontmatter.dateString || new Date(ref.frontmatter.date).getFullYear()}</span>
</span>
</div>
</div>
</div>
{/* Industrial Hover Indicator */}
<div className="absolute right-6 bottom-6 md:right-8 md:bottom-8 w-10 h-10 bg-neutral-50 border border-neutral-200 rounded flex items-center justify-center transform group-hover:bg-primary group-hover:border-primary transition-colors duration-300">
<ArrowUpRight className="w-5 h-5 text-neutral-dark group-hover:text-white transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-transform duration-300" />
</div>
</div>
</TrackedLink>
))}
</div>
{/* Support Section */}
<div className="mt-24 p-8 md:p-12 bg-primary-dark rounded-3xl text-white shadow-2xl relative overflow-hidden group">
<div className="absolute top-0 right-0 w-64 h-full bg-accent/5 -skew-x-12 translate-x-1/2 transition-transform group-hover:translate-x-1/3" />
<div className="relative z-10 max-w-2xl">
<h3 className="text-2xl md:text-3xl font-bold mb-4">Ihr nächstes Projekt?</h3>
<p className="text-lg text-white/70 mb-8">Lassen Sie uns gemeinsam herausragende Infrastruktur bauen.</p>
<TrackedLink
href={`/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}`}
className={getButtonClasses('accent', 'lg')}
eventProperties={{
location: 'referenzen_support_cta',
}}
>
<span className="relative z-10 flex items-center justify-center gap-2 transition-colors duration-500 group-hover/btn:text-primary-dark">
{t('contactUs')}
<span className="ml-2 transition-transform group-hover/btn:translate-x-1">
&rarr;
</span>
</span>
<ButtonOverlay variant="accent" />
</TrackedLink>
</div>
</div>
</Container>
</div>
);
}