diff --git a/app/[locale]/[slug]/page.tsx b/app/[locale]/[slug]/page.tsx index 2a29fc51e..e30e8c478 100644 --- a/app/[locale]/[slug]/page.tsx +++ b/app/[locale]/[slug]/page.tsx @@ -132,52 +132,57 @@ export default async function Page(props: { params: Promise<{ locale: string; sl } */ - // Full-bleed pages render blocks edge-to-edge without the generic article wrapper - if (pageData.frontmatter.layout === 'fullBleed') { - return ( -
- -
- ); - } + // Determine layout type + const isFullBleed = pageData.frontmatter.layout === 'fullBleed'; - // Default article layout with hero, content, and support CTA return ( -
- {/* Hero Section */} -
-
-
-
- -
- - {t('badge')} - - - {pageData.frontmatter.title} - +
+ {/* Generic Hero Section (only for standard pages) */} + {!isFullBleed && ( +
+
+
- -
+ +
+ + {t('badge')} + + + {pageData.frontmatter.title} + +
+
+
+ )} {/* Main Content Area */} - - {/* Excerpt/Lead paragraph if available */} - {pageData.frontmatter.excerpt && ( -
-

- {pageData.frontmatter.excerpt} -

-
- )} - - {/* Main content */} + {isFullBleed ? (
+ ) : ( + + {/* Excerpt/Lead paragraph if available */} + {pageData.frontmatter.excerpt && ( +
+

+ {pageData.frontmatter.excerpt} +

+
+ )} - {/* Support Section */} + {/* Main content */} +
+
+ +
+
+
+ )} + + {/* Support Section */} +
diff --git a/components/blocks/CallToAction.tsx b/components/blocks/CallToAction.tsx index 87eac0ae4..d20427a92 100644 --- a/components/blocks/CallToAction.tsx +++ b/components/blocks/CallToAction.tsx @@ -1,5 +1,8 @@ +'use client'; + import React from 'react'; import { Button } from '@/components/ui/Button'; +import { motion } from 'framer-motion'; export interface CallToActionProps { title?: string; @@ -9,6 +12,26 @@ export interface CallToActionProps { theme?: 'light' | 'dark'; } +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.15, + delayChildren: 0.1, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] }, + }, +}; + export const CallToAction: React.FC = ({ title = 'Bereit für Ihr Projekt?', description = 'Wir suchen stets nach neuen Herausforderungen und starken Partnern. Kontaktieren Sie uns für eine unverbindliche Beratung zu Ihrem Vorhaben.', @@ -20,21 +43,29 @@ export const CallToAction: React.FC = ({ return (
-
-

+ + {title} -

-

+ + {description} -

- -
+ + + + +
); }; diff --git a/components/blocks/ContactSection.tsx b/components/blocks/ContactSection.tsx index 1597309a0..c88f28c2a 100644 --- a/components/blocks/ContactSection.tsx +++ b/components/blocks/ContactSection.tsx @@ -4,6 +4,7 @@ import React, { Suspense } from 'react'; import { Section, Container } from '@/components/ui'; import { ContactForm } from '@/components/forms/ContactForm'; import dynamic from 'next/dynamic'; +import { motion } from 'framer-motion'; const ContactMap = dynamic(() => import('@/components/ContactMap'), { ssr: false, @@ -15,63 +16,96 @@ export interface ContactSectionProps { showMap?: boolean; } +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.15, + delayChildren: 0.2, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, x: -20 }, + visible: { opacity: 1, x: 0, transition: { duration: 0.6, ease: [0.16, 1, 0.3, 1] } }, +}; + +const formVariants = { + hidden: { opacity: 0, y: 30 }, + visible: { opacity: 1, y: 0, transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1], delay: 0.4 } }, +}; + export const ContactSection: React.FC = (props) => { const { showForm, showMap } = props; return ( -
+
-
-

Direktkontakt

-

Wir sind für Sie da.

-

+ + Direktkontakt + Wir sind für Sie da. + Haben Sie Fragen zu unseren Leistungen oder möchten Sie ein konkretes Projekt besprechen? Rufen Sie uns an oder schreiben Sie uns eine E-Mail. -

+
-
-
+ +
-

Telefon

+

Telefon

+49 (0) 3561 / 68577 33

-
+ -
-
+ +
-

E-Mail

+

E-Mail

info@e-tib.com

-
+ -
-
+ +
-

Standort

+

Standort

Gewerbestraße 22
03172 Guben
Deutschland

-
+
-
+ {showForm && ( -
+ @@ -79,12 +113,18 @@ export const ContactSection: React.FC = (props) => { > -
+ )}
{showMap && ( -
+ } > @@ -94,7 +134,7 @@ export const ContactSection: React.FC = (props) => { lng={14.7214} /> -
+ )}
); diff --git a/components/blocks/HeroSection.tsx b/components/blocks/HeroSection.tsx index 1fa034444..a79911490 100644 --- a/components/blocks/HeroSection.tsx +++ b/components/blocks/HeroSection.tsx @@ -1,6 +1,8 @@ +'use client'; + import React from 'react'; import Image from 'next/image'; -import Reveal from '@/components/Reveal'; +import { motion } from 'framer-motion'; import { Badge, Container, Heading } from '@/components/ui'; import { Button } from '@/components/ui/Button'; @@ -14,63 +16,97 @@ export interface HeroSectionProps { ctaHref?: string; } +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.15, + delayChildren: 0.1, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, y: 30 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] } + }, +}; + export const HeroSection: React.FC = (props) => { const { title, badge, subtitle, backgroundImage, alignment, ctaLabel, ctaHref } = props; const bgSrc = backgroundImage?.sizes?.card?.url || backgroundImage?.url; return ( - -
- {bgSrc && ( -
- {title -
-
- )} - -
- {badge && ( +
+ {bgSrc && ( + + {title +
+ + )} + + + {badge && ( + {badge} - )} + + )} + {title} - {subtitle && ( + + {subtitle && ( +

{subtitle}

- )} - {ctaLabel && ctaHref && ( -
- -
- )} -
- -
- + + )} + {ctaLabel && ctaHref && ( + + + + )} + + +
); }; diff --git a/components/blocks/InteractiveGermanyMap.tsx b/components/blocks/InteractiveGermanyMap.tsx index 86e99905a..e606c904e 100644 --- a/components/blocks/InteractiveGermanyMap.tsx +++ b/components/blocks/InteractiveGermanyMap.tsx @@ -5,7 +5,7 @@ import { motion, AnimatePresence } from 'framer-motion'; import { MapPin, Factory, Zap, CheckCircle2 } from 'lucide-react'; import Image from 'next/image'; import { useRouter } from 'next/navigation'; -import { Location } from '@/lib/map-data'; +import { Location, defaultLocations } from '@/lib/map-data'; interface Stat { value: string; diff --git a/components/blocks/JobListingBlock.tsx b/components/blocks/JobListingBlock.tsx index e656622ed..51a663f21 100644 --- a/components/blocks/JobListingBlock.tsx +++ b/components/blocks/JobListingBlock.tsx @@ -1,7 +1,10 @@ +'use client'; + import React from 'react'; import Link from 'next/link'; import { Button } from '@/components/ui/Button'; import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; +import { motion } from 'framer-motion'; export interface JobListingBlockProps { title?: string; @@ -21,7 +24,27 @@ export interface JobListingBlockProps { emptyStateLinkHref?: string; } -export const JobListingBlock = async (props: JobListingBlockProps) => { +const containerVariants = { + hidden: { opacity: 0 }, + visible: { + opacity: 1, + transition: { + staggerChildren: 0.15, + delayChildren: 0.1, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, y: 30 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] }, + }, +}; + +export const JobListingBlock = (props: JobListingBlockProps) => { const { title, showJobs = true, @@ -45,11 +68,23 @@ export const JobListingBlock = async (props: JobListingBlockProps) => {
{showFairs && (
-

+ {fairsTitle} -

-
+ + {fairs.map((messe, idx) => { const isLink = !!messe.url; const innerContent = ( @@ -120,58 +155,77 @@ export const JobListingBlock = async (props: JobListingBlockProps) => { if (isLink) { return ( - + {innerContent} - + ); } return ( -
+ {innerContent} -
+
); })} -
+
)} {showJobs && (
-

+ {title || 'Aktuelle Stellenangebote'} -

+ {jobs.length > 0 ? ( -
+ {jobs.map((job: any) => ( - -
-
- {job.type} - {job.department} + + +
+
+ {job.type} + {job.department} +
+

{job.title}

+

{job.location}

-

{job.title}

-

{job.location}

-
-
- Details ansehen - -
- +
+ Details ansehen + +
+ + ))} -
+
) : ( -
+

{emptyStateMessage}

-
+ )}
)} diff --git a/components/blocks/SupportCTA.tsx b/components/blocks/SupportCTA.tsx index f90d8ccf9..2a6a2f2a9 100644 --- a/components/blocks/SupportCTA.tsx +++ b/components/blocks/SupportCTA.tsx @@ -1,6 +1,9 @@ +'use client'; + import React from 'react'; import TrackedLink from '@/components/analytics/TrackedLink'; import { getButtonClasses, ButtonOverlay } from '@/components/ui/Button'; +import { motion } from 'framer-motion'; export interface SupportCTAProps { title: string; @@ -9,31 +12,62 @@ export interface SupportCTAProps { buttonHref: string; } +const containerVariants = { + hidden: { opacity: 0, y: 30 }, + visible: { + opacity: 1, + y: 0, + transition: { + duration: 0.8, + ease: [0.16, 1, 0.3, 1], + staggerChildren: 0.15, + delayChildren: 0.1, + }, + }, +}; + +const itemVariants = { + hidden: { opacity: 0, y: 20 }, + visible: { + opacity: 1, + y: 0, + transition: { duration: 0.6, ease: [0.16, 1, 0.3, 1] }, + }, +}; + export const SupportCTA: React.FC = (props) => { const { title, description, buttonLabel, buttonHref } = props; return ( -
-
+ +
-

{title}

-

{description}

- - - {buttonLabel} - - → + {title} + {description} + + + + {buttonLabel} + + → + - - - + + +
-
+
); }; diff --git a/components/blocks/TeamGrid.tsx b/components/blocks/TeamGrid.tsx index 07343dae3..e43a6dae8 100644 --- a/components/blocks/TeamGrid.tsx +++ b/components/blocks/TeamGrid.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { motion } from 'framer-motion'; import Image from 'next/image'; +import { HoverShineOverlay } from '@/components/ui/HoverShineOverlay'; export interface TeamMember { id: string; @@ -25,12 +26,12 @@ export function TeamGrid({ members }: TeamGridProps) { if (!members || members.length === 0) return null; return ( -
-
+
+

Persönliche Beratung

Ihre Ansprechpartner

-

+

Sprechen Sie direkt mit unseren Experten für Ihr regionales Projekt.

@@ -39,48 +40,60 @@ export function TeamGrid({ members }: TeamGridProps) { {members.map((member, i) => ( -
-
- {member.image && typeof member.image === 'object' && member.image.url ? ( - {member.name} - ) : ( -
- -
+ + +
+
+
+ {member.image && typeof member.image === 'object' && member.image.url ? ( + {member.name} + ) : ( +
+ +
+ )} +
+
+

{member.name}

+

{member.position}

+

+ {member.branch === 'e-tib' ? 'E-TIB GmbH' : member.branch === 'ing' ? 'Ingenieurgesellschaft' : 'Bohrtechnik'} +

+
+
+ +
+ {member.email && ( + +
+ +
+ {member.email} + +
+ )} + {member.phone && ( + +
+ +
+ {member.phone} + +
)}
-
-

{member.name}

-

{member.position}

-

{member.branch === 'e-tib' ? 'E-TIB GmbH' : member.branch === 'ing' ? 'Ingenieurgesellschaft' : 'Bohrtechnik'}

-
-
- -
- {member.email && ( - - - {member.email} - - )} - {member.phone && ( - - - {member.phone} - - )}
))} diff --git a/content/de/home.mdx b/content/de/home.mdx index 29730d47a..c3a3c552b 100644 --- a/content/de/home.mdx +++ b/content/de/home.mdx @@ -179,25 +179,3 @@ description: Willkommen bei E-TIB GmbH ]} /> - diff --git a/content/de/ueber-uns.mdx b/content/de/ueber-uns.mdx index 85f0138b4..c420851c4 100644 --- a/content/de/ueber-uns.mdx +++ b/content/de/ueber-uns.mdx @@ -1,5 +1,5 @@ --- -title: "Über E-TIB" +title: "Über uns" date: "2024-03-20" excerpt: "Die E-TIB Gruppe ist Ihr kompetenter Partner für Kabeltiefbau, Bohrtechnik und Ingenieurdienstleistungen." layout: "fullBleed"