Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 1m11s
Build & Deploy / 🧪 QA (push) Failing after 1m2s
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 3s
CI - Lint, Typecheck & Test / quality-assurance (pull_request) Successful in 4m25s
245 lines
11 KiB
TypeScript
245 lines
11 KiB
TypeScript
'use client';
|
|
|
|
import * as React from 'react';
|
|
import { motion, Variants } from 'framer-motion';
|
|
import Image from 'next/image';
|
|
import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay';
|
|
import { AnimatedGlossyBorder } from '@/components/ui/AnimatedGlossyBorder';
|
|
|
|
interface SubCompanyTilesProps {
|
|
badge?: string;
|
|
title?: string;
|
|
companies?: {
|
|
title?: string;
|
|
url?: string;
|
|
backgroundImage?: string;
|
|
}[];
|
|
data?: any;
|
|
}
|
|
|
|
const defaultCompanies = [
|
|
{
|
|
title: 'E-TIB GmbH',
|
|
backgroundImage: '/assets/photos/DJI_0243.JPG',
|
|
},
|
|
{
|
|
title: 'E-TIB Ingenieurgesellschaft mbH',
|
|
url: 'https://www.etib-ing.com/',
|
|
backgroundImage: '/assets/photos/DSC01137.JPG',
|
|
},
|
|
{
|
|
title: 'NEMO GmbH',
|
|
url: 'https://www.nemo-gmbh.de/',
|
|
backgroundImage: '/assets/photos/DJI_0048.JPG',
|
|
}
|
|
];
|
|
|
|
const containerVariants: Variants = {
|
|
hidden: { opacity: 0 },
|
|
visible: {
|
|
opacity: 1,
|
|
transition: {
|
|
staggerChildren: 0.15,
|
|
},
|
|
},
|
|
};
|
|
|
|
const itemVariants: Variants = {
|
|
hidden: { opacity: 0, y: 30 },
|
|
visible: { opacity: 1, y: 0, transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] } },
|
|
};
|
|
|
|
import { usePathname } from 'next/navigation';
|
|
import { LogoArcs } from '@/components/ui/LogoArcs';
|
|
|
|
export function SubCompanyTiles(props: SubCompanyTilesProps) {
|
|
const { data } = props;
|
|
const badge = props.badge || data?.badge;
|
|
const title = props.title || data?.title;
|
|
const rawCompanies = props.companies || data?.companies;
|
|
const pathname = usePathname();
|
|
const isDe = pathname?.startsWith('/de') ?? true;
|
|
|
|
const companiesData = rawCompanies?.map((c: any) => ({
|
|
title: c.title,
|
|
url: c.url,
|
|
backgroundImage: c.backgroundImage?.url || c.backgroundImage || '/assets/photos/DJI_0243.JPG',
|
|
})) || defaultCompanies;
|
|
|
|
return (
|
|
<section id="unternehmen" className="py-24 bg-neutral-dark border-b border-neutral-800 relative overflow-hidden">
|
|
<div className="container relative z-10 px-4">
|
|
|
|
{(badge || title) && (
|
|
<div className="text-center max-w-3xl mx-auto mb-16">
|
|
{badge && <h2 className="text-primary font-bold tracking-wider uppercase text-sm mb-3">{badge}</h2>}
|
|
{title && <h3 className="font-heading text-4xl md:text-5xl font-extrabold text-white">{title}</h3>}
|
|
</div>
|
|
)}
|
|
|
|
<motion.div
|
|
className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6"
|
|
variants={containerVariants}
|
|
initial="hidden"
|
|
whileInView="visible"
|
|
viewport={{ once: true, margin: "-50px" }}
|
|
>
|
|
{companiesData.map((company: any, index: number) => {
|
|
const isCurrent = company.title.toUpperCase() === 'E-TIB GMBH';
|
|
const hasUrl = !!company.url;
|
|
const CardWrapper = hasUrl ? 'a' : 'div';
|
|
const wrapperProps = hasUrl ? { href: company.url, target: "_blank", rel: "noopener noreferrer" } : {};
|
|
|
|
// Generate logo representation based on title
|
|
const isEtib = company.title.includes('E-TIB');
|
|
const isIng = company.title.includes('Ingenieur');
|
|
const isVerwaltung = company.title.includes('Verwaltung');
|
|
const isBohrtechnik = company.title.includes('Bohrtechnik');
|
|
const isNemo = company.title.includes('NEMO');
|
|
|
|
const bgPositionClasses = [
|
|
"-bottom-[30%] -right-[30%]",
|
|
"-top-[30%] -left-[30%]",
|
|
"-bottom-[30%] -left-[30%]",
|
|
"-top-[30%] -right-[30%]"
|
|
];
|
|
const animationClasses = [
|
|
"animate-[spin_60s_linear_infinite]",
|
|
"animate-[spin_80s_linear_infinite]",
|
|
"animate-[spin_100s_linear_infinite]",
|
|
"animate-[spin_120s_linear_infinite]"
|
|
];
|
|
const positionClass = bgPositionClasses[index % bgPositionClasses.length];
|
|
const animationClass = animationClasses[index % animationClasses.length];
|
|
|
|
return (
|
|
<motion.div
|
|
key={index}
|
|
variants={itemVariants}
|
|
className="h-full"
|
|
>
|
|
<CardWrapper
|
|
{...wrapperProps}
|
|
className={`group relative overflow-hidden aspect-[4/3] flex flex-col justify-center items-center shadow-xl transition-all duration-500 bg-neutral-dark block w-full h-full sm:rounded-xl select-none ${
|
|
isCurrent
|
|
? 'border-2 border-primary shadow-[0_0_30px_rgba(17,124,97,0.15)] cursor-default'
|
|
: 'border border-white/5 hover:shadow-2xl hover:-translate-y-1 hover:border-white/10 cursor-pointer'
|
|
}`}
|
|
>
|
|
<div className="absolute inset-0 bg-[#0a192f] z-0">
|
|
<Image
|
|
src={company.backgroundImage}
|
|
alt="Background"
|
|
fill
|
|
className={`object-cover transition-all duration-1000 ease-out ${
|
|
isCurrent
|
|
? 'opacity-30 grayscale-0 scale-105'
|
|
: 'opacity-40 grayscale-[50%] group-hover:opacity-30 group-hover:grayscale-0 group-hover:scale-110'
|
|
}`}
|
|
sizes="(max-width: 768px) 100vw, 33vw"
|
|
/>
|
|
</div>
|
|
|
|
{/* Heavy dark gradient overlay to make logos pop */}
|
|
<div className={`absolute inset-0 z-0 transition-colors duration-700 mix-blend-multiply ${
|
|
isCurrent
|
|
? 'bg-gradient-to-t from-[#0a192f]/90 via-[#0a192f]/60 to-[#0a192f]/40'
|
|
: 'bg-gradient-to-t from-[#0a192f]/90 via-[#0a192f]/60 to-[#0a192f]/40 group-hover:from-primary/90 group-hover:to-primary/20'
|
|
}`} />
|
|
|
|
{/* Subtle Background Logo Arcs */}
|
|
<div className={`absolute ${positionClass} w-[120%] h-[120%] z-10 opacity-[0.02] group-hover:opacity-[0.08] transition-opacity duration-1000 pointer-events-none mix-blend-overlay`}>
|
|
<LogoArcs className={`w-full h-full text-white ${animationClass}`} />
|
|
</div>
|
|
|
|
{/* Premium Shine Sweep Effect (Industrial Reflection) */}
|
|
<HoverShineOverlay shineColor="via-white/30" />
|
|
|
|
{/* Glossy Animated Border */}
|
|
<AnimatedGlossyBorder
|
|
color={isCurrent ? "primary" : "white"}
|
|
className={`transition-opacity duration-700 ${isCurrent ? 'opacity-100' : 'opacity-0 group-hover:opacity-100'}`}
|
|
borderWidth={1}
|
|
/>
|
|
|
|
{/* Current Site Indicator Badge */}
|
|
{isCurrent && (
|
|
<div className="absolute top-6 right-6 z-20">
|
|
<div className="flex items-center space-x-2 bg-neutral-dark/80 backdrop-blur-md border border-primary/40 px-3 py-1.5 rounded-full shadow-lg">
|
|
<span className="relative flex h-2 w-2">
|
|
<span className="animate-ping absolute inline-flex h-full w-full rounded-full bg-primary opacity-75"></span>
|
|
<span className="relative inline-flex rounded-full h-2 w-2 bg-primary"></span>
|
|
</span>
|
|
<span className="text-[10px] font-bold uppercase tracking-widest text-primary/90">
|
|
{isDe ? 'Aktuell hier' : 'You are here'}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
<div className="relative z-10 flex flex-col items-center justify-center w-full h-full p-8 transform group-hover:scale-105 transition-transform duration-500">
|
|
|
|
{/* LOGO RENDERING */}
|
|
{isEtib ? (
|
|
<div className="flex flex-col items-center">
|
|
<div className="relative w-48 h-14 mb-2">
|
|
<Image
|
|
src="/assets/logo-white.png"
|
|
alt="E-TIB Logo"
|
|
fill
|
|
className="object-contain"
|
|
/>
|
|
</div>
|
|
{isIng && (
|
|
<div className="text-white/80 tracking-[0.2em] text-[10px] sm:text-xs font-semibold uppercase mt-1 text-center">
|
|
Ingenieurgesellschaft
|
|
</div>
|
|
)}
|
|
{isVerwaltung && (
|
|
<div className="text-white/80 tracking-[0.2em] text-[10px] sm:text-xs font-semibold uppercase mt-1 text-center">
|
|
Verwaltung GmbH
|
|
</div>
|
|
)}
|
|
{isBohrtechnik && (
|
|
<div className="text-white/80 tracking-[0.2em] text-[10px] sm:text-xs font-semibold uppercase mt-1 text-center">
|
|
Bohrtechnik GmbH
|
|
</div>
|
|
)}
|
|
</div>
|
|
) : isNemo ? (
|
|
<div className="flex flex-col items-center">
|
|
<div className="text-5xl font-heading font-black text-white tracking-tight">
|
|
NEMO
|
|
</div>
|
|
<div className="text-white/60 tracking-widest text-xs font-semibold uppercase mt-1">
|
|
GmbH
|
|
</div>
|
|
</div>
|
|
) : (
|
|
<div className="text-2xl font-heading font-bold text-white uppercase text-center">
|
|
{company.title}
|
|
</div>
|
|
)}
|
|
|
|
</div>
|
|
|
|
{/* Subtle Link Indicator */}
|
|
{company.url && (
|
|
<div className="absolute bottom-6 left-0 right-0 flex justify-center opacity-0 group-hover:opacity-100 transform translate-y-4 group-hover:translate-y-0 transition-all duration-500 z-20">
|
|
<div className="flex items-center text-white font-bold uppercase text-xs tracking-widest bg-white/10 backdrop-blur-md px-4 py-2 rounded-full border border-white/20">
|
|
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>
|
|
)}
|
|
|
|
</CardWrapper>
|
|
</motion.div>
|
|
);
|
|
})}
|
|
</motion.div>
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|