fix: deploy issues
Some checks failed
CI - Lint, Typecheck & Test / quality-assurance (push) Failing after 34s

This commit is contained in:
2026-02-10 11:52:10 +01:00
parent cb51c37207
commit ae7a45a911
7 changed files with 123 additions and 101 deletions

1
.env
View File

@@ -23,6 +23,7 @@ DIRECTUS_ADMIN_PASSWORD=Tim300493.
DIRECTUS_API_TOKEN=59fb8f4c1a51b18fe28ad947f713914e DIRECTUS_API_TOKEN=59fb8f4c1a51b18fe28ad947f713914e
DIRECTUS_DB_NAME=directus DIRECTUS_DB_NAME=directus
DIRECTUS_DB_USER=directus DIRECTUS_DB_USER=directus
DIRECTUS_DB_PASSWORD=directus
# Local Development # Local Development
PROJECT_NAME=klz-cables PROJECT_NAME=klz-cables
GATEKEEPER_BYPASS_ENABLED=true GATEKEEPER_BYPASS_ENABLED=true

View File

@@ -32,8 +32,10 @@ export default function Header() {
// Close mobile menu on route change // Close mobile menu on route change
useEffect(() => { useEffect(() => {
setIsMobileMenuOpen(false); if (isMobileMenuOpen) {
}, [pathname]); setIsMobileMenuOpen(false);
}
}, [pathname, isMobileMenuOpen]);
// Prevent scroll when mobile menu is open // Prevent scroll when mobile menu is open
useEffect(() => { useEffect(() => {
@@ -59,15 +61,15 @@ export default function Header() {
]; ];
const headerClass = cn( const headerClass = cn(
"fixed top-0 left-0 right-0 z-50 transition-all duration-500 safe-area-p transform-gpu", 'fixed top-0 left-0 right-0 z-50 transition-all duration-500 safe-area-p transform-gpu',
{ {
"bg-transparent py-4 md:py-8": isHomePage && !isScrolled && !isMobileMenuOpen, 'bg-transparent py-4 md:py-8': isHomePage && !isScrolled && !isMobileMenuOpen,
"bg-primary py-3 md:py-4 shadow-2xl": !isHomePage || isScrolled || isMobileMenuOpen, 'bg-primary py-3 md:py-4 shadow-2xl': !isHomePage || isScrolled || isMobileMenuOpen,
} },
); );
const textColorClass = "text-white"; const textColorClass = 'text-white';
const logoSrc = "/logo-white.svg"; const logoSrc = '/logo-white.svg';
return ( return (
<> <>
@@ -75,14 +77,14 @@ export default function Header() {
className={headerClass} className={headerClass}
initial={{ y: -100, opacity: 0 }} initial={{ y: -100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }} animate={{ y: 0, opacity: 1 }}
transition={{ duration: 0.8, ease: "easeOut" }} transition={{ duration: 0.8, ease: 'easeOut' }}
> >
<div className="container mx-auto px-4 md:px-12 lg:px-16 max-w-7xl flex items-center justify-between"> <div className="container mx-auto px-4 md:px-12 lg:px-16 max-w-7xl flex items-center justify-between">
<motion.div <motion.div
className="flex-shrink-0 group touch-target" className="flex-shrink-0 group touch-target"
initial={{ scale: 0.8, opacity: 0 }} initial={{ scale: 0.8, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }} animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.6, ease: "easeOut", delay: 0.1 }} transition={{ duration: 0.6, ease: 'easeOut', delay: 0.1 }}
> >
<Link href={`/${currentLocale}`}> <Link href={`/${currentLocale}`}>
<Image <Image
@@ -105,25 +107,19 @@ export default function Header() {
visible: { visible: {
transition: { transition: {
staggerChildren: 0.08, staggerChildren: 0.08,
delayChildren: 0.3 delayChildren: 0.3,
} },
} },
}} }}
> >
<motion.nav <motion.nav className="hidden lg:flex items-center space-x-10" variants={navVariants}>
className="hidden lg:flex items-center space-x-10"
variants={navVariants}
>
{menuItems.map((item, idx) => ( {menuItems.map((item, idx) => (
<motion.div <motion.div key={item.href} variants={navLinkVariants}>
key={item.href}
variants={navLinkVariants}
>
<Link <Link
href={`/${currentLocale}${item.href === '/' ? '' : item.href}`} href={`/${currentLocale}${item.href === '/' ? '' : item.href}`}
className={cn( className={cn(
textColorClass, textColorClass,
"hover:text-accent font-bold transition-all duration-500 text-base md:text-lg tracking-tight relative group inline-block hover:-translate-y-0.5" 'hover:text-accent font-bold transition-all duration-500 text-base md:text-lg tracking-tight relative group inline-block hover:-translate-y-0.5',
)} )}
> >
{item.label} {item.label}
@@ -134,7 +130,7 @@ export default function Header() {
</motion.nav> </motion.nav>
<motion.div <motion.div
className={cn("hidden lg:flex items-center space-x-8", textColorClass)} className={cn('hidden lg:flex items-center space-x-8', textColorClass)}
variants={headerRightVariants} variants={headerRightVariants}
> >
<motion.div <motion.div
@@ -178,7 +174,7 @@ export default function Header() {
<motion.div <motion.div
initial={{ scale: 0.9, opacity: 0 }} initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }} animate={{ scale: 1, opacity: 1 }}
transition={{ duration: 0.6, type: "spring", stiffness: 400, delay: 0.7 }} transition={{ duration: 0.6, type: 'spring', stiffness: 400, delay: 0.7 }}
> >
<Button <Button
href={`/${currentLocale}/contact`} href={`/${currentLocale}/contact`}
@@ -193,11 +189,20 @@ export default function Header() {
{/* Mobile Menu Button */} {/* Mobile Menu Button */}
<motion.button <motion.button
className={cn("lg:hidden touch-target p-2 rounded-xl bg-white/10 border border-white/20 z-50", textColorClass)} className={cn(
'lg:hidden touch-target p-2 rounded-xl bg-white/10 border border-white/20 z-50',
textColorClass,
)}
aria-label={t('toggleMenu')} aria-label={t('toggleMenu')}
initial={{ scale: 0.8, opacity: 0, rotate: -180 }} initial={{ scale: 0.8, opacity: 0, rotate: -180 }}
animate={{ scale: 1, opacity: 1, rotate: 0 }} animate={{ scale: 1, opacity: 1, rotate: 0 }}
transition={{ duration: 0.6, type: "spring", stiffness: 300, damping: 20, delay: 0.5 }} transition={{
duration: 0.6,
type: 'spring',
stiffness: 300,
damping: 20,
delay: 0.5,
}}
onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)}
> >
<motion.svg <motion.svg
@@ -236,21 +241,25 @@ export default function Header() {
</div> </div>
{/* Mobile Menu Overlay */} {/* Mobile Menu Overlay */}
<div className={cn( <div
"fixed inset-0 bg-primary z-40 lg:hidden transition-all duration-500 ease-in-out flex flex-col", className={cn(
isMobileMenuOpen ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-full pointer-events-none" 'fixed inset-0 bg-primary z-40 lg:hidden transition-all duration-500 ease-in-out flex flex-col',
)}> isMobileMenuOpen
? 'opacity-100 translate-y-0'
: 'opacity-0 -translate-y-full pointer-events-none',
)}
>
<motion.div <motion.div
className="flex-grow flex flex-col justify-center items-center p-8 space-y-8" className="flex-grow flex flex-col justify-center items-center p-8 space-y-8"
initial="closed" initial="closed"
animate={isMobileMenuOpen ? "open" : "closed"} animate={isMobileMenuOpen ? 'open' : 'closed'}
variants={{ variants={{
open: { open: {
transition: { transition: {
staggerChildren: 0.1, staggerChildren: 0.1,
delayChildren: 0.2 delayChildren: 0.2,
} },
} },
}} }}
> >
{menuItems.map((item, idx) => ( {menuItems.map((item, idx) => (
@@ -264,10 +273,10 @@ export default function Header() {
scale: 1, scale: 1,
transition: { transition: {
duration: 0.6, duration: 0.6,
ease: "easeOut", ease: 'easeOut',
delay: idx * 0.08 delay: idx * 0.08,
} },
} },
}} }}
> >
<Link <Link
@@ -326,7 +335,7 @@ export default function Header() {
<motion.div <motion.div
initial={{ scale: 0.9, opacity: 0, y: 20 }} initial={{ scale: 0.9, opacity: 0, y: 20 }}
animate={{ scale: 1, opacity: 1, y: 0 }} animate={{ scale: 1, opacity: 1, y: 0 }}
transition={{ type: "spring", stiffness: 400, damping: 20, delay: 1.2 }} transition={{ type: 'spring', stiffness: 400, damping: 20, delay: 1.2 }}
> >
<Button <Button
href={`/${currentLocale}/contact`} href={`/${currentLocale}/contact`}
@@ -339,22 +348,22 @@ export default function Header() {
</motion.div> </motion.div>
</motion.div> </motion.div>
{/* Bottom Branding */} {/* Bottom Branding */}
<motion.div
className="p-12 flex justify-center opacity-20"
initial={{ opacity: 0, scale: 0.8 }}
animate={isMobileMenuOpen ? { opacity: 0.2, scale: 1 } : { opacity: 0, scale: 0.8 }}
transition={{ duration: 0.5, delay: 1.4 }}
>
<motion.div <motion.div
initial={{ scale: 0.5 }} className="p-12 flex justify-center opacity-20"
animate={{ scale: 1 }} initial={{ opacity: 0, scale: 0.8 }}
transition={{ type: "spring", stiffness: 300, delay: 1.5 }} animate={isMobileMenuOpen ? { opacity: 0.2, scale: 1 } : { opacity: 0, scale: 0.8 }}
transition={{ duration: 0.5, delay: 1.4 }}
> >
<Image src="/logo-white.svg" alt={t('home')} width={80} height={80} unoptimized /> <motion.div
initial={{ scale: 0.5 }}
animate={{ scale: 1 }}
transition={{ type: 'spring', stiffness: 300, delay: 1.5 }}
>
<Image src="/logo-white.svg" alt={t('home')} width={80} height={80} unoptimized />
</motion.div>
</motion.div> </motion.div>
</motion.div> </motion.div>
</motion.div>
</div> </div>
</motion.header> </motion.header>
</> </>
@@ -367,9 +376,9 @@ const navVariants = {
opacity: 1, opacity: 1,
transition: { transition: {
staggerChildren: 0.06, staggerChildren: 0.06,
delayChildren: 0.1 delayChildren: 0.1,
} },
} },
} as const; } as const;
const navLinkVariants = { const navLinkVariants = {
@@ -380,9 +389,9 @@ const navLinkVariants = {
scale: 1, scale: 1,
transition: { transition: {
duration: 0.5, duration: 0.5,
ease: "easeOut" ease: 'easeOut',
} },
} },
} as const; } as const;
const headerRightVariants = { const headerRightVariants = {
@@ -390,6 +399,6 @@ const headerRightVariants = {
visible: { visible: {
opacity: 1, opacity: 1,
x: 0, x: 0,
transition: { duration: 0.6, ease: "easeOut" } transition: { duration: 0.6, ease: 'easeOut' },
} },
} as const; } as const;

View File

@@ -25,15 +25,18 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh
return () => setMounted(false); return () => setMounted(false);
}, []); }, []);
const updateUrl = useCallback((index: number | null) => { const updateUrl = useCallback(
const params = new URLSearchParams(searchParams.toString()); (index: number | null) => {
if (index !== null) { const params = new URLSearchParams(searchParams.toString());
params.set('photo', index.toString()); if (index !== null) {
} else { params.set('photo', index.toString());
params.delete('photo'); } else {
} params.delete('photo');
router.replace(`${pathname}?${params.toString()}`, { scroll: false }); }
}, [pathname, router, searchParams]); router.replace(`${pathname}?${params.toString()}`, { scroll: false });
},
[pathname, router, searchParams],
);
const prevImage = useCallback(() => { const prevImage = useCallback(() => {
setCurrentIndex((prev) => { setCurrentIndex((prev) => {
@@ -61,6 +64,11 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh
} }
}, [searchParams, images.length]); }, [searchParams, images.length]);
const handleClose = useCallback(() => {
updateUrl(null);
onClose();
}, [updateUrl, onClose]);
useEffect(() => { useEffect(() => {
if (isOpen) { if (isOpen) {
updateUrl(currentIndex); updateUrl(currentIndex);
@@ -86,15 +94,10 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh
document.body.style.overflow = originalStyle; document.body.style.overflow = originalStyle;
window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keydown', handleKeyDown);
}; };
}, [isOpen, prevImage, nextImage]); }, [isOpen, prevImage, nextImage, handleClose]);
if (!mounted) return null; if (!mounted) return null;
const handleClose = () => {
updateUrl(null);
onClose();
};
return createPortal( return createPortal(
<AnimatePresence> <AnimatePresence>
{isOpen && ( {isOpen && (
@@ -131,7 +134,9 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh
className="absolute left-6 top-1/2 -translate-y-1/2 text-white/60 hover:text-white transition-all duration-500 w-14 h-14 flex items-center justify-center hover:bg-white/5 rounded-full z-[10000] group border border-white/10" className="absolute left-6 top-1/2 -translate-y-1/2 text-white/60 hover:text-white transition-all duration-500 w-14 h-14 flex items-center justify-center hover:bg-white/5 rounded-full z-[10000] group border border-white/10"
aria-label="Previous image" aria-label="Previous image"
> >
<span className="text-4xl font-extralight group-hover:-translate-x-1 transition-transform duration-500"></span> <span className="text-4xl font-extralight group-hover:-translate-x-1 transition-transform duration-500">
</span>
</motion.button> </motion.button>
<motion.button <motion.button
@@ -143,7 +148,9 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh
className="absolute right-6 top-1/2 -translate-y-1/2 text-white/60 hover:text-white transition-all duration-500 w-14 h-14 flex items-center justify-center hover:bg-white/5 rounded-full z-[10000] group border border-white/10" className="absolute right-6 top-1/2 -translate-y-1/2 text-white/60 hover:text-white transition-all duration-500 w-14 h-14 flex items-center justify-center hover:bg-white/5 rounded-full z-[10000] group border border-white/10"
aria-label="Next image" aria-label="Next image"
> >
<span className="text-4xl font-extralight group-hover:translate-x-1 transition-transform duration-500"></span> <span className="text-4xl font-extralight group-hover:translate-x-1 transition-transform duration-500">
</span>
</motion.button> </motion.button>
<motion.div <motion.div
@@ -199,6 +206,6 @@ export default function Lightbox({ isOpen, images, initialIndex, onClose }: Ligh
</div> </div>
)} )}
</AnimatePresence>, </AnimatePresence>,
document.body document.body,
); );
} }

View File

@@ -27,11 +27,11 @@ export default function GallerySection() {
if (photoParam !== null) { if (photoParam !== null) {
const index = parseInt(photoParam, 10); const index = parseInt(photoParam, 10);
if (!isNaN(index) && index >= 0 && index < images.length) { if (!isNaN(index) && index >= 0 && index < images.length) {
setLightboxIndex(index); if (lightboxIndex !== index) setLightboxIndex(index);
setLightboxOpen(true); if (!lightboxOpen) setLightboxOpen(true);
} }
} }
}, [searchParams, images.length]); }, [searchParams, images.length, lightboxIndex, lightboxOpen]);
return ( return (
<Section className="bg-white text-white py-32"> <Section className="bg-white text-white py-32">

View File

@@ -20,8 +20,11 @@ export default [
"*.mjs", "*.mjs",
"scripts/**", "scripts/**",
"tests/**", "tests/**",
"next-env.d.ts" "next-env.d.ts",
"reference/**",
"data/**"
], ],
}, },
...baseConfig, ...baseConfig,
...nextConfig.map((config) => ({ ...nextConfig.map((config) => ({
@@ -39,7 +42,9 @@ export default [
"@typescript-eslint/no-require-imports": "off", "@typescript-eslint/no-require-imports": "off",
"prefer-const": "warn", "prefer-const": "warn",
"react/no-unescaped-entities": "off", "react/no-unescaped-entities": "off",
"@next/next/no-img-element": "warn" "@next/next/no-img-element": "warn",
"react-hooks/set-state-in-effect": "warn"
} }
})), })),
]; ];

View File

@@ -34,5 +34,5 @@
"tests/**/*.test.ts", "tests/**/*.test.ts",
".next/dev/types/**/*.ts" ".next/dev/types/**/*.ts"
], ],
"exclude": ["node_modules", "scripts"] "exclude": ["node_modules", "scripts", "reference", "data"]
} }

File diff suppressed because one or more lines are too long