chore: optimize reference gallery, add typography plugin, fix SEO and map animations
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 37s
Build & Deploy / 🧪 QA (push) Failing after 1m31s
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 4s
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 37s
Build & Deploy / 🧪 QA (push) Failing after 1m31s
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 4s
This commit is contained in:
@@ -203,6 +203,7 @@ jobs:
|
||||
build-args: |
|
||||
NEXT_PUBLIC_BASE_URL=${{ needs.prepare.outputs.next_public_url }}
|
||||
NEXT_PUBLIC_TARGET=${{ needs.prepare.outputs.target }}
|
||||
NEXT_PUBLIC_APP_VERSION=${{ needs.prepare.outputs.image_tag }}
|
||||
UMAMI_WEBSITE_ID=${{ secrets.UMAMI_WEBSITE_ID || vars.UMAMI_WEBSITE_ID }}
|
||||
UMAMI_API_ENDPOINT=${{ secrets.UMAMI_API_ENDPOINT || vars.UMAMI_API_ENDPOINT || 'https://analytics.infra.mintel.me' }}
|
||||
NPM_TOKEN=${{ steps.auth.outputs.working_token }}
|
||||
|
||||
@@ -146,44 +146,42 @@ export default async function Page(props: { params: Promise<{ locale: string; sl
|
||||
|
||||
{/* Main Content Area */}
|
||||
<Container className="py-16 md:py-24">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
{/* Excerpt/Lead paragraph if available */}
|
||||
{pageData.frontmatter.excerpt && (
|
||||
<div className="mb-16">
|
||||
<p className="text-xl md:text-2xl text-text-primary leading-relaxed font-medium border-l-4 border-primary pl-8 py-2 italic">
|
||||
{pageData.frontmatter.excerpt}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Main content */}
|
||||
<div className="prose prose-lg md:prose-xl max-w-none prose-headings:font-bold prose-headings:text-text-primary prose-p:text-text-secondary prose-p:leading-relaxed prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-img:rounded-2xl prose-img:shadow-2xl prose-blockquote:border-primary prose-blockquote:bg-primary/5 prose-blockquote:rounded-r-2xl prose-strong:text-primary">
|
||||
<MDXRemote source={pageData.content} components={mdxComponents} />
|
||||
{/* Excerpt/Lead paragraph if available */}
|
||||
{pageData.frontmatter.excerpt && (
|
||||
<div className="mb-16">
|
||||
<p className="text-xl md:text-2xl text-text-primary leading-relaxed font-medium border-l-4 border-primary pl-8 py-2 italic">
|
||||
{pageData.frontmatter.excerpt}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Support Section */}
|
||||
<div className="mt-24 p-8 md:p-12 bg-primary-dark rounded-3xl text-white shadow-2xl relative overflow-hidden group animate-slight-fade-in-from-bottom">
|
||||
<div className="absolute top-0 right-0 w-64 h-full bg-accent/5 -skew-x-12 translate-x-1/2 transition-transform group-hover:translate-x-1/3" />
|
||||
<div className="relative z-10 max-w-2xl">
|
||||
<h3 className="text-2xl md:text-3xl font-bold mb-4">{t('needHelp')}</h3>
|
||||
<p className="text-lg text-white/70 mb-8">{t('supportTeamAvailable')}</p>
|
||||
<TrackedLink
|
||||
href={`/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}`}
|
||||
className={getButtonClasses('accent', 'lg')}
|
||||
eventProperties={{
|
||||
location: 'generic_page_support_cta',
|
||||
page_slug: slug,
|
||||
}}
|
||||
>
|
||||
<span className="relative z-10 flex items-center justify-center gap-2 transition-colors duration-500 group-hover/btn:text-primary-dark">
|
||||
{t('contactUs')}
|
||||
<span className="ml-2 transition-transform group-hover/btn:translate-x-1">
|
||||
→
|
||||
</span>
|
||||
{/* Main content */}
|
||||
<div className="prose prose-lg md:prose-xl max-w-none prose-headings:font-bold prose-headings:text-text-primary prose-p:text-text-secondary prose-p:leading-relaxed prose-a:text-primary prose-a:no-underline hover:prose-a:underline prose-img:rounded-2xl prose-img:shadow-2xl prose-blockquote:border-primary prose-blockquote:bg-primary/5 prose-blockquote:rounded-r-2xl prose-strong:text-primary">
|
||||
<MDXRemote source={pageData.content} components={mdxComponents} />
|
||||
</div>
|
||||
|
||||
{/* Support Section */}
|
||||
<div className="mt-24 p-8 md:p-12 bg-primary-dark rounded-3xl text-white shadow-2xl relative overflow-hidden group animate-slight-fade-in-from-bottom">
|
||||
<div className="absolute top-0 right-0 w-64 h-full bg-accent/5 -skew-x-12 translate-x-1/2 transition-transform group-hover:translate-x-1/3" />
|
||||
<div className="relative z-10 max-w-2xl">
|
||||
<h3 className="text-2xl md:text-3xl font-bold mb-4">{t('needHelp')}</h3>
|
||||
<p className="text-lg text-white/70 mb-8">{t('supportTeamAvailable')}</p>
|
||||
<TrackedLink
|
||||
href={`/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}`}
|
||||
className={getButtonClasses('accent', 'lg')}
|
||||
eventProperties={{
|
||||
location: 'generic_page_support_cta',
|
||||
page_slug: slug,
|
||||
}}
|
||||
>
|
||||
<span className="relative z-10 flex items-center justify-center gap-2 transition-colors duration-500 group-hover/btn:text-primary-dark">
|
||||
{t('contactUs')}
|
||||
<span className="ml-2 transition-transform group-hover/btn:translate-x-1">
|
||||
→
|
||||
</span>
|
||||
<ButtonOverlay variant="accent" />
|
||||
</TrackedLink>
|
||||
</div>
|
||||
</span>
|
||||
<ButtonOverlay variant="accent" />
|
||||
</TrackedLink>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
|
||||
@@ -91,6 +91,10 @@ export default async function Layout(props: {
|
||||
label: safeLocale === 'de' ? 'Über uns' : 'About Us',
|
||||
url: `/${safeLocale}/${await mapFileSlugToTranslated('ueber-uns', safeLocale)}`
|
||||
},
|
||||
{
|
||||
label: safeLocale === 'de' ? 'Referenzen' : 'References',
|
||||
url: `/${safeLocale}/referenzen`
|
||||
},
|
||||
{
|
||||
label: safeLocale === 'de' ? 'Karriere' : 'Careers',
|
||||
url: `/${safeLocale}/${await mapFileSlugToTranslated('karriere', safeLocale)}`
|
||||
@@ -103,7 +107,7 @@ export default async function Layout(props: {
|
||||
|
||||
const companyInfo = {
|
||||
contactEmail: 'info@e-tib.com',
|
||||
contactPhone: '+49 15207230518',
|
||||
contactPhone: '+49 (0) 3561 / 68577 33',
|
||||
address: 'Gewerbestraße 22\n03172 Guben'
|
||||
};
|
||||
|
||||
|
||||
166
app/[locale]/referenzen/[slug]/page.tsx
Normal file
166
app/[locale]/referenzen/[slug]/page.tsx
Normal file
@@ -0,0 +1,166 @@
|
||||
import { notFound } from 'next/navigation';
|
||||
import { Container, Badge, Heading } from '@/components/ui';
|
||||
import { setRequestLocale } from 'next-intl/server';
|
||||
import { Metadata } from 'next';
|
||||
import { getReferenceBySlug, getAllReferences } from '@/lib/references';
|
||||
import { MDXRemote } from 'next-mdx-remote/rsc';
|
||||
import { SITE_URL } from '@/lib/schema';
|
||||
import TrackedLink from '@/components/analytics/TrackedLink';
|
||||
import { getButtonClasses, ButtonOverlay } from '@/components/ui/Button';
|
||||
import { MapPin, Calendar, Briefcase, ChevronLeft } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{
|
||||
locale: string;
|
||||
slug: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
||||
const { locale, slug } = await params;
|
||||
if (locale !== 'de' && locale !== 'en') return {};
|
||||
|
||||
const reference = await getReferenceBySlug(slug, locale);
|
||||
if (!reference) return {};
|
||||
|
||||
return {
|
||||
title: `${reference.frontmatter.title} | Referenzen | E-TIB Gruppe`,
|
||||
description: `Details zum Projekt ${reference.frontmatter.title} in ${reference.frontmatter.location}.`,
|
||||
alternates: {
|
||||
canonical: `${SITE_URL}/${locale}/referenzen/${slug}`,
|
||||
},
|
||||
openGraph: {
|
||||
title: `${reference.frontmatter.title} | E-TIB`,
|
||||
description: `Details zum Projekt ${reference.frontmatter.title} in ${reference.frontmatter.location}.`,
|
||||
url: `${SITE_URL}/${locale}/referenzen/${slug}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export async function generateStaticParams({ params }: { params: { locale: string } }) {
|
||||
const references = await getAllReferences(params.locale);
|
||||
return references.map((ref) => ({
|
||||
slug: ref.slug,
|
||||
}));
|
||||
}
|
||||
|
||||
export default async function ReferenceDetail(props: { params: Promise<{ locale: string; slug: string }> }) {
|
||||
const { locale, slug } = await props.params;
|
||||
|
||||
if (locale !== 'de' && locale !== 'en') {
|
||||
notFound();
|
||||
}
|
||||
|
||||
setRequestLocale(locale);
|
||||
const reference = await getReferenceBySlug(slug, locale);
|
||||
|
||||
if (!reference) {
|
||||
notFound();
|
||||
}
|
||||
|
||||
// MDX components mapping can be expanded if we use custom components in reference MDX
|
||||
const mdxComponents = {
|
||||
ul: ({ children }: any) => <ul className="space-y-4 my-8 pl-0 list-none">{children}</ul>,
|
||||
li: ({ children }: any) => (
|
||||
<li className="flex items-start gap-4 p-4 bg-neutral-50 rounded-2xl border border-neutral-100 shadow-sm">
|
||||
<div className="w-6 h-6 rounded-full bg-primary/20 flex items-center justify-center shrink-0 mt-0.5">
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-primary" />
|
||||
</div>
|
||||
<span className="text-lg font-medium text-neutral-800">{children}</span>
|
||||
</li>
|
||||
),
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen bg-white">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-[#050B14] text-white py-20 md:py-32 relative overflow-hidden">
|
||||
{reference.frontmatter.featuredImage && (
|
||||
<div className="absolute inset-0 z-0">
|
||||
<Image
|
||||
src={reference.frontmatter.featuredImage}
|
||||
alt={reference.frontmatter.title}
|
||||
fill
|
||||
className="object-cover opacity-25 mix-blend-luminosity scale-105"
|
||||
priority
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-[#050B14] via-[#050B14]/60 to-transparent" />
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-[#050B14] via-transparent to-transparent" />
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute inset-0 opacity-20 z-0">
|
||||
<div className="absolute top-0 left-0 w-full h-full bg-[radial-gradient(circle_at_center,_var(--tw-gradient-stops))] from-primary/30 via-transparent to-transparent" />
|
||||
</div>
|
||||
<Container className="relative z-10">
|
||||
<div className="mb-12">
|
||||
<TrackedLink
|
||||
href={`/${locale}/referenzen`}
|
||||
className="inline-flex items-center gap-2 text-white/60 hover:text-white transition-colors"
|
||||
eventProperties={{ location: 'reference_back_btn' }}
|
||||
>
|
||||
<ChevronLeft className="w-5 h-5" />
|
||||
Zurück zur Übersicht
|
||||
</TrackedLink>
|
||||
</div>
|
||||
<div className="max-w-4xl">
|
||||
<Badge variant="accent" className="mb-4 md:mb-6">
|
||||
Projektreferenz
|
||||
</Badge>
|
||||
<Heading level={1} variant="white" className="mb-8 leading-tight">
|
||||
{reference.frontmatter.title}
|
||||
</Heading>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6 mt-12">
|
||||
<div className="flex items-start gap-4 p-6 bg-white/5 rounded-2xl border border-white/10 backdrop-blur-sm">
|
||||
<MapPin className="w-8 h-8 text-primary shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm text-white/50 mb-1 uppercase tracking-wider font-bold">Ort</p>
|
||||
<p className="font-semibold text-lg">{reference.frontmatter.location}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-4 p-6 bg-white/5 rounded-2xl border border-white/10 backdrop-blur-sm">
|
||||
<Briefcase className="w-8 h-8 text-primary shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm text-white/50 mb-1 uppercase tracking-wider font-bold">Auftraggeber</p>
|
||||
<p className="font-semibold text-lg">{reference.frontmatter.client}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start gap-4 p-6 bg-white/5 rounded-2xl border border-white/10 backdrop-blur-sm">
|
||||
<Calendar className="w-8 h-8 text-primary shrink-0" />
|
||||
<div>
|
||||
<p className="text-sm text-white/50 mb-1 uppercase tracking-wider font-bold">Zeitraum</p>
|
||||
<p className="font-semibold text-lg">{reference.frontmatter.dateString || new Date(reference.frontmatter.date).getFullYear()}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</section>
|
||||
|
||||
{/* Main Content Area */}
|
||||
<Container className="py-16 md:py-24">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-bold text-neutral-dark mb-8">Leistungsumfang & Projektbeschreibung</h2>
|
||||
|
||||
<div className="prose prose-lg md:prose-xl max-w-none prose-headings:font-bold prose-headings:text-text-primary prose-p:text-text-secondary">
|
||||
<MDXRemote source={reference.content} components={mdxComponents} />
|
||||
</div>
|
||||
|
||||
<div className="mt-20 flex justify-center">
|
||||
<TrackedLink
|
||||
href={`/${locale}/referenzen`}
|
||||
className={getButtonClasses('primary', 'lg')}
|
||||
eventProperties={{ location: 'reference_bottom_back_btn' }}
|
||||
>
|
||||
<span className="relative z-10 flex items-center justify-center gap-2">
|
||||
Alle Referenzen ansehen
|
||||
</span>
|
||||
<ButtonOverlay variant="primary" />
|
||||
</TrackedLink>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
172
app/[locale]/referenzen/page.tsx
Normal file
172
app/[locale]/referenzen/page.tsx
Normal file
@@ -0,0 +1,172 @@
|
||||
import { Container, Heading, Badge } from '@/components/ui';
|
||||
import { getTranslations, setRequestLocale } from 'next-intl/server';
|
||||
import { Metadata } from 'next';
|
||||
import { getAllReferences } from '@/lib/references';
|
||||
import TrackedLink from '@/components/analytics/TrackedLink';
|
||||
import { MapPin, Calendar, Briefcase, ArrowUpRight } from 'lucide-react';
|
||||
import { getButtonClasses, ButtonOverlay } from '@/components/ui/Button';
|
||||
import { SITE_URL } from '@/lib/schema';
|
||||
import Image from 'next/image';
|
||||
import { InteractiveGermanyMap } from '@/components/blocks/InteractiveGermanyMap';
|
||||
import { defaultLocations } from '@/lib/map-data';
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{
|
||||
locale: string;
|
||||
}>;
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params }: PageProps): Promise<Metadata> {
|
||||
const { locale } = await params;
|
||||
if (locale !== 'de' && locale !== 'en') return {};
|
||||
|
||||
return {
|
||||
title: 'Referenzen | E-TIB Gruppe',
|
||||
description: 'Erfolgreich abgeschlossene Projekte der E-TIB Gruppe im Bereich Kabeltiefbau, Spülbohrtechnik und Netzinfrastruktur.',
|
||||
alternates: {
|
||||
canonical: `${SITE_URL}/${locale}/referenzen`,
|
||||
languages: {
|
||||
de: `${SITE_URL}/de/referenzen`,
|
||||
en: `${SITE_URL}/en/referenzen`,
|
||||
'x-default': `${SITE_URL}/en/referenzen`,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default async function ReferenzenOverview(props: { params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await props.params;
|
||||
setRequestLocale(locale);
|
||||
const t = await getTranslations('StandardPage');
|
||||
|
||||
const references = await getAllReferences(locale);
|
||||
|
||||
// Enrich the static map locations with dynamic project data (images, details)
|
||||
const enrichedLocations = defaultLocations.map(loc => {
|
||||
if (loc.type === 'project') {
|
||||
const ref = references.find(r => r.slug === loc.id);
|
||||
if (ref) {
|
||||
return {
|
||||
...loc,
|
||||
featuredImage: ref.frontmatter.featuredImage,
|
||||
details: [
|
||||
ref.frontmatter.client || 'Kunde',
|
||||
ref.frontmatter.dateString || new Date(ref.frontmatter.date).getFullYear().toString(),
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
return loc;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="flex flex-col min-h-screen bg-neutral-50 pb-16 md:pb-24">
|
||||
{/* Map Hero Section */}
|
||||
<InteractiveGermanyMap
|
||||
isHero={true}
|
||||
badge="Unsere Referenzen"
|
||||
title={<>Erfolgreich umgesetzte<br/>Projekte.</>}
|
||||
description="Vom Breitbandausbau bis zur komplexen 110kV-Trasse: Ein Auszug unserer bundesweiten Projekte, bei denen wir Infrastruktur für die Zukunft geschaffen haben. Entdecken Sie unsere Standorte."
|
||||
locations={enrichedLocations}
|
||||
/>
|
||||
|
||||
{/* Main Content Area */}
|
||||
<Container className="relative z-20 mt-16 md:mt-24">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 md:gap-8">
|
||||
{references.map((ref) => (
|
||||
<TrackedLink
|
||||
key={ref.slug}
|
||||
href={`/${locale}/referenzen/${ref.slug}`}
|
||||
className="group flex flex-col bg-white border border-neutral-100 rounded-3xl overflow-hidden shadow-sm hover:shadow-2xl transition-all duration-300 transform hover:-translate-y-2"
|
||||
eventProperties={{
|
||||
location: 'referenzen_grid',
|
||||
target_slug: ref.slug,
|
||||
}}
|
||||
>
|
||||
<div className="flex flex-col h-full relative">
|
||||
{/* Image Section */}
|
||||
<div className="relative h-64 w-full bg-[#f4f4f5] overflow-hidden shrink-0 border-b border-neutral-100">
|
||||
{ref.frontmatter.featuredImage ? (
|
||||
<Image
|
||||
src={ref.frontmatter.featuredImage}
|
||||
alt={ref.frontmatter.title}
|
||||
fill
|
||||
className="object-cover group-hover:scale-105 transition-transform duration-1000 ease-[cubic-bezier(0.16,1,0.3,1)] filter grayscale-[20%] group-hover:grayscale-0"
|
||||
/>
|
||||
) : (
|
||||
<div className="absolute inset-0 bg-[#f4f4f5] flex items-center justify-center">
|
||||
<Image src="/assets/logo.png" alt="E-TIB Logo" width={80} height={80} className="opacity-20 grayscale" />
|
||||
</div>
|
||||
)}
|
||||
<div className="absolute inset-0 bg-black/5 group-hover:bg-transparent transition-colors duration-500" />
|
||||
|
||||
{/* Location Badge */}
|
||||
<div className="absolute top-4 left-4 z-10">
|
||||
<span className="bg-white/95 backdrop-blur-md text-neutral-dark px-3 py-1.5 rounded-sm text-[10px] font-bold uppercase tracking-widest flex items-center gap-1.5 shadow-sm border border-neutral-200">
|
||||
<MapPin className="w-3 h-3 text-primary" />
|
||||
{ref.frontmatter.location}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Content Section */}
|
||||
<div className="flex flex-col flex-grow p-6 md:p-8 bg-white">
|
||||
<h3 className="text-xl md:text-2xl font-bold font-heading text-neutral-dark mb-6 group-hover:text-primary transition-colors line-clamp-3 leading-[1.2]">
|
||||
{ref.frontmatter.title}
|
||||
</h3>
|
||||
|
||||
{/* Technical Meta Data */}
|
||||
<div className="grid grid-cols-[1fr_1fr] gap-4 mt-auto border-t border-neutral-100 pt-6 pr-16 md:pr-20 relative z-10">
|
||||
<div className="min-w-0">
|
||||
<span className="block text-[10px] uppercase tracking-widest text-neutral-400 font-bold mb-1">Kunde</span>
|
||||
<span className="flex items-center gap-1.5 text-sm font-semibold text-neutral-700">
|
||||
<Briefcase className="w-3.5 h-3.5 text-primary shrink-0" />
|
||||
<span className="truncate">{ref.frontmatter.client}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<span className="block text-[10px] uppercase tracking-widest text-neutral-400 font-bold mb-1">Zeitraum</span>
|
||||
<span className="flex items-center gap-1.5 text-sm font-semibold text-neutral-700">
|
||||
<Calendar className="w-3.5 h-3.5 text-primary shrink-0" />
|
||||
<span className="truncate">{ref.frontmatter.dateString || new Date(ref.frontmatter.date).getFullYear()}</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Industrial Hover Indicator */}
|
||||
<div className="absolute right-6 bottom-6 md:right-8 md:bottom-8 w-10 h-10 bg-neutral-50 border border-neutral-200 rounded flex items-center justify-center transform group-hover:bg-primary group-hover:border-primary transition-colors duration-300">
|
||||
<ArrowUpRight className="w-5 h-5 text-neutral-dark group-hover:text-white transform group-hover:translate-x-0.5 group-hover:-translate-y-0.5 transition-transform duration-300" />
|
||||
</div>
|
||||
</div>
|
||||
</TrackedLink>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Support Section */}
|
||||
<div className="mt-24 p-8 md:p-12 bg-primary-dark rounded-3xl text-white shadow-2xl relative overflow-hidden group">
|
||||
<div className="absolute top-0 right-0 w-64 h-full bg-accent/5 -skew-x-12 translate-x-1/2 transition-transform group-hover:translate-x-1/3" />
|
||||
<div className="relative z-10 max-w-2xl">
|
||||
<h3 className="text-2xl md:text-3xl font-bold mb-4">Ihr nächstes Projekt?</h3>
|
||||
<p className="text-lg text-white/70 mb-8">Lassen Sie uns gemeinsam herausragende Infrastruktur bauen.</p>
|
||||
<TrackedLink
|
||||
href={`/${locale}/${locale === 'de' ? 'kontakt' : 'contact'}`}
|
||||
className={getButtonClasses('accent', 'lg')}
|
||||
eventProperties={{
|
||||
location: 'referenzen_support_cta',
|
||||
}}
|
||||
>
|
||||
<span className="relative z-10 flex items-center justify-center gap-2 transition-colors duration-500 group-hover/btn:text-primary-dark">
|
||||
{t('contactUs')}
|
||||
<span className="ml-2 transition-transform group-hover/btn:translate-x-1">
|
||||
→
|
||||
</span>
|
||||
</span>
|
||||
<ButtonOverlay variant="accent" />
|
||||
</TrackedLink>
|
||||
</div>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
@import "tailwindcss";
|
||||
@plugin "@tailwindcss/typography";
|
||||
|
||||
@config "../tailwind.config.cjs";
|
||||
|
||||
|
||||
@@ -36,8 +36,8 @@ export const ContactSection: React.FC<ContactSectionProps> = (props) => {
|
||||
</div>
|
||||
<div>
|
||||
<h4 className="font-bold text-neutral-dark">Telefon</h4>
|
||||
<p className="text-primary hover:text-primary-dark font-medium transition-colors">
|
||||
<a href="tel:+4935616892550">+49 3561 6892 550</a>
|
||||
<p className="text-xl md:text-2xl font-bold font-heading text-neutral-dark hover:text-primary transition-colors">
|
||||
<a href="tel:+4935616857733">+49 (0) 3561 / 68577 33</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,77 +4,8 @@ import React, { useState } from 'react';
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { MapPin, Factory, Zap, CheckCircle2 } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
|
||||
export interface Location {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'hq' | 'branch' | 'project';
|
||||
x: number;
|
||||
y: number;
|
||||
description: string;
|
||||
details?: string[];
|
||||
}
|
||||
|
||||
const defaultLocations: Location[] = [
|
||||
{
|
||||
id: 'guben',
|
||||
name: 'Guben (Hauptsitz)',
|
||||
type: 'hq',
|
||||
x: 85,
|
||||
y: 48,
|
||||
description: 'E-TIB GmbH Holding & Bohrtechnik GmbH',
|
||||
details: ['Zentrale Steuerung', 'Kabelleitungstiefbau', 'Maschinenpark'],
|
||||
},
|
||||
{
|
||||
id: 'buelstedt',
|
||||
name: 'Bülstedt (Ingenieurgesellschaft)',
|
||||
type: 'branch',
|
||||
x: 37,
|
||||
y: 25,
|
||||
description: 'E-TIB Ingenieurgesellschaft mbH',
|
||||
details: ['Planung & Projektierung', 'Vermessung', 'Dokumentation'],
|
||||
},
|
||||
{
|
||||
id: 'spreewald',
|
||||
name: 'Spreewald (Projekt)',
|
||||
type: 'project',
|
||||
x: 82,
|
||||
y: 45,
|
||||
description: 'Breitbandausbau FTTC',
|
||||
},
|
||||
{
|
||||
id: 'bomlitz',
|
||||
name: 'Bomlitz (Projekt)',
|
||||
type: 'project',
|
||||
x: 45,
|
||||
y: 30,
|
||||
description: 'Breitbandausbau FTTH',
|
||||
},
|
||||
{
|
||||
id: 'forst',
|
||||
name: 'Forst (Projekt)',
|
||||
type: 'project',
|
||||
x: 88,
|
||||
y: 50,
|
||||
description: 'Neubau Kabeltrasse',
|
||||
},
|
||||
{
|
||||
id: 'eisenhuettenstadt',
|
||||
name: 'Eisenhüttenstadt (Projekt)',
|
||||
type: 'project',
|
||||
x: 85,
|
||||
y: 40,
|
||||
description: 'Kabelverbindung U30 - T10',
|
||||
},
|
||||
{
|
||||
id: 'goerne',
|
||||
name: 'Görne (Projekt)',
|
||||
type: 'project',
|
||||
x: 70,
|
||||
y: 35,
|
||||
description: 'Einspeisung PV-Anlage',
|
||||
}
|
||||
];
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { Location } from '@/lib/map-data';
|
||||
|
||||
interface Stat {
|
||||
value: string;
|
||||
@@ -88,6 +19,7 @@ interface InteractiveGermanyMapProps {
|
||||
description?: string;
|
||||
stats?: Stat[];
|
||||
locations?: Location[];
|
||||
isHero?: boolean;
|
||||
}
|
||||
|
||||
export function InteractiveGermanyMap({
|
||||
@@ -98,22 +30,24 @@ export function InteractiveGermanyMap({
|
||||
{ value: '100', suffix: '%', label: 'Überregionale Reichweite' },
|
||||
{ value: '2', suffix: '+', label: 'Operative Standorte' },
|
||||
],
|
||||
locations = defaultLocations
|
||||
locations = defaultLocations,
|
||||
isHero = false
|
||||
}: InteractiveGermanyMapProps) {
|
||||
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
|
||||
const router = useRouter();
|
||||
|
||||
const hq = locations.find((l) => l.type === 'hq');
|
||||
const branch = locations.find((l) => l.type === 'branch');
|
||||
const projects = locations.filter((l) => l.type === 'project');
|
||||
|
||||
return (
|
||||
<div className="relative w-full max-w-7xl mx-auto py-16 md:py-32 px-4 sm:px-6">
|
||||
<div className="bg-[#050B14] rounded-[2.5rem] md:rounded-[3.5rem] overflow-hidden relative shadow-2xl border border-white/5">
|
||||
<div className={isHero ? "relative w-full" : "relative w-full max-w-7xl mx-auto py-16 md:py-24 px-4 sm:px-6 mt-16 md:mt-20"}>
|
||||
<div className={`bg-[#050B14] ${isHero ? 'pt-32 pb-16 md:pt-40 md:pb-24' : 'rounded-[2.5rem] md:rounded-[3.5rem] shadow-2xl border border-white/5'} overflow-visible relative`}>
|
||||
{/* Background Effects */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322] to-[#050B14]" />
|
||||
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-primary/5 rounded-full blur-[120px] pointer-events-none translate-x-1/3 -translate-y-1/3" />
|
||||
<div className={`absolute inset-0 bg-gradient-to-br from-[#050B14] via-[#0A1322] to-[#050B14] ${!isHero && 'rounded-[2.5rem] md:rounded-[3.5rem]'} overflow-hidden`} />
|
||||
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-primary/5 rounded-full blur-[120px] pointer-events-none translate-x-1/3 -translate-y-1/3 overflow-hidden" />
|
||||
|
||||
<div className="relative z-10 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-12 gap-12 items-center min-h-[600px] p-8 md:p-12 lg:p-16">
|
||||
<div className={`relative z-10 grid grid-cols-1 lg:grid-cols-2 xl:grid-cols-12 gap-12 items-center min-h-[600px] ${isHero ? 'max-w-7xl mx-auto px-4 sm:px-6' : 'p-8 md:p-12 lg:p-16'}`}>
|
||||
|
||||
{/* Content Left */}
|
||||
<div className="xl:col-span-5 text-white z-20">
|
||||
@@ -122,9 +56,15 @@ export function InteractiveGermanyMap({
|
||||
<span>{badge}</span>
|
||||
</div>
|
||||
|
||||
<h3 className="font-heading text-4xl lg:text-5xl xl:text-6xl font-extrabold mb-6 leading-[1.1] text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70 break-words [hyphens:auto]">
|
||||
{title}
|
||||
</h3>
|
||||
{isHero ? (
|
||||
<h1 className="font-heading text-4xl lg:text-5xl xl:text-6xl font-extrabold mb-6 leading-[1.1] text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70 break-words [hyphens:auto]">
|
||||
{title}
|
||||
</h1>
|
||||
) : (
|
||||
<h3 className="font-heading text-4xl lg:text-5xl xl:text-6xl font-extrabold mb-6 leading-[1.1] text-transparent bg-clip-text bg-gradient-to-r from-white to-white/70 break-words [hyphens:auto]">
|
||||
{title}
|
||||
</h3>
|
||||
)}
|
||||
|
||||
<p className="text-white/60 text-lg mb-12 leading-relaxed">
|
||||
{description}
|
||||
@@ -199,13 +139,32 @@ export function InteractiveGermanyMap({
|
||||
const isBranch = loc.type === 'branch';
|
||||
const isActive = activeLocation?.id === loc.id;
|
||||
|
||||
const isNearLeft = loc.x < 50;
|
||||
const isNearRight = loc.x >= 50;
|
||||
const isNearTop = loc.y < 55; // 55% threshold to strongly avoid the top header
|
||||
|
||||
const tooltipClasses = [
|
||||
'absolute w-[280px] sm:w-64 bg-white text-neutral-dark p-5 rounded-2xl shadow-2xl z-[9999] pointer-events-none border border-neutral-100',
|
||||
isNearLeft ? 'left-1/2 sm:left-0 -translate-x-1/2 sm:translate-x-0' : 'left-1/2 sm:left-auto sm:right-0 -translate-x-1/2 sm:translate-x-0',
|
||||
isNearTop ? 'top-full mt-4' : 'bottom-full mb-4'
|
||||
].join(' ');
|
||||
|
||||
const arrowClasses = [
|
||||
'absolute border-8 border-transparent drop-shadow-sm hidden sm:block',
|
||||
isNearLeft ? 'left-6' : 'right-6',
|
||||
isNearTop ? '-top-4 border-b-white border-t-0' : '-bottom-4 border-t-white border-b-0'
|
||||
].join(' ');
|
||||
|
||||
return (
|
||||
<div
|
||||
key={loc.id}
|
||||
className="absolute transform -translate-x-1/2 -translate-y-1/2 z-20 group cursor-pointer w-16 h-16 flex items-center justify-center"
|
||||
className={`absolute transform -translate-x-1/2 -translate-y-1/2 group cursor-pointer w-16 h-16 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-20'}`}
|
||||
style={{ left: `${loc.x}%`, top: `${loc.y}%` }}
|
||||
onMouseEnter={() => setActiveLocation(loc)}
|
||||
onMouseLeave={() => setActiveLocation(null)}
|
||||
onClick={() => {
|
||||
if (loc.href) router.push(loc.href);
|
||||
}}
|
||||
>
|
||||
{/* Ping Animation for HQ / Branch */}
|
||||
{(isHQ || isBranch) && (
|
||||
@@ -222,7 +181,7 @@ export function InteractiveGermanyMap({
|
||||
} ${
|
||||
isHQ || isBranch
|
||||
? 'w-6 h-6 bg-primary text-[#050B14]'
|
||||
: 'w-3 h-3 bg-white/90 ring-2 ring-primary'
|
||||
: 'w-4 h-4 bg-white ring-[3px] ring-primary'
|
||||
}`}
|
||||
>
|
||||
{(isHQ || isBranch) && <MapPin className="w-3.5 h-3.5" />}
|
||||
@@ -232,33 +191,92 @@ export function InteractiveGermanyMap({
|
||||
<AnimatePresence>
|
||||
{isActive && (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10, scale: 0.95 }}
|
||||
animate={{ opacity: 1, y: 0, scale: 1 }}
|
||||
exit={{ opacity: 0, y: 10, scale: 0.95 }}
|
||||
transition={{ duration: 0.15 }}
|
||||
className="absolute left-1/2 -translate-x-1/2 bottom-full mb-3 w-56 bg-white text-neutral-dark p-5 rounded-2xl shadow-2xl z-50 pointer-events-none border border-neutral-100"
|
||||
variants={{
|
||||
hidden: { opacity: 0, y: isNearTop ? -15 : 15, scale: 0.9 },
|
||||
visible: {
|
||||
opacity: 1, y: 0, scale: 1,
|
||||
transition: {
|
||||
type: "spring", stiffness: 350, damping: 25,
|
||||
staggerChildren: 0.05, delayChildren: 0.05
|
||||
}
|
||||
},
|
||||
exit: {
|
||||
opacity: 0, y: isNearTop ? -10 : 10, scale: 0.95,
|
||||
transition: { duration: 0.15, ease: "easeIn" }
|
||||
}
|
||||
}}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
className={`${tooltipClasses} overflow-hidden p-0`}
|
||||
>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
{isHQ ? <Factory className="w-4 h-4 text-primary" /> : <Zap className="w-4 h-4 text-primary" />}
|
||||
<span className="font-extrabold text-sm leading-tight text-neutral-dark">{loc.name}</span>
|
||||
</div>
|
||||
<p className="text-xs text-neutral-500 mt-2 font-medium">{loc.description}</p>
|
||||
{loc.featuredImage && (
|
||||
<motion.div
|
||||
variants={{ hidden: { opacity: 0 }, visible: { opacity: 1 } }}
|
||||
className="relative w-full h-32 bg-neutral-100 overflow-hidden"
|
||||
>
|
||||
<Image
|
||||
src={loc.featuredImage}
|
||||
alt={loc.name}
|
||||
fill
|
||||
className="object-cover transform transition-transform duration-1000 ease-[cubic-bezier(0.16,1,0.3,1)] group-hover:scale-110"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-80" />
|
||||
<div className="absolute bottom-3 left-4 flex items-center gap-2">
|
||||
{isHQ ? <Factory className="w-4 h-4 text-primary drop-shadow" /> : <Zap className="w-4 h-4 text-primary drop-shadow" />}
|
||||
<span className="font-extrabold text-sm leading-tight text-white drop-shadow-md">{loc.name}</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
<div className={loc.featuredImage ? "p-5 pt-4" : "p-5"}>
|
||||
{!loc.featuredImage && (
|
||||
<motion.div
|
||||
variants={{ hidden: { opacity: 0, x: -5 }, visible: { opacity: 1, x: 0 } }}
|
||||
className="flex items-center gap-2 mb-2"
|
||||
>
|
||||
{isHQ ? <Factory className="w-4 h-4 text-primary" /> : <Zap className="w-4 h-4 text-primary" />}
|
||||
<span className="font-extrabold text-sm leading-tight text-neutral-dark">{loc.name}</span>
|
||||
</motion.div>
|
||||
)}
|
||||
|
||||
<motion.p
|
||||
variants={{ hidden: { opacity: 0, y: 5 }, visible: { opacity: 1, y: 0 } }}
|
||||
className="text-xs text-neutral-500 font-medium"
|
||||
>
|
||||
{loc.description}
|
||||
</motion.p>
|
||||
|
||||
{loc.details && (
|
||||
<ul className="mt-4 space-y-2">
|
||||
{loc.details.map((detail, i) => (
|
||||
<li key={i} className="text-[11px] text-neutral-dark flex items-center gap-2 font-semibold">
|
||||
<motion.li
|
||||
key={i}
|
||||
variants={{ hidden: { opacity: 0, x: -5 }, visible: { opacity: 1, x: 0 } }}
|
||||
className="text-[11px] text-neutral-dark flex items-center gap-2 font-semibold"
|
||||
>
|
||||
<div className="w-4 h-4 rounded-full bg-primary/10 flex items-center justify-center shrink-0">
|
||||
<CheckCircle2 className="w-3 h-3 text-primary" />
|
||||
</div>
|
||||
{detail}
|
||||
</li>
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{/* Arrow Down */}
|
||||
<div className="absolute left-1/2 -bottom-2 -translate-x-1/2 border-8 border-transparent border-t-white drop-shadow-sm" />
|
||||
{loc.href && (
|
||||
<motion.div
|
||||
variants={{ hidden: { opacity: 0, y: 5 }, visible: { opacity: 1, y: 0 } }}
|
||||
className="mt-4 pt-3 border-t border-neutral-100 text-xs font-bold text-primary flex items-center gap-1 group/link"
|
||||
>
|
||||
Zum Projekt
|
||||
<span className="text-base leading-none translate-y-[1px] transform transition-transform duration-300 group-hover:translate-x-1.5">→</span>
|
||||
</motion.div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Arrow Down/Up */}
|
||||
<div className={arrowClasses} />
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
||||
@@ -122,13 +122,9 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{/* Built Info inside Legal box for compact layout */}
|
||||
<div className="mt-8 pt-4 md:mt-12 md:pt-6 border-t border-white/5 text-white/30 text-xs">
|
||||
<a href="https://mintel.me" target="_blank" rel="noopener noreferrer" className="hover:text-white/60 transition-colors flex items-center gap-2">
|
||||
<span>Designed & Engineered by Mintel</span>
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M7 17l9.2-9.2M17 17V7H7"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
{/* Built Info */}
|
||||
|
||||
{/* Legal Info removed from here */}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -136,7 +132,31 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
|
||||
<div className="container relative z-10">
|
||||
<div className="flex flex-col md:flex-row justify-between items-center gap-4 md:gap-6 py-4 px-5 md:py-6 md:px-8 rounded-2xl bg-white/[0.02] border border-white/5 backdrop-blur-md text-center md:text-left">
|
||||
<p className="text-white/50 text-sm font-medium">© {new Date().getFullYear()} E-TIB GmbH. {locale === 'de' ? 'Alle Rechte vorbehalten.' : 'All rights reserved.'}</p>
|
||||
<div className="flex flex-col md:flex-row items-center gap-4 md:gap-6 h-full">
|
||||
<p className="text-white/50 text-xs font-medium m-0">© {new Date().getFullYear()} E-TIB GmbH. {locale === 'de' ? 'Alle Rechte vorbehalten.' : 'All rights reserved.'}</p>
|
||||
|
||||
<div className="hidden md:block w-px h-3 bg-white/10" />
|
||||
|
||||
<div className="flex items-center gap-3 text-white/30 text-xs">
|
||||
<a href="https://mintel.me" target="_blank" rel="noopener noreferrer" className="hover:text-white/60 transition-colors flex items-center gap-2">
|
||||
<span>Designed & Engineered by Mintel</span>
|
||||
</a>
|
||||
{process.env.NEXT_PUBLIC_APP_VERSION && (
|
||||
<>
|
||||
<span className="w-1 h-1 rounded-full bg-white/20" />
|
||||
<div className="flex items-center gap-2 opacity-60">
|
||||
<span className="font-mono text-[10px]">v{process.env.NEXT_PUBLIC_APP_VERSION.replace(/^v/, '')}</span>
|
||||
{process.env.NEXT_PUBLIC_TARGET && process.env.NEXT_PUBLIC_TARGET !== 'production' && (
|
||||
<span className="px-1.5 py-0.5 rounded-sm bg-white/10 text-[9px] uppercase tracking-wider">
|
||||
{process.env.NEXT_PUBLIC_TARGET}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-6">
|
||||
<LanguageSwitcher isSolidMode={false} />
|
||||
</div>
|
||||
|
||||
@@ -30,8 +30,9 @@ E-TIB GmbH
|
||||
Gewerbestraße 22
|
||||
03172 Guben
|
||||
|
||||
Telefon: +49 1520 7230518
|
||||
E-Mail: d.joseph@e-tib.com
|
||||
Telefon: +49 (0) 3561 / 68577 33
|
||||
Telefax: +49 (0) 3561 / 68577 35
|
||||
E-Mail: info@e-tib.com
|
||||
|
||||
## 4. Datenerfassung auf dieser Website
|
||||
|
||||
|
||||
@@ -17,8 +17,9 @@ Danny Joseph
|
||||
|
||||
## Kontakt
|
||||
|
||||
Telefon: +49 1520 7230518
|
||||
E-Mail: d.joseph@e-tib.com
|
||||
Telefon: +49 (0) 3561 / 68577 33
|
||||
Telefax: +49 (0) 3561 / 68577 35
|
||||
E-Mail: info@e-tib.com
|
||||
|
||||
## Registereintrag
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ layout: "fullBleed"
|
||||
---
|
||||
|
||||
<HomeHero
|
||||
badge="Events"
|
||||
title="Treffen Sie uns\nvor Ort"
|
||||
description="Kommen Sie mit unseren Experten ins Gespräch. Wir sind auf den wichtigsten Branchenmessen vertreten und freuen uns auf den persönlichen Austausch mit Ihnen."
|
||||
videoUrl="/assets/videos/web/hero-messe.mp4"
|
||||
linkText="Zu den Terminen"
|
||||
linkHref="#termine"
|
||||
badge="Messen & Events"
|
||||
title="Treffen Sie uns persönlich"
|
||||
description="Lernen Sie die E-TIB Gruppe auf den führenden Branchenmessen kennen."
|
||||
videoUrl="/assets/videos/web/hero-bahnkreuzung.mp4"
|
||||
linkText="Kontakt aufnehmen"
|
||||
linkHref="/de/kontakt"
|
||||
/>
|
||||
|
||||
<div id="termine">
|
||||
|
||||
12
content/de/referenzen/boerde.mdx
Normal file
12
content/de/referenzen/boerde.mdx
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "Breitbandausbau FTTH, Landkreis Börde"
|
||||
client: "EKN Breitband GmbH & Co. KG"
|
||||
date: "2026-01-01"
|
||||
dateString: "seit 05/2019"
|
||||
location: "Landkreis Börde"
|
||||
featuredImage: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-294.jpg"
|
||||
---
|
||||
|
||||
- 109.000 m Leitungstrasse herstellen (Tiefbau/HDD)
|
||||
- 63 Stück Aufstellung Netzverteiler
|
||||
- 747 Stück Herstellung Hausanschlüsse
|
||||
13
content/de/referenzen/bomlitz.mdx
Normal file
13
content/de/referenzen/bomlitz.mdx
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: "Breitbandausbau FTTH, Planungsregion Bomlitz"
|
||||
client: "Telekom Deutschland GmbH"
|
||||
date: "2018-12-31"
|
||||
dateString: "04/2018 bis 12/2018"
|
||||
location: "Bomlitz"
|
||||
featuredImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-100.jpg"
|
||||
---
|
||||
|
||||
- 88.890 m Leitungstrasse herstellen (Tiefbau/HDD)
|
||||
- 23 Stück Aufstellung Multifunktionsgehäuse
|
||||
- 52 Stück Aufstellung Netzverteiler
|
||||
- 571 Stück Herstellung Hausanschlüsse
|
||||
19
content/de/referenzen/eisenhuettenstadt.mdx
Normal file
19
content/de/referenzen/eisenhuettenstadt.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Kabelverbindung U30 - T10, 15890 Eisenhüttenstadt"
|
||||
client: "ArcelorMittal Eisenhüttenstadt GmbH"
|
||||
date: "2019-12-31"
|
||||
dateString: "07/2019 bis 12/2019"
|
||||
location: "Eisenhüttenstadt"
|
||||
featuredImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie_Vermessung_(24_von_99)_groß2.jpg"
|
||||
---
|
||||
|
||||
- 2.095 m Kabelgraben ausheben und verfüllen
|
||||
- 180 m Horizontalspülbohrung d 160 + d 50
|
||||
- 5.700 m Lieferung und Verlegung MS-Kabel 240 mm², 18/30 kV
|
||||
- 3.000 m Lieferung und Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 3.000 m Lieferung und Einblasen LWL-Kabel, 12 Fasern
|
||||
- 3.000 m Lieferung und Verlegung Steuerkabel, 0,6/1 kV
|
||||
- 16 Satz Lieferung und Montage MS-Verbindungsmuffe 240 mm², 18/30 kV
|
||||
- 1 Stück Lieferung und Montage LWL-Verbindungsmuffe, 12 Fasern
|
||||
- 4 Satz Lieferung und Montage MS-T-Stecker 240 mm², 18/30 kV
|
||||
- Hauptprüfung / Mantelprüfung / OTDR-Messung
|
||||
16
content/de/referenzen/forst.mdx
Normal file
16
content/de/referenzen/forst.mdx
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: "Neubau Kabeltrasse, 03149 Forst"
|
||||
client: "Mitteldeutsche Netzgesellschaft Strom mbH"
|
||||
date: "2020-09-30"
|
||||
dateString: "03/2020 bis 09/2020"
|
||||
location: "Forst"
|
||||
featuredImage: "/assets/photos/DSC02156.jpg"
|
||||
---
|
||||
|
||||
- 2984 m Kabelgraben ausheben und verfüllen
|
||||
- 945 m Horizontalspülbohrung d 160 + d 50
|
||||
- 3.929 m Verlegung MS-Kabel 240 mm², 12/20 kV
|
||||
- 3.929 m Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 11 Satz Montage MS-Verbindungsmuffe 240 mm², 12/20 kV
|
||||
- 1 Satz Montage MS-Endverschluss 240 mm², 12/20 kV
|
||||
- 2.000 m Rückbau Freileitung (inkl. 16 Stück Maste)
|
||||
19
content/de/referenzen/goerne.mdx
Normal file
19
content/de/referenzen/goerne.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Einspeisung PV-Anlage 14728 Görne"
|
||||
client: "EVH GmbH"
|
||||
date: "2020-07-31"
|
||||
dateString: "05/2020 bis 07/2020"
|
||||
location: "Görne"
|
||||
featuredImage: "/assets/photos/DSC08744.JPG"
|
||||
---
|
||||
|
||||
- 4.215 m Kabelgraben ausheben und verfüllen
|
||||
- 1.285 m Horizontalspülbohrung d 140 + d 50
|
||||
- 5.500 m Verlegung MS-Kabel 300 mm², 12/20 kV
|
||||
- 4.500 m Verlegung MS-Kabel 300 mm², 12/20 kV mittels Kabelpflug
|
||||
- 10.000 m Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 10.000 m Einblasen LWL-Kabel, 12 Fasern
|
||||
- 3 Stück Lieferung und Montage LWL-Verbindungsmuffe, 12 Fasern
|
||||
- 16 Satz Montage MS-Verbindungsmuffe 300 mm², 12/20 kV
|
||||
- 4 Satz Montage MS-T-Stecker 300 mm², 12/20 kV
|
||||
- Mantelprüfung, VLF-Prüfung, OTDR-Messung
|
||||
19
content/de/referenzen/spreewald.mdx
Normal file
19
content/de/referenzen/spreewald.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Breitbandausbau FTTC, Planungsregion Spreewald"
|
||||
client: "Telekom Deutschland GmbH"
|
||||
date: "2018-01-31"
|
||||
dateString: "09/2017 bis 01/2018"
|
||||
location: "Spreewald"
|
||||
featuredImage: "/assets/photos/DSC01129.JPG"
|
||||
---
|
||||
|
||||
- 4.006 m Kabelgraben ausheben und verfüllen
|
||||
- 4.006 m Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 13.008 m Horizontalspülbohrung D 50
|
||||
- 94.951 m Einblasen von Kabel/Rohren unbelegt
|
||||
- 42 Stück Stellen von Multifunktionsgehäusen
|
||||
- Aufbau von Energieanschlusssäulen
|
||||
- Aufbau elektrischer Anlagen 230V
|
||||
- Koordination mit Energieversorgungsunternehmen
|
||||
- Inbetriebnahme der elektrischen Anlagen
|
||||
- Oberflächen- und Tiefbauarbeiten für Multifunktionsgehäuse
|
||||
@@ -31,8 +31,9 @@ Gewerbestraße 22
|
||||
03172 Guben
|
||||
Germany
|
||||
|
||||
Phone: +49 1520 7230518
|
||||
Email: d.joseph@e-tib.com
|
||||
Phone: +49 (0) 3561 / 68577 33
|
||||
Fax: +49 (0) 3561 / 68577 35
|
||||
Email: info@e-tib.com
|
||||
|
||||
## 4. Data Collection on this Website
|
||||
|
||||
|
||||
@@ -18,8 +18,9 @@ Danny Joseph
|
||||
|
||||
## Contact
|
||||
|
||||
Phone: +49 1520 7230518
|
||||
Email: d.joseph@e-tib.com
|
||||
Phone: +49 (0) 3561 / 68577 33
|
||||
Fax: +49 (0) 3561 / 68577 35
|
||||
Email: info@e-tib.com
|
||||
|
||||
## Register Entry
|
||||
|
||||
|
||||
12
content/en/referenzen/boerde.mdx
Normal file
12
content/en/referenzen/boerde.mdx
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "Breitbandausbau FTTH, Landkreis Börde"
|
||||
client: "EKN Breitband GmbH & Co. KG"
|
||||
date: "2026-01-01"
|
||||
dateString: "seit 05/2019"
|
||||
location: "Landkreis Börde"
|
||||
featuredImage: "/assets/photos/etib_ingenieure_tiefbau_solar_pv_planung_vermessung_gis-294.jpg"
|
||||
---
|
||||
|
||||
- 109.000 m Leitungstrasse herstellen (Tiefbau/HDD)
|
||||
- 63 Stück Aufstellung Netzverteiler
|
||||
- 747 Stück Herstellung Hausanschlüsse
|
||||
13
content/en/referenzen/bomlitz.mdx
Normal file
13
content/en/referenzen/bomlitz.mdx
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: "Breitbandausbau FTTH, Planungsregion Bomlitz"
|
||||
client: "Telekom Deutschland GmbH"
|
||||
date: "2018-12-31"
|
||||
dateString: "04/2018 bis 12/2018"
|
||||
location: "Bomlitz"
|
||||
featuredImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie-100.jpg"
|
||||
---
|
||||
|
||||
- 88.890 m Leitungstrasse herstellen (Tiefbau/HDD)
|
||||
- 23 Stück Aufstellung Multifunktionsgehäuse
|
||||
- 52 Stück Aufstellung Netzverteiler
|
||||
- 571 Stück Herstellung Hausanschlüsse
|
||||
19
content/en/referenzen/eisenhuettenstadt.mdx
Normal file
19
content/en/referenzen/eisenhuettenstadt.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Kabelverbindung U30 - T10, 15890 Eisenhüttenstadt"
|
||||
client: "ArcelorMittal Eisenhüttenstadt GmbH"
|
||||
date: "2019-12-31"
|
||||
dateString: "07/2019 bis 12/2019"
|
||||
location: "Eisenhüttenstadt"
|
||||
featuredImage: "/assets/photos/Etib_E-tib_Tiefbau_Guben_Netzanbindung_Energie_Vermessung_(24_von_99)_groß2.jpg"
|
||||
---
|
||||
|
||||
- 2.095 m Kabelgraben ausheben und verfüllen
|
||||
- 180 m Horizontalspülbohrung d 160 + d 50
|
||||
- 5.700 m Lieferung und Verlegung MS-Kabel 240 mm², 18/30 kV
|
||||
- 3.000 m Lieferung und Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 3.000 m Lieferung und Einblasen LWL-Kabel, 12 Fasern
|
||||
- 3.000 m Lieferung und Verlegung Steuerkabel, 0,6/1 kV
|
||||
- 16 Satz Lieferung und Montage MS-Verbindungsmuffe 240 mm², 18/30 kV
|
||||
- 1 Stück Lieferung und Montage LWL-Verbindungsmuffe, 12 Fasern
|
||||
- 4 Satz Lieferung und Montage MS-T-Stecker 240 mm², 18/30 kV
|
||||
- Hauptprüfung / Mantelprüfung / OTDR-Messung
|
||||
16
content/en/referenzen/forst.mdx
Normal file
16
content/en/referenzen/forst.mdx
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: "Neubau Kabeltrasse, 03149 Forst"
|
||||
client: "Mitteldeutsche Netzgesellschaft Strom mbH"
|
||||
date: "2020-09-30"
|
||||
dateString: "03/2020 bis 09/2020"
|
||||
location: "Forst"
|
||||
featuredImage: "/assets/photos/DSC02156.jpg"
|
||||
---
|
||||
|
||||
- 2984 m Kabelgraben ausheben und verfüllen
|
||||
- 945 m Horizontalspülbohrung d 160 + d 50
|
||||
- 3.929 m Verlegung MS-Kabel 240 mm², 12/20 kV
|
||||
- 3.929 m Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 11 Satz Montage MS-Verbindungsmuffe 240 mm², 12/20 kV
|
||||
- 1 Satz Montage MS-Endverschluss 240 mm², 12/20 kV
|
||||
- 2.000 m Rückbau Freileitung (inkl. 16 Stück Maste)
|
||||
19
content/en/referenzen/goerne.mdx
Normal file
19
content/en/referenzen/goerne.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Einspeisung PV-Anlage 14728 Görne"
|
||||
client: "EVH GmbH"
|
||||
date: "2020-07-31"
|
||||
dateString: "05/2020 bis 07/2020"
|
||||
location: "Görne"
|
||||
featuredImage: "/assets/photos/DSC08744.JPG"
|
||||
---
|
||||
|
||||
- 4.215 m Kabelgraben ausheben und verfüllen
|
||||
- 1.285 m Horizontalspülbohrung d 140 + d 50
|
||||
- 5.500 m Verlegung MS-Kabel 300 mm², 12/20 kV
|
||||
- 4.500 m Verlegung MS-Kabel 300 mm², 12/20 kV mittels Kabelpflug
|
||||
- 10.000 m Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 10.000 m Einblasen LWL-Kabel, 12 Fasern
|
||||
- 3 Stück Lieferung und Montage LWL-Verbindungsmuffe, 12 Fasern
|
||||
- 16 Satz Montage MS-Verbindungsmuffe 300 mm², 12/20 kV
|
||||
- 4 Satz Montage MS-T-Stecker 300 mm², 12/20 kV
|
||||
- Mantelprüfung, VLF-Prüfung, OTDR-Messung
|
||||
19
content/en/referenzen/spreewald.mdx
Normal file
19
content/en/referenzen/spreewald.mdx
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
title: "Breitbandausbau FTTC, Planungsregion Spreewald"
|
||||
client: "Telekom Deutschland GmbH"
|
||||
date: "2018-01-31"
|
||||
dateString: "09/2017 bis 01/2018"
|
||||
location: "Spreewald"
|
||||
featuredImage: "/assets/photos/DSC01129.JPG"
|
||||
---
|
||||
|
||||
- 4.006 m Kabelgraben ausheben und verfüllen
|
||||
- 4.006 m Verlegung PE-Schutzrohr 50 x 4,6 mm
|
||||
- 13.008 m Horizontalspülbohrung D 50
|
||||
- 94.951 m Einblasen von Kabel/Rohren unbelegt
|
||||
- 42 Stück Stellen von Multifunktionsgehäusen
|
||||
- Aufbau von Energieanschlusssäulen
|
||||
- Aufbau elektrischer Anlagen 230V
|
||||
- Koordination mit Energieversorgungsunternehmen
|
||||
- Inbetriebnahme der elektrischen Anlagen
|
||||
- Oberflächen- und Tiefbauarbeiten für Multifunktionsgehäuse
|
||||
86
lib/map-data.ts
Normal file
86
lib/map-data.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
export interface Location {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'hq' | 'branch' | 'project';
|
||||
x: number;
|
||||
y: number;
|
||||
description: string;
|
||||
details?: string[];
|
||||
href?: string;
|
||||
featuredImage?: string;
|
||||
}
|
||||
|
||||
export const defaultLocations: Location[] = [
|
||||
{
|
||||
id: 'guben',
|
||||
name: 'Guben (Hauptsitz)',
|
||||
type: 'hq',
|
||||
x: 85,
|
||||
y: 48,
|
||||
description: 'E-TIB GmbH Holding & Bohrtechnik GmbH',
|
||||
details: ['Zentrale Steuerung', 'Kabelleitungstiefbau', 'Maschinenpark'],
|
||||
},
|
||||
{
|
||||
id: 'buelstedt',
|
||||
name: 'Bülstedt (Ingenieurgesellschaft)',
|
||||
type: 'branch',
|
||||
x: 37,
|
||||
y: 25,
|
||||
description: 'E-TIB Ingenieurgesellschaft mbH',
|
||||
details: ['Planung & Projektierung', 'Vermessung', 'Dokumentation'],
|
||||
},
|
||||
{
|
||||
id: 'spreewald',
|
||||
name: 'Spreewald (LWL-Trasse)',
|
||||
type: 'project',
|
||||
x: 81,
|
||||
y: 42,
|
||||
description: '28km LWL-Trasse inkl. Spülbohrung',
|
||||
href: '/referenzen/spreewald',
|
||||
},
|
||||
{
|
||||
id: 'bomlitz',
|
||||
name: 'Bomlitz (110kV-Trasse)',
|
||||
type: 'project',
|
||||
x: 43,
|
||||
y: 30,
|
||||
description: 'Neuverlegung einer 110kV Hochspannungstrasse',
|
||||
href: '/referenzen/bomlitz',
|
||||
},
|
||||
{
|
||||
id: 'forst',
|
||||
name: 'Forst (Verteilerknoten)',
|
||||
type: 'project',
|
||||
x: 87,
|
||||
y: 52,
|
||||
description: 'Ausbau lokaler Glasfasernetze',
|
||||
href: '/referenzen/forst',
|
||||
},
|
||||
{
|
||||
id: 'eisenhuettenstadt',
|
||||
name: 'Eisenhüttenstadt (Industriegebiet)',
|
||||
type: 'project',
|
||||
x: 86,
|
||||
y: 44,
|
||||
description: 'Erschließung Industriegebiet Nord',
|
||||
href: '/referenzen/eisenhuettenstadt',
|
||||
},
|
||||
{
|
||||
id: 'goerne',
|
||||
name: 'Görne (Breitbandausbau)',
|
||||
type: 'project',
|
||||
x: 65,
|
||||
y: 35,
|
||||
description: 'Glasfaser-Rückgrat für 3 Gemeinden',
|
||||
href: '/referenzen/goerne',
|
||||
},
|
||||
{
|
||||
id: 'boerde',
|
||||
name: 'Börde (Windpark-Anschluss)',
|
||||
type: 'project',
|
||||
x: 55,
|
||||
y: 38,
|
||||
description: 'Kabeltrasse für erneuerbare Energien',
|
||||
href: '/referenzen/boerde',
|
||||
}
|
||||
];
|
||||
52
lib/references.ts
Normal file
52
lib/references.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import matter from 'gray-matter';
|
||||
|
||||
export interface ReferenceFrontmatter {
|
||||
title: string;
|
||||
client: string;
|
||||
date: string;
|
||||
dateString?: string;
|
||||
featuredImage?: string | null;
|
||||
location: string;
|
||||
}
|
||||
|
||||
export interface ReferenceData {
|
||||
slug: string;
|
||||
frontmatter: ReferenceFrontmatter;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export async function getReferenceBySlug(slug: string, locale: string): Promise<ReferenceData | null> {
|
||||
const localeDir = path.join(process.cwd(), 'content', locale, 'referenzen');
|
||||
const filePath = path.join(localeDir, `${slug}.mdx`);
|
||||
|
||||
if (!fs.existsSync(filePath)) return null;
|
||||
|
||||
const source = fs.readFileSync(filePath, 'utf8');
|
||||
const { content, data } = matter(source);
|
||||
|
||||
return {
|
||||
slug,
|
||||
frontmatter: data as ReferenceFrontmatter,
|
||||
content,
|
||||
};
|
||||
}
|
||||
|
||||
export async function getAllReferences(locale: string): Promise<ReferenceData[]> {
|
||||
const localeDir = path.join(process.cwd(), 'content', locale, 'referenzen');
|
||||
if (!fs.existsSync(localeDir)) return [];
|
||||
|
||||
const files = fs.readdirSync(localeDir).filter(f => f.endsWith('.mdx'));
|
||||
|
||||
const references = await Promise.all(
|
||||
files.map(async f => {
|
||||
const slug = f.replace('.mdx', '');
|
||||
return await getReferenceBySlug(slug, locale);
|
||||
})
|
||||
);
|
||||
|
||||
return references
|
||||
.filter((p): p is ReferenceData => p !== null)
|
||||
.sort((a, b) => new Date(b.frontmatter.date).getTime() - new Date(a.frontmatter.date).getTime());
|
||||
}
|
||||
@@ -17,9 +17,9 @@ export const getOrganizationSchema = () => ({
|
||||
sameAs: ['https://www.instagram.com/me.and.eloise/'],
|
||||
contactPoint: {
|
||||
'@type': 'ContactPoint' as const,
|
||||
telephone: '+49-15207230518',
|
||||
telephone: '+4935616857733',
|
||||
contactType: 'customer service' as const,
|
||||
email: 'd.joseph@e-tib.com',
|
||||
email: 'info@e-tib.com',
|
||||
availableLanguage: ['German', 'English'],
|
||||
},
|
||||
});
|
||||
@@ -43,8 +43,8 @@ export const getLocalBusinessSchema = () => ({
|
||||
logo: LOGO_URL,
|
||||
image: LOGO_URL,
|
||||
description: 'Ihr Partner für Kabelleitungstiefbau, Horizontalspülbohrungen, Planung und Vermessung in Guben und überregional.',
|
||||
telephone: '+49-15207230518',
|
||||
email: 'd.joseph@e-tib.com',
|
||||
telephone: '+4935616857733',
|
||||
email: 'info@e-tib.com',
|
||||
address: {
|
||||
'@type': 'PostalAddress' as const,
|
||||
streetAddress: 'Gewerbestraße 22',
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
"howToReachUs": "So erreichen Sie uns",
|
||||
"office": "Hauptsitz Guben",
|
||||
"address": "Gewerbestraße 22\n03172 Guben\nDeutschland",
|
||||
"phone": "+49 15207230518",
|
||||
"phone": "+49 (0) 3561 / 68577 33",
|
||||
"email": "d.joseph@e-tib.com"
|
||||
},
|
||||
"hours": {
|
||||
|
||||
@@ -96,7 +96,7 @@
|
||||
"howToReachUs": "How to reach us",
|
||||
"office": "Headquarters Guben",
|
||||
"address": "Gewerbestraße 22\n03172 Guben\nGermany",
|
||||
"phone": "+49 15207230518",
|
||||
"phone": "+49 (0) 3561 / 68577 33",
|
||||
"email": "d.joseph@e-tib.com"
|
||||
},
|
||||
"hours": {
|
||||
|
||||
@@ -38,6 +38,9 @@ const nextConfig = {
|
||||
},
|
||||
},
|
||||
...(isProd ? { output: 'standalone' } : {}),
|
||||
env: {
|
||||
NEXT_PUBLIC_APP_VERSION: process.env.NEXT_PUBLIC_APP_VERSION || process.env.npm_package_version || 'dev',
|
||||
},
|
||||
// Prevent webpack from restarting when .env files are touched via Docker volume mount
|
||||
webpack: (config, { dev }) => {
|
||||
if (dev) {
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
"@next/bundle-analyzer": "^16.1.6",
|
||||
"@tailwindcss/cli": "^4.1.18",
|
||||
"@tailwindcss/postcss": "^4.1.18",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@types/geojson": "^7946.0.16",
|
||||
"@types/leaflet": "^1.9.21",
|
||||
"@types/node": "^22.19.3",
|
||||
|
||||
29
pnpm-lock.yaml
generated
29
pnpm-lock.yaml
generated
@@ -178,6 +178,9 @@ importers:
|
||||
'@tailwindcss/postcss':
|
||||
specifier: ^4.1.18
|
||||
version: 4.2.2
|
||||
'@tailwindcss/typography':
|
||||
specifier: ^0.5.19
|
||||
version: 0.5.19(tailwindcss@4.2.2)
|
||||
'@types/geojson':
|
||||
specifier: ^7946.0.16
|
||||
version: 7946.0.16
|
||||
@@ -2928,6 +2931,11 @@ packages:
|
||||
'@tailwindcss/postcss@4.2.2':
|
||||
resolution: {integrity: sha512-n4goKQbW8RVXIbNKRB/45LzyUqN451deQK0nzIeauVEqjlI49slUlgKYJM2QyUzap/PcpnS7kzSUmPb1sCRvYQ==}
|
||||
|
||||
'@tailwindcss/typography@0.5.19':
|
||||
resolution: {integrity: sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==}
|
||||
peerDependencies:
|
||||
tailwindcss: '>=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1'
|
||||
|
||||
'@tootallnate/quickjs-emscripten@0.23.0':
|
||||
resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==}
|
||||
|
||||
@@ -4131,6 +4139,11 @@ packages:
|
||||
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==}
|
||||
engines: {node: '>= 6'}
|
||||
|
||||
cssesc@3.0.0:
|
||||
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
|
||||
engines: {node: '>=4'}
|
||||
hasBin: true
|
||||
|
||||
cssstyle@5.3.7:
|
||||
resolution: {integrity: sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==}
|
||||
engines: {node: '>=20'}
|
||||
@@ -6634,6 +6647,10 @@ packages:
|
||||
postcss-media-query-parser@0.2.3:
|
||||
resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==}
|
||||
|
||||
postcss-selector-parser@6.0.10:
|
||||
resolution: {integrity: sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==}
|
||||
engines: {node: '>=4'}
|
||||
|
||||
postcss-value-parser@4.2.0:
|
||||
resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==}
|
||||
|
||||
@@ -10800,6 +10817,11 @@ snapshots:
|
||||
postcss: 8.5.8
|
||||
tailwindcss: 4.2.2
|
||||
|
||||
'@tailwindcss/typography@0.5.19(tailwindcss@4.2.2)':
|
||||
dependencies:
|
||||
postcss-selector-parser: 6.0.10
|
||||
tailwindcss: 4.2.2
|
||||
|
||||
'@tootallnate/quickjs-emscripten@0.23.0': {}
|
||||
|
||||
'@turbo/darwin-64@2.9.3':
|
||||
@@ -12133,6 +12155,8 @@ snapshots:
|
||||
|
||||
css-what@6.2.2: {}
|
||||
|
||||
cssesc@3.0.0: {}
|
||||
|
||||
cssstyle@5.3.7:
|
||||
dependencies:
|
||||
'@asamuzakjp/css-color': 4.1.2
|
||||
@@ -15275,6 +15299,11 @@ snapshots:
|
||||
|
||||
postcss-media-query-parser@0.2.3: {}
|
||||
|
||||
postcss-selector-parser@6.0.10:
|
||||
dependencies:
|
||||
cssesc: 3.0.0
|
||||
util-deprecate: 1.0.2
|
||||
|
||||
postcss-value-parser@4.2.0: {}
|
||||
|
||||
postcss@8.4.31:
|
||||
|
||||
Reference in New Issue
Block a user