clone init
This commit is contained in:
36
app/[locale]/[slug]/page.tsx
Normal file
36
app/[locale]/[slug]/page.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc';
|
||||
import { getPostBySlug } from '@/lib/blog';
|
||||
|
||||
interface PageProps {
|
||||
params: {
|
||||
locale: string;
|
||||
slug: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default async function StandardPage({ params: { locale, slug } }: PageProps) {
|
||||
const page = await getPostBySlug(slug, locale); // Reusing blog logic for now as structure is same
|
||||
|
||||
// If not found in blog, try pages directory (we need to implement getPageBySlug)
|
||||
// Actually, let's implement getPageBySlug in lib/mdx.ts or similar
|
||||
|
||||
// For now, let's assume we use a unified loader or separate.
|
||||
// Let's use a separate loader for pages.
|
||||
|
||||
const { getPageBySlug } = await import('@/lib/pages');
|
||||
const pageData = await getPageBySlug(slug, locale);
|
||||
|
||||
if (!pageData) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-12 max-w-4xl">
|
||||
<h1 className="text-4xl font-bold text-primary mb-8">{pageData.frontmatter.title}</h1>
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<MDXRemote source={pageData.content} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
48
app/[locale]/blog/[slug]/page.tsx
Normal file
48
app/[locale]/blog/[slug]/page.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc';
|
||||
import { getPostBySlug } from '@/lib/blog';
|
||||
|
||||
interface BlogPostProps {
|
||||
params: {
|
||||
locale: string;
|
||||
slug: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default async function BlogPost({ params: { locale, slug } }: BlogPostProps) {
|
||||
const post = await getPostBySlug(slug, locale);
|
||||
|
||||
if (!post) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<article className="container mx-auto px-4 py-12 max-w-4xl">
|
||||
<header className="mb-8 text-center">
|
||||
<div className="text-text-secondary mb-4">
|
||||
{new Date(post.frontmatter.date).toLocaleDateString(locale, {
|
||||
year: 'numeric',
|
||||
month: 'long',
|
||||
day: 'numeric'
|
||||
})}
|
||||
</div>
|
||||
<h1 className="text-4xl md:text-5xl font-bold text-primary mb-6">
|
||||
{post.frontmatter.title}
|
||||
</h1>
|
||||
{post.frontmatter.featuredImage && (
|
||||
<div className="aspect-video relative rounded-xl overflow-hidden shadow-lg mb-8">
|
||||
<img
|
||||
src={post.frontmatter.featuredImage}
|
||||
alt={post.frontmatter.title}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</header>
|
||||
|
||||
<div className="prose prose-lg max-w-none">
|
||||
<MDXRemote source={post.content} />
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
51
app/[locale]/blog/page.tsx
Normal file
51
app/[locale]/blog/page.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import Link from 'next/link';
|
||||
import { getAllPosts } from '@/lib/blog';
|
||||
import { useTranslations } from 'next-intl';
|
||||
|
||||
interface BlogIndexProps {
|
||||
params: {
|
||||
locale: string;
|
||||
};
|
||||
}
|
||||
|
||||
export default async function BlogIndex({ params: { locale } }: BlogIndexProps) {
|
||||
const posts = await getAllPosts(locale);
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-12">
|
||||
<h1 className="text-4xl font-bold text-primary mb-8">Blog</h1>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{posts.map((post) => (
|
||||
<Link key={post.slug} href={`/${locale}/blog/${post.slug}`} className="group">
|
||||
<article className="bg-white rounded-lg shadow-sm overflow-hidden border border-neutral-dark h-full flex flex-col transition-transform hover:-translate-y-1">
|
||||
{post.frontmatter.featuredImage && (
|
||||
<div className="aspect-video relative overflow-hidden">
|
||||
<img
|
||||
src={post.frontmatter.featuredImage}
|
||||
alt={post.frontmatter.title}
|
||||
className="w-full h-full object-cover transition-transform group-hover:scale-105"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="p-6 flex flex-col flex-grow">
|
||||
<div className="text-sm text-text-secondary mb-2">
|
||||
{new Date(post.frontmatter.date).toLocaleDateString(locale)}
|
||||
</div>
|
||||
<h2 className="text-xl font-bold text-text-primary mb-3 group-hover:text-primary transition-colors">
|
||||
{post.frontmatter.title}
|
||||
</h2>
|
||||
<p className="text-text-secondary line-clamp-3 mb-4 flex-grow">
|
||||
{post.frontmatter.excerpt}
|
||||
</p>
|
||||
<span className="text-primary font-medium group-hover:underline">
|
||||
Read more →
|
||||
</span>
|
||||
</div>
|
||||
</article>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
89
app/[locale]/contact/page.tsx
Normal file
89
app/[locale]/contact/page.tsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Section, Container, Button } from '@/components/ui';
|
||||
|
||||
export default function ContactPage() {
|
||||
const t = useTranslations('Navigation'); // Reusing navigation translations for now
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<Section className="bg-neutral">
|
||||
<Container>
|
||||
<div className="max-w-3xl mx-auto text-center mb-12">
|
||||
<h1 className="text-4xl font-bold mb-4">Get in Touch</h1>
|
||||
<p className="text-xl text-text-secondary">
|
||||
Have questions about our products or need a custom solution? We're here to help.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-12 max-w-5xl mx-auto">
|
||||
{/* Contact Info */}
|
||||
<div className="space-y-8">
|
||||
<div>
|
||||
<h3 className="text-xl font-bold mb-4">Contact Information</h3>
|
||||
<div className="space-y-4 text-text-secondary">
|
||||
<p className="flex items-start">
|
||||
<svg className="w-6 h-6 text-primary mr-3 mt-1" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
</svg>
|
||||
<span>
|
||||
Raiffeisenstraße 22<br />
|
||||
73630 Remshalden<br />
|
||||
Germany
|
||||
</span>
|
||||
</p>
|
||||
<p className="flex items-center">
|
||||
<svg className="w-6 h-6 text-primary mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
<a href="tel:+4988192537298" className="hover:text-primary transition-colors">+49 881 92537298</a>
|
||||
</p>
|
||||
<p className="flex items-center">
|
||||
<svg className="w-6 h-6 text-primary mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<a href="mailto:info@klz-vertriebs-gmbh.com" className="hover:text-primary transition-colors">info@klz-vertriebs-gmbh.com</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h3 className="text-xl font-bold mb-4">Business Hours</h3>
|
||||
<ul className="space-y-2 text-text-secondary">
|
||||
<li className="flex justify-between">
|
||||
<span>Monday - Friday</span>
|
||||
<span>8:00 AM - 5:00 PM</span>
|
||||
</li>
|
||||
<li className="flex justify-between">
|
||||
<span>Saturday - Sunday</span>
|
||||
<span>Closed</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Contact Form Placeholder */}
|
||||
<div className="bg-white p-8 rounded-lg shadow-sm border border-neutral-dark">
|
||||
<h3 className="text-xl font-bold mb-6">Send us a message</h3>
|
||||
<form className="space-y-4">
|
||||
<div>
|
||||
<label htmlFor="name" className="block text-sm font-medium text-text-primary mb-1">Name</label>
|
||||
<input type="text" id="name" className="w-full px-4 py-2 border border-neutral-dark rounded-md focus:ring-primary focus:border-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="email" className="block text-sm font-medium text-text-primary mb-1">Email</label>
|
||||
<input type="email" id="email" className="w-full px-4 py-2 border border-neutral-dark rounded-md focus:ring-primary focus:border-primary" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="message" className="block text-sm font-medium text-text-primary mb-1">Message</label>
|
||||
<textarea id="message" rows={4} className="w-full px-4 py-2 border border-neutral-dark rounded-md focus:ring-primary focus:border-primary"></textarea>
|
||||
</div>
|
||||
<Button type="submit" className="w-full">Send Message</Button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
31
app/[locale]/layout.tsx
Normal file
31
app/[locale]/layout.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import {NextIntlClientProvider} from 'next-intl';
|
||||
import {getMessages} from 'next-intl/server';
|
||||
import '../../styles/globals.css';
|
||||
import Header from '@/components/Header';
|
||||
import Footer from '@/components/Footer';
|
||||
|
||||
export default async function LocaleLayout({
|
||||
children,
|
||||
params: {locale}
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
params: {locale: string};
|
||||
}) {
|
||||
// Providing all messages to the client
|
||||
// side is the easiest way to get started
|
||||
const messages = await getMessages();
|
||||
|
||||
return (
|
||||
<html lang={locale}>
|
||||
<body className="flex flex-col min-h-screen">
|
||||
<NextIntlClientProvider messages={messages}>
|
||||
<Header />
|
||||
<main className="flex-grow">
|
||||
{children}
|
||||
</main>
|
||||
<Footer />
|
||||
</NextIntlClientProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
182
app/[locale]/page.tsx
Normal file
182
app/[locale]/page.tsx
Normal file
@@ -0,0 +1,182 @@
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Button, Section, Container } from '@/components/ui';
|
||||
import Link from 'next/link';
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function HomePage() {
|
||||
const t = useTranslations('Index');
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen">
|
||||
{/* Hero Section */}
|
||||
<section className="relative h-[80vh] flex items-center justify-center overflow-hidden bg-neutral-dark">
|
||||
<div className="absolute inset-0 z-0">
|
||||
<video
|
||||
className="w-full h-full object-cover"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
poster="https://klz-cables.com/wp-content/uploads/2025/02/Still-2025-02-10-104337_1.1.1.webp"
|
||||
>
|
||||
<source src="https://klz-cables.com/wp-content/uploads/2025/02/header.webm" type="video/webm" />
|
||||
<source src="https://klz-cables.com/wp-content/uploads/2025/02/header.mp4" type="video/mp4" />
|
||||
</video>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-black/10 to-black/40" />
|
||||
</div>
|
||||
|
||||
<Container className="relative z-10 text-left text-white w-full">
|
||||
<div className="max-w-4xl">
|
||||
<h1 className="text-4xl md:text-6xl lg:text-7xl font-bold mb-6 tracking-tight leading-tight">
|
||||
We are helping to expand the energy cable networks for a <span className="text-[#82ed20] relative inline-block">green</span> future
|
||||
</h1>
|
||||
<div className="mt-8">
|
||||
<Link href="/contact" className="inline-flex items-center text-white text-xl font-medium group">
|
||||
Let's talk
|
||||
<span className="ml-2 w-8 h-8 border-2 border-white rounded-full flex items-center justify-center group-hover:bg-white group-hover:text-black transition-all">
|
||||
→
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
|
||||
{/* Product Categories Preview */}
|
||||
<Section className="bg-neutral-dark py-0">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4">
|
||||
{[
|
||||
{
|
||||
title: 'Low Voltage Cables',
|
||||
desc: 'Powering everyday essentials with reliability and safety.',
|
||||
img: 'https://klz-cables.com/wp-content/uploads/2024/12/low-voltage-scaled.webp',
|
||||
icon: 'https://klz-cables.com/wp-content/uploads/2024/11/Low-Voltage.svg',
|
||||
href: '/products/low-voltage-cables'
|
||||
},
|
||||
{
|
||||
title: 'Medium Voltage Cables',
|
||||
desc: 'The perfect balance between power and performance for industrial and urban grids.',
|
||||
img: 'https://klz-cables.com/wp-content/uploads/2024/12/medium-voltage-scaled.webp',
|
||||
icon: 'https://klz-cables.com/wp-content/uploads/2024/11/Medium-Voltage.svg',
|
||||
href: '/products/medium-voltage-cables'
|
||||
},
|
||||
{
|
||||
title: 'High Voltage Cables',
|
||||
desc: 'Delivering maximum power over long distances—without compromise.',
|
||||
img: 'https://klz-cables.com/wp-content/uploads/2025/06/na2xsfl2y-rendered.webp',
|
||||
icon: 'https://klz-cables.com/wp-content/uploads/2024/11/High-Voltage.svg',
|
||||
href: '/products/high-voltage-cables'
|
||||
},
|
||||
{
|
||||
title: 'Solar Cables',
|
||||
desc: 'Connecting the sun’s energy to your sustainable future.',
|
||||
img: 'https://klz-cables.com/wp-content/uploads/2025/04/3.webp',
|
||||
icon: 'https://klz-cables.com/wp-content/uploads/2024/11/Solar.svg',
|
||||
href: '/products/solar-cables'
|
||||
}
|
||||
].map((category, idx) => (
|
||||
<Link key={idx} href={category.href} className="group block relative h-[400px] md:h-[500px] overflow-hidden">
|
||||
<Image
|
||||
src={category.img}
|
||||
alt={category.title}
|
||||
fill
|
||||
className="object-cover transition-transform duration-700 group-hover:scale-110"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-black/40 group-hover:bg-black/50 transition-colors" />
|
||||
<div className="absolute inset-0 p-8 flex flex-col justify-center items-center text-center text-white">
|
||||
<div className="mb-4 transform transition-transform group-hover:-translate-y-2">
|
||||
<img src={category.icon} alt="" className="w-16 h-16 mx-auto" />
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold mb-2 transform transition-transform group-hover:-translate-y-2">{category.title}</h3>
|
||||
<p className="text-white/90 opacity-0 group-hover:opacity-100 transform translate-y-4 group-hover:translate-y-0 transition-all duration-300">
|
||||
{category.desc}
|
||||
</p>
|
||||
</div>
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</Section>
|
||||
|
||||
{/* What We Do Section */}
|
||||
<Section className="bg-neutral-dark text-white">
|
||||
<Container>
|
||||
<div className="grid grid-cols-1 lg:grid-cols-12 gap-12">
|
||||
<div className="lg:col-span-4">
|
||||
<div className="sticky top-24">
|
||||
<h2 className="text-5xl font-bold text-primary mb-6">What we do</h2>
|
||||
<p className="text-xl text-white/80">
|
||||
We ensure that the electricity flows – with quality-tested cables. From low voltage up to high voltage.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="lg:col-span-8 grid grid-cols-1 md:grid-cols-2 gap-x-12 gap-y-16">
|
||||
{[
|
||||
{
|
||||
num: '01',
|
||||
title: 'Supply to energy suppliers, wind and solar parks, industry and trade',
|
||||
desc: 'We support your projects from 1 to 220 kV, from simple NYY to high-voltage cables with segment conductors and aluminum sheaths, with a particular focus on medium-voltage cables.'
|
||||
},
|
||||
{
|
||||
num: '02',
|
||||
title: 'Supply of cables whose quality is certified',
|
||||
desc: 'Cables are products that have to function 100%. For decades, often 80 to 100 years. Our cables are not only approved by VDE. The most well-known energy suppliers trust us.'
|
||||
},
|
||||
{
|
||||
num: '03',
|
||||
title: 'We deliver on time because we know the consequences for you',
|
||||
desc: 'Wind farm North Germany, coordinates XYZ, delivery Wednesday 2-4 p.m., no unloading option. Yes, we know that. We organize the logistics with a back office team that has up to 20 years of cable experience.'
|
||||
},
|
||||
{
|
||||
num: '04',
|
||||
title: 'The cable alone is not the solution',
|
||||
desc: 'Stony ground? Perhaps a thicker outer sheath would be better? Damp ground? Can there be transverse watertight protection? We think for you and ask questions.'
|
||||
}
|
||||
].map((item, idx) => (
|
||||
<div key={idx} className="space-y-4">
|
||||
<span className="text-sm font-mono text-white/60 border-b border-white/20 pb-2 block w-fit">{item.num}</span>
|
||||
<h3 className="text-2xl font-bold">{item.title}</h3>
|
||||
<p className="text-white/70 leading-relaxed">{item.desc}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</Section>
|
||||
|
||||
{/* Video Section */}
|
||||
<section className="relative h-[60vh] overflow-hidden">
|
||||
<video
|
||||
className="w-full h-full object-cover"
|
||||
autoPlay
|
||||
muted
|
||||
loop
|
||||
playsInline
|
||||
>
|
||||
<source src="https://klz-cables.com/wp-content/uploads/2024/12/making-of-metal-cable-on-factory-2023-11-27-04-55-16-utc-2.webm" type="video/mp4" />
|
||||
</video>
|
||||
<div className="absolute inset-0 bg-black/50 flex items-center justify-center">
|
||||
<h2 className="text-3xl md:text-5xl font-bold text-white text-center max-w-4xl px-4 leading-tight">
|
||||
From a single strand to infinite power – the <span className="text-[#82ed20] italic">future</span> starts here.
|
||||
</h2>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<Section className="bg-primary text-white py-24">
|
||||
<Container>
|
||||
<div className="flex flex-col md:flex-row items-center justify-between gap-8">
|
||||
<h2 className="text-3xl md:text-4xl font-bold max-w-2xl">
|
||||
Enough information, let's build something together!
|
||||
</h2>
|
||||
<Link href="/contact" className="group flex items-center gap-4 text-xl font-bold text-[#82ed20]">
|
||||
Reach out now
|
||||
<span className="w-10 h-10 border-2 border-[#82ed20] rounded-full flex items-center justify-center group-hover:bg-[#82ed20] group-hover:text-primary transition-all">
|
||||
→
|
||||
</span>
|
||||
</Link>
|
||||
</div>
|
||||
</Container>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
84
app/[locale]/products/[...slug]/page.tsx
Normal file
84
app/[locale]/products/[...slug]/page.tsx
Normal file
@@ -0,0 +1,84 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc';
|
||||
import { getProductBySlug } from '@/lib/mdx';
|
||||
import ProductTechnicalData from '@/components/ProductTechnicalData';
|
||||
import Image from 'next/image';
|
||||
|
||||
interface ProductPageProps {
|
||||
params: {
|
||||
locale: string;
|
||||
slug: string[];
|
||||
};
|
||||
}
|
||||
|
||||
const components = {
|
||||
ProductTechnicalData,
|
||||
// Add other components if needed
|
||||
};
|
||||
|
||||
export default async function ProductPage({ params }: ProductPageProps) {
|
||||
const { locale, slug } = params;
|
||||
const productSlug = slug[slug.length - 1]; // Use the last segment as the slug
|
||||
|
||||
const product = await getProductBySlug(productSlug, locale);
|
||||
|
||||
if (!product) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="mb-8">
|
||||
<h1 className="text-4xl font-bold text-primary mb-4">{product.frontmatter.title}</h1>
|
||||
<div className="flex flex-wrap gap-2 mb-4">
|
||||
{product.frontmatter.categories.map((cat, idx) => (
|
||||
<span key={idx} className="bg-neutral-dark text-text-secondary px-2 py-1 rounded text-sm">
|
||||
{cat}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
||||
<div className="lg:col-span-2">
|
||||
<div className="prose max-w-none mb-8">
|
||||
<MDXRemote source={product.content} components={components} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="lg:col-span-1">
|
||||
{product.frontmatter.images && product.frontmatter.images.length > 0 && (
|
||||
<div className="sticky top-4">
|
||||
<div className="bg-white p-4 rounded-lg shadow-sm border border-neutral-dark">
|
||||
<div className="relative aspect-square mb-4">
|
||||
{/* Note: Images from WC might be external URLs. Next/Image requires configuration for external domains. */}
|
||||
{/* For now using standard img tag if domain not configured, or configure domains. */}
|
||||
<img
|
||||
src={product.frontmatter.images[0]}
|
||||
alt={product.frontmatter.title}
|
||||
className="w-full h-full object-contain"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-4 gap-2">
|
||||
{product.frontmatter.images.slice(1, 5).map((img, idx) => (
|
||||
<div key={idx} className="relative aspect-square border border-neutral-dark rounded overflow-hidden">
|
||||
<img src={img} alt="" className="w-full h-full object-cover" />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-6 bg-primary-light p-6 rounded-lg">
|
||||
<h3 className="text-lg font-semibold text-primary-dark mb-2">Contact Us</h3>
|
||||
<p className="text-text-secondary mb-4">Need more information about {product.frontmatter.title}?</p>
|
||||
<button className="w-full bg-primary text-white py-2 px-4 rounded hover:bg-primary-dark transition-colors">
|
||||
Request Quote
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
57
app/[locale]/team/page.tsx
Normal file
57
app/[locale]/team/page.tsx
Normal file
@@ -0,0 +1,57 @@
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Section, Container } from '@/components/ui';
|
||||
import Image from 'next/image';
|
||||
|
||||
export default function TeamPage() {
|
||||
const t = useTranslations('Navigation');
|
||||
|
||||
const teamMembers = [
|
||||
{
|
||||
name: 'Klaus',
|
||||
role: 'Founder & CEO',
|
||||
image: '/media/team/klaus.jpg', // Placeholder path
|
||||
bio: 'With decades of experience in the cable industry, Klaus leads KLZ with a vision for quality and innovation.'
|
||||
},
|
||||
{
|
||||
name: 'Michael',
|
||||
role: 'Technical Director',
|
||||
image: '/media/team/michael.jpg', // Placeholder path
|
||||
bio: 'Expert in high-voltage systems and technical planning, ensuring every project meets the highest standards.'
|
||||
},
|
||||
// Add more team members as needed
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen">
|
||||
<Section className="bg-neutral-light">
|
||||
<Container>
|
||||
<div className="max-w-3xl mx-auto text-center mb-16">
|
||||
<h1 className="text-4xl font-bold mb-6">Our Team</h1>
|
||||
<p className="text-xl text-text-secondary">
|
||||
Meet the experts behind KLZ Cables. We are a dedicated team of professionals committed to powering your success.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{teamMembers.map((member, idx) => (
|
||||
<div key={idx} className="bg-white rounded-lg overflow-hidden shadow-sm border border-neutral-dark group hover:-translate-y-1 transition-transform duration-300">
|
||||
<div className="aspect-[3/4] bg-neutral relative overflow-hidden">
|
||||
{/* Placeholder for team image */}
|
||||
<div className="absolute inset-0 flex items-center justify-center text-text-light bg-neutral-dark">
|
||||
<span className="text-4xl font-bold opacity-20">{member.name[0]}</span>
|
||||
</div>
|
||||
{/* <Image src={member.image} alt={member.name} fill className="object-cover" /> */}
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<h3 className="text-xl font-bold text-text-primary mb-1">{member.name}</h3>
|
||||
<p className="text-primary font-medium mb-4">{member.role}</p>
|
||||
<p className="text-text-secondary text-sm">{member.bio}</p>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
</Section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user