feat(ui): finalize E-TIB modernization with footer redesign, video optimization, and TS fixes

Former-commit-id: 67ac02c8404cc66893fdf97308574701cca6000c
This commit is contained in:
2026-05-07 10:43:20 +02:00
parent f2fdea96ec
commit 5439df72ea
3712 changed files with 932332 additions and 1867 deletions

View File

@@ -6,6 +6,18 @@ import Image from 'next/image';
import Link from 'next/link';
interface SubCompanyTilesProps {
badge?: string;
title?: string;
companies?: {
title?: string;
description?: string;
icon?: string;
url?: string;
backgroundImage?: {
url?: string;
alt?: string;
} | any;
}[];
data?: {
badge?: string;
title?: string;
@@ -13,6 +25,7 @@ interface SubCompanyTilesProps {
title?: string;
description?: string;
icon?: string;
url?: string;
backgroundImage?: {
url?: string;
alt?: string;
@@ -63,15 +76,22 @@ const itemVariants: Variants = {
visible: { opacity: 1, y: 0, transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] } },
};
export function SubCompanyTiles({ data }: SubCompanyTilesProps) {
const badge = data?.badge || 'Die Gruppe';
const title = data?.title || 'Geballte Kompetenz unter einem Dach';
const companiesData = data?.companies?.map(c => ({
export function SubCompanyTiles(props: SubCompanyTilesProps) {
const { data } = props;
const badge = props.badge || data?.badge || 'Die Gruppe';
const title = props.title || data?.title || 'Geballte Kompetenz unter einem Dach';
const rawCompanies = props.companies || data?.companies;
const companiesData = rawCompanies?.map(c => ({
title: c.title,
desc: c.description,
url: c.url,
icon: c.icon || 'M13 10V3L4 14h7v7l9-11h-7z',
bgImage: c.backgroundImage?.url || '/assets/photos/DJI_0243.JPG',
bgImage: c.backgroundImage?.url || c.backgroundImage || '/assets/photos/DJI_0243.JPG',
})) || defaultCompanies;
const gridColsClass = companiesData.length === 3
? "grid-cols-1 lg:grid-cols-3"
: "grid-cols-1 md:grid-cols-2 lg:grid-cols-4";
return (
<section id="unternehmen" className="py-24 bg-neutral overflow-hidden">
@@ -82,47 +102,63 @@ export function SubCompanyTiles({ data }: SubCompanyTilesProps) {
</div>
<motion.div
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"
className={`grid gap-8 ${gridColsClass}`}
variants={containerVariants}
initial="hidden"
whileInView="visible"
viewport={{ once: true, margin: "-100px" }}
>
{companiesData.map((company, index) => (
<motion.div
key={index}
variants={itemVariants}
className="group relative rounded-none overflow-hidden aspect-[4/5] flex flex-col justify-end p-8 shadow-xl border-b-4 border-primary transition-colors duration-500 bg-white"
>
<div className="absolute inset-0 bg-white z-0">
<Image
src={company.bgImage}
alt={company.title || ''}
fill
className="object-cover opacity-80 group-hover:scale-105 group-hover:opacity-100 transition-all duration-700 ease-in-out"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 25vw"
/>
</div>
{/* Premium Bright Gradient */}
<div className="absolute inset-0 bg-gradient-to-t from-white via-white/80 to-white/10 opacity-90 group-hover:opacity-100 transition-opacity duration-500 z-0" />
<div className="relative z-10 flex flex-col h-full justify-between">
<div className="w-12 h-12 rounded-none bg-primary text-white flex items-center justify-center group-hover:bg-primary-dark transition-all duration-300 shadow-md">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d={company.icon} />
</svg>
</div>
<div className="mt-auto transform translate-y-4 group-hover:translate-y-0 transition-transform duration-500 ease-out">
<h4 className="font-heading font-bold text-2xl text-text-primary mb-2 leading-tight group-hover:text-primary transition-colors">{company.title}</h4>
<p className="text-text-secondary leading-relaxed text-sm h-0 opacity-0 group-hover:h-auto group-hover:opacity-100 group-hover:mt-3 transition-all duration-500 ease-out overflow-hidden line-clamp-3">
{company.desc}
</p>
</div>
</div>
</motion.div>
))}
{companiesData.map((company, index) => {
const CardWrapper = company.url ? 'a' : 'div';
const wrapperProps = company.url ? { href: company.url, target: "_blank", rel: "noopener noreferrer" } : {};
return (
<motion.div
key={index}
variants={itemVariants}
className="h-full"
>
<CardWrapper
{...wrapperProps}
className="group relative rounded-lg overflow-hidden aspect-[3/4] flex flex-col justify-end p-8 shadow-xl border-t-4 border-primary transition-all duration-500 hover:shadow-2xl hover:-translate-y-2 bg-neutral-dark cursor-pointer block w-full h-full"
>
<div className="absolute inset-0 bg-[#0a192f] z-0">
<Image
src={company.bgImage}
alt={company.title || ''}
fill
className="object-cover opacity-50 group-hover:opacity-70 group-hover:scale-105 transition-all duration-700 ease-in-out grayscale-[30%] group-hover:grayscale-0"
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
/>
</div>
{/* Premium Dark Gradient, lighter this time */}
<div className="absolute inset-0 bg-gradient-to-t from-[#0a192f]/90 via-[#0a192f]/40 to-transparent z-0" />
<div className="relative z-10 flex flex-col h-full justify-between">
<div className="w-14 h-14 rounded-none bg-primary/90 text-white flex items-center justify-center group-hover:bg-primary transition-all duration-300 shadow-lg backdrop-blur-sm">
<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d={company.icon} />
</svg>
</div>
<div className="mt-auto transform translate-y-6 group-hover:translate-y-0 transition-transform duration-500 ease-out">
<h4 className="font-heading font-bold text-3xl text-white mb-3 leading-tight group-hover:text-primary transition-colors">{company.title}</h4>
<p className="text-white/80 leading-relaxed text-base h-0 opacity-0 group-hover:h-auto group-hover:opacity-100 group-hover:mt-4 transition-all duration-500 ease-out overflow-hidden line-clamp-4">
{company.desc}
</p>
{company.url && (
<div className="h-0 opacity-0 group-hover:h-auto group-hover:opacity-100 group-hover:mt-4 transition-all duration-500 ease-out flex items-center text-primary font-bold uppercase text-xs tracking-widest">
Website Besuchen
<svg className="w-4 h-4 ml-2" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>
</div>
)}
</div>
</div>
</CardWrapper>
</motion.div>
);
})}
</motion.div>
</div>
</section>