Compare commits
11 Commits
content/ka
...
fix/ci-dis
| Author | SHA1 | Date | |
|---|---|---|---|
| d2668e36eb | |||
| 5678ddcfd9 | |||
| 06d5178614 | |||
| a983696153 | |||
| 6908964df5 | |||
| 159587f545 | |||
| c02b49644e | |||
| 313fa14c56 | |||
| 052be7d1c9 | |||
| aef10f706c | |||
| 35d9650626 |
@@ -43,9 +43,20 @@ jobs:
|
||||
- name: 🧹 Maintenance (High Density Cleanup)
|
||||
shell: bash
|
||||
run: |
|
||||
echo "Purging old build layers and dangling images..."
|
||||
docker image prune -f
|
||||
docker builder prune -f --filter "until=24h"
|
||||
echo "=== System Disk Usage ==="
|
||||
df -h || true
|
||||
echo "=== Tool Cache Usage ==="
|
||||
du -sh /opt/hostedtoolcache/* || true
|
||||
du -sh /opt/hostedtoolcache/.[!.]* || true
|
||||
echo "Purging old tool caches..."
|
||||
rm -rf /opt/hostedtoolcache/* || true
|
||||
rm -rf /opt/hostedtoolcache/.[!.]* || true
|
||||
echo "Purging old build layers, unused volumes and images..."
|
||||
docker builder prune -a -f || true
|
||||
docker volume prune -f || true
|
||||
docker system prune -a -f || true
|
||||
echo "=== System Disk Usage After Prune ==="
|
||||
df -h || true
|
||||
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
@@ -207,6 +218,7 @@ jobs:
|
||||
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 }}
|
||||
NPM_DOMAIN=${{ steps.auth.outputs.working_domain }}
|
||||
tags: registry.infra.mintel.me/mintel/e-tib.com:${{ needs.prepare.outputs.image_tag }}
|
||||
secrets: |
|
||||
"NPM_TOKEN=${{ steps.auth.outputs.working_token }}"
|
||||
|
||||
1
.turbo-test/85340b254e0f10f1-manifest.json
Normal file
1
.turbo-test/85340b254e0f10f1-manifest.json
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{".turbo/turbo-lint.log":{"size":10746,"mtime_nanos":1779098006288513580,"mode":420,"is_dir":false}},"order":[".turbo/turbo-lint.log"]}
|
||||
1
.turbo-test/85340b254e0f10f1-meta.json
Normal file
1
.turbo-test/85340b254e0f10f1-meta.json
Normal file
@@ -0,0 +1 @@
|
||||
{"hash":"85340b254e0f10f1","duration":6595,"sha":"35d9650626b56a727e9c1981308145cb7b2f28aa","dirty_hash":"9cc3e16c40a10f42f7a963333e800e1384f047b1f387b18b5f37769c34f36609"}
|
||||
BIN
.turbo-test/85340b254e0f10f1.tar.zst
Normal file
BIN
.turbo-test/85340b254e0f10f1.tar.zst
Normal file
Binary file not shown.
1
.turbo/cache/32905076da5f4894-manifest.json
vendored
Normal file
1
.turbo/cache/32905076da5f4894-manifest.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{".turbo/turbo-typecheck.log":{"size":92,"mtime_nanos":1779097674383861303,"mode":420,"is_dir":false}},"order":[".turbo/turbo-typecheck.log"]}
|
||||
1
.turbo/cache/32905076da5f4894-meta.json
vendored
Normal file
1
.turbo/cache/32905076da5f4894-meta.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"hash":"32905076da5f4894","duration":4492,"sha":"35d9650626b56a727e9c1981308145cb7b2f28aa","dirty_hash":"58f8ebc92a0452cbb0a09c5ebe800385fcc42ff82fee098bb7d6c8828bc526f0"}
|
||||
BIN
.turbo/cache/32905076da5f4894.tar.zst
vendored
Normal file
BIN
.turbo/cache/32905076da5f4894.tar.zst
vendored
Normal file
Binary file not shown.
1
.turbo/cache/7e2629942c881f80-manifest.json
vendored
Normal file
1
.turbo/cache/7e2629942c881f80-manifest.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{".turbo/turbo-test.log":{"size":818,"mtime_nanos":1779097671747078359,"mode":420,"is_dir":false}},"order":[".turbo/turbo-test.log"]}
|
||||
1
.turbo/cache/7e2629942c881f80-meta.json
vendored
Normal file
1
.turbo/cache/7e2629942c881f80-meta.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"hash":"7e2629942c881f80","duration":1855,"sha":"35d9650626b56a727e9c1981308145cb7b2f28aa","dirty_hash":"58f8ebc92a0452cbb0a09c5ebe800385fcc42ff82fee098bb7d6c8828bc526f0"}
|
||||
BIN
.turbo/cache/7e2629942c881f80.tar.zst
vendored
Normal file
BIN
.turbo/cache/7e2629942c881f80.tar.zst
vendored
Normal file
Binary file not shown.
1
.turbo/cache/85340b254e0f10f1-manifest.json
vendored
Normal file
1
.turbo/cache/85340b254e0f10f1-manifest.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"files":{".turbo/turbo-lint.log":{"size":10746,"mtime_nanos":1779097675143794164,"mode":420,"is_dir":false}},"order":[".turbo/turbo-lint.log"]}
|
||||
1
.turbo/cache/85340b254e0f10f1-meta.json
vendored
Normal file
1
.turbo/cache/85340b254e0f10f1-meta.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"hash":"85340b254e0f10f1","duration":5252,"sha":"35d9650626b56a727e9c1981308145cb7b2f28aa","dirty_hash":"58f8ebc92a0452cbb0a09c5ebe800385fcc42ff82fee098bb7d6c8828bc526f0"}
|
||||
BIN
.turbo/cache/85340b254e0f10f1.tar.zst
vendored
Normal file
BIN
.turbo/cache/85340b254e0f10f1.tar.zst
vendored
Normal file
Binary file not shown.
119
.turbo/turbo-lint.log
Normal file
119
.turbo/turbo-lint.log
Normal file
@@ -0,0 +1,119 @@
|
||||
|
||||
|
||||
> e-tib-nextjs@2.2.12 lint /Volumes/Alpha SSD/Coding/e-tib.com
|
||||
> eslint .
|
||||
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/[slug]/page.tsx
|
||||
1:20 warning 'redirect' is defined but never used @typescript-eslint/no-unused-vars
|
||||
67:24 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/blog/[slug]/page.tsx
|
||||
1:20 warning 'redirect' is defined but never used @typescript-eslint/no-unused-vars
|
||||
39:24 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/error.tsx
|
||||
7:30 warning 'AlertTriangle' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/not-found.tsx
|
||||
6:10 warning 'Terminal' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/referenzen/[slug]/page.tsx
|
||||
91:26 warning Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element @next/next/no-img-element
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/app/[locale]/referenzen/page.tsx
|
||||
1:21 warning 'Heading' is defined but never used @typescript-eslint/no-unused-vars
|
||||
1:30 warning 'Badge' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/JsonLd.tsx
|
||||
1:30 warning 'Graph' is defined but never used @typescript-eslint/no-unused-vars
|
||||
43:31 warning '_' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
48:29 warning '_' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CertificatesBlock.tsx
|
||||
6:10 warning 'Button' is defined but never used @typescript-eslint/no-unused-vars
|
||||
9:10 warning 'FileText' is defined but never used @typescript-eslint/no-unused-vars
|
||||
77:5 warning Error: Calling setState synchronously within an effect can trigger cascading renders
|
||||
|
||||
Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
|
||||
* Update external systems with the latest state from React.
|
||||
* Subscribe for updates from some external system, calling setState in a callback function when external state changes.
|
||||
|
||||
Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CertificatesBlock.tsx:77:5
|
||||
75 |
|
||||
76 | useEffect(() => {
|
||||
> 77 | setIsMounted(true);
|
||||
| ^^^^^^^^^^^^ Avoid calling setState() directly within an effect
|
||||
78 | }, []);
|
||||
79 |
|
||||
80 | const badgeText = badge || 'Zertifizierungen & Nachweise'; react-hooks/set-state-in-effect
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CompetenceBentoGrid.tsx
|
||||
53:5 warning Error: Calling setState synchronously within an effect can trigger cascading renders
|
||||
|
||||
Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
|
||||
* Update external systems with the latest state from React.
|
||||
* Subscribe for updates from some external system, calling setState in a callback function when external state changes.
|
||||
|
||||
Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended. (https://react.dev/learn/you-might-not-need-an-effect).
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/CompetenceBentoGrid.tsx:53:5
|
||||
51 |
|
||||
52 | useEffect(() => {
|
||||
> 53 | setIsMounted(true);
|
||||
| ^^^^^^^^^^^^ Avoid calling setState() directly within an effect
|
||||
54 | }, []);
|
||||
55 |
|
||||
56 | const badge = props.badge || data?.badge || 'Leistungsspektrum'; react-hooks/set-state-in-effect
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/HeroVideo.tsx
|
||||
5:18 warning 'AnimatePresence' is defined but never used @typescript-eslint/no-unused-vars
|
||||
6:10 warning 'useState' is defined but never used @typescript-eslint/no-unused-vars
|
||||
6:20 warning 'useEffect' is defined but never used @typescript-eslint/no-unused-vars
|
||||
45:12 warning 'e' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/InteractiveGermanyMap.tsx
|
||||
5:46 warning 'ArrowUpRight' is defined but never used @typescript-eslint/no-unused-vars
|
||||
147:23 warning 'isNearRight' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/blocks/TeamGridBlock.tsx
|
||||
20:39 warning 'title' is defined but never used. Allowed unused args must match /^_/u @typescript-eslint/no-unused-vars
|
||||
20:46 warning 'department' is defined but never used. Allowed unused args must match /^_/u @typescript-eslint/no-unused-vars
|
||||
20:58 warning 'showContact' is assigned a value but never used. Allowed unused args must match /^_/u @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/decorations/CorporateBackground.tsx
|
||||
36:13 warning 'distance' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/home/Hero.tsx
|
||||
9:39 warning 'useCallback' is defined but never used @typescript-eslint/no-unused-vars
|
||||
77:6 warning React Hook useEffect has a missing dependency: 'HERO_PLACEHOLDERS'. Either include it or remove the dependency array react-hooks/exhaustive-deps
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/home/MeetTheTeam.tsx
|
||||
8:9 warning 'teamT' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/layout/Footer.tsx
|
||||
4:35 warning 'Accessibility' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/providers/InitialLoader.tsx
|
||||
5:8 warning 'Image' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/providers/PageTransitionShutter.tsx
|
||||
6:8 warning 'Image' is defined but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/search/AIOrb.tsx
|
||||
153:13 warning 'breathe' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
212:15 warning 'targetExcite' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/components/search/AISearchResults.tsx
|
||||
99:6 warning React Hook useEffect has missing dependencies: 'handleSearch' and 'initialQuery'. Either include them or remove the dependency array react-hooks/exhaustive-deps
|
||||
|
||||
/Volumes/Alpha SSD/Coding/e-tib.com/lib/blog.ts
|
||||
6:7 warning 'BLOG_DIR' is assigned a value but never used @typescript-eslint/no-unused-vars
|
||||
94:7 warning 'next' is never reassigned. Use 'const' instead prefer-const
|
||||
95:7 warning 'prev' is never reassigned. Use 'const' instead prefer-const
|
||||
|
||||
✖ 38 problems (0 errors, 38 warnings)
|
||||
0 errors and 2 warnings potentially fixable with the `--fix` option.
|
||||
|
||||
31
.turbo/turbo-test.log
Normal file
31
.turbo/turbo-test.log
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
> e-tib-nextjs@2.2.12 test /Volumes/Alpha SSD/Coding/e-tib.com
|
||||
> vitest run --passWithNoTests
|
||||
|
||||
[?25l
|
||||
RUN v4.1.2 /Volumes/Alpha SSD/Coding/e-tib.com
|
||||
|
||||
[?2026h
|
||||
❯ lib/mail/mailer.test.ts [queued]
|
||||
|
||||
Test Files 0 passed (2)
|
||||
Tests 0 passed (0)
|
||||
Start at 11:47:51
|
||||
Duration 504ms
|
||||
[?2026l[?2026h[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K ✓ lib/mail/mailer.test.ts (1 test) 2ms
|
||||
|
||||
❯ lib/env.test.ts 0/6
|
||||
|
||||
Test Files 1 passed (2)
|
||||
Tests 1 passed (7)
|
||||
Start at 11:47:51
|
||||
Duration 605ms
|
||||
[?2026l[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K[1A[K ✓ lib/env.test.ts (6 tests) 3ms
|
||||
|
||||
Test Files 2 passed (2)
|
||||
Tests 7 passed (7)
|
||||
Start at 11:47:51
|
||||
Duration 672ms (transform 113ms, setup 0ms, import 222ms, tests 5ms, environment 813ms)
|
||||
|
||||
[?25h
|
||||
5
.turbo/turbo-typecheck.log
Normal file
5
.turbo/turbo-typecheck.log
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
> e-tib-nextjs@2.2.12 typecheck /Volumes/Alpha SSD/Coding/e-tib.com
|
||||
> tsc --noEmit
|
||||
|
||||
@@ -20,13 +20,15 @@ ENV CI=true
|
||||
COPY pnpm-lock.yaml package.json .npmrc* ./
|
||||
COPY patches* ./patches/
|
||||
|
||||
ARG NPM_DOMAIN=git.infra.mintel.me
|
||||
|
||||
# Configure private registry and install dependencies
|
||||
RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
|
||||
--mount=type=secret,id=NPM_TOKEN \
|
||||
if [ -f /run/secrets/NPM_TOKEN ]; then \
|
||||
export NPM_TOKEN=$(cat /run/secrets/NPM_TOKEN); \
|
||||
echo "@mintel:registry=https://git.infra.mintel.me/api/packages/mmintel/npm" > .npmrc; \
|
||||
echo "//git.infra.mintel.me/api/packages/mmintel/npm/:_authToken=${NPM_TOKEN}" >> .npmrc; \
|
||||
echo "@mintel:registry=https://${NPM_DOMAIN}/api/packages/mmintel/npm" > .npmrc; \
|
||||
echo "//${NPM_DOMAIN}/api/packages/mmintel/npm/:_authToken=${NPM_TOKEN}" >> .npmrc; \
|
||||
fi && \
|
||||
pnpm install --no-frozen-lockfile && \
|
||||
rm -f .npmrc
|
||||
|
||||
@@ -5,8 +5,8 @@ RUN apk add --no-cache libc6-compat python3 make g++ curl
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# Enable corepack for pnpm
|
||||
RUN corepack enable
|
||||
# Install pnpm v10 explicitly (corepack defaults to v11 which requires Node 22)
|
||||
RUN npm install -g pnpm@10.18.3
|
||||
|
||||
# Pre-set the pnpm store directory
|
||||
ENV PNPM_HOME="/pnpm"
|
||||
|
||||
@@ -26,8 +26,12 @@ import { FaqBlock } from '@/components/blocks/FaqBlock';
|
||||
import { CertificatesBlock } from '@/components/blocks/CertificatesBlock';
|
||||
import { HeroSection } from '@/components/blocks/HeroSection';
|
||||
import { TeamGrid } from '@/components/blocks/TeamGrid';
|
||||
import { DeepDrillAnimation } from '@/components/blocks/DeepDrillAnimation';
|
||||
import { DataGridPulse } from '@/components/blocks/DataGridPulse';
|
||||
import { GrowthChart } from '@/components/blocks/GrowthChart';
|
||||
import JsonLd from '@/components/JsonLd';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { AnimatedCounter } from '@/components/ui';
|
||||
|
||||
|
||||
const mdxComponents = {
|
||||
@@ -47,6 +51,10 @@ const mdxComponents = {
|
||||
TeamGrid,
|
||||
JsonLd,
|
||||
Button,
|
||||
AnimatedCounter,
|
||||
GrowthChart,
|
||||
DeepDrillAnimation,
|
||||
DataGridPulse,
|
||||
// Standard HTML element mapping for consistent E-TIB typography
|
||||
h1: (props: any) => <Heading level={1} size="2" className="hidden" {...props} />, // Hidden because Hero handles H1
|
||||
h2: (props: any) => <Heading level={2} size="3" className="mt-16 mb-6 border-b border-neutral-100 pb-4" {...props} />,
|
||||
@@ -169,7 +177,7 @@ export default async function Page(props: { params: Promise<{ locale: string; sl
|
||||
id: r.slug,
|
||||
slug: r.slug,
|
||||
title: r.frontmatter.title,
|
||||
category: r.frontmatter.category || 'Projekt',
|
||||
category: Array.isArray(r.frontmatter.category) ? r.frontmatter.category[0] : (r.frontmatter.category || 'Projekt'),
|
||||
image: r.frontmatter.featuredImage
|
||||
}))} />,
|
||||
};
|
||||
|
||||
@@ -18,6 +18,9 @@ import JsonLd from '@/components/JsonLd';
|
||||
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { Heading } from '@/components/ui/Heading';
|
||||
import { AnimatedCounter } from '@/components/ui';
|
||||
import { InteractiveGermanyMap } from '@/components/blocks/InteractiveGermanyMap';
|
||||
import { ScaleOfImpact } from '@/components/blocks/ScaleOfImpact';
|
||||
import { getAllReferences } from '@/lib/references';
|
||||
|
||||
const mdxComponents = (references: any[]) => ({
|
||||
@@ -31,6 +34,9 @@ const mdxComponents = (references: any[]) => ({
|
||||
JsonLd,
|
||||
Button,
|
||||
Heading,
|
||||
AnimatedCounter,
|
||||
InteractiveGermanyMap,
|
||||
ScaleOfImpact,
|
||||
});
|
||||
|
||||
export async function generateMetadata(props: any): Promise<Metadata> {
|
||||
|
||||
@@ -8,7 +8,7 @@ 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';
|
||||
import { defaultLocations, minorLocations } from '@/lib/map-data';
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{
|
||||
@@ -34,6 +34,17 @@ export async function generateMetadata({ params }: PageProps): Promise<Metadata>
|
||||
};
|
||||
}
|
||||
|
||||
function cleanLocation(location?: string): string {
|
||||
if (!location) return '';
|
||||
// Remove 5 digit postal codes
|
||||
let cleaned = location.replace(/\b\d{5}\b/g, '');
|
||||
// Clean up multiple spaces, slashes and commas
|
||||
cleaned = cleaned.replace(/\s*,\s*/g, ', ').replace(/\s*\/\s*/g, ' / ').trim();
|
||||
// Remove leading/trailing slash/comma residues
|
||||
cleaned = cleaned.replace(/^[,/\s]+|[,/\s]+$/g, '').trim();
|
||||
return cleaned || location;
|
||||
}
|
||||
|
||||
export default async function ReferenzenOverview(props: { params: Promise<{ locale: string }> }) {
|
||||
const { locale } = await props.params;
|
||||
setRequestLocale(locale);
|
||||
@@ -41,8 +52,8 @@ export default async function ReferenzenOverview(props: { params: Promise<{ loca
|
||||
|
||||
const references = await getAllReferences(locale);
|
||||
|
||||
// Enrich the static map locations with dynamic project data (images, details)
|
||||
const enrichedLocations = defaultLocations.map(loc => {
|
||||
const allLocations = [...defaultLocations, ...minorLocations];
|
||||
const enrichedLocations = allLocations.map(loc => {
|
||||
if (loc.type === 'project') {
|
||||
const ref = references.find(r => r.slug === loc.id);
|
||||
if (ref) {
|
||||
@@ -104,7 +115,7 @@ export default async function ReferenzenOverview(props: { params: Promise<{ loca
|
||||
<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}
|
||||
{cleanLocation(ref.frontmatter.location)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -93,7 +93,7 @@ export function CertificatesBlock({ badge, title, description, certificates = de
|
||||
|
||||
const itemVariants = {
|
||||
hidden: { opacity: 0, y: 20 },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.5, ease: 'easeOut' } },
|
||||
show: { opacity: 1, y: 0, transition: { duration: 0.5, ease: 'easeOut' as const } },
|
||||
};
|
||||
|
||||
if (!isMounted) {
|
||||
|
||||
52
components/blocks/DataGridPulse.tsx
Normal file
52
components/blocks/DataGridPulse.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
import { useLocale } from 'next-intl';
|
||||
|
||||
export function DataGridPulse() {
|
||||
const locale = useLocale();
|
||||
return (
|
||||
<div className="relative w-full py-32 bg-[#050B14] overflow-hidden flex flex-col items-center border-y border-primary/20 -mx-[50vw] px-[50vw] mb-16">
|
||||
|
||||
{/* Blueprint grid background */}
|
||||
<div
|
||||
className="absolute inset-0 opacity-20 pointer-events-none"
|
||||
style={{
|
||||
backgroundImage: 'linear-gradient(#82ED20 1px, transparent 1px), linear-gradient(90deg, #82ED20 1px, transparent 1px)',
|
||||
backgroundSize: '40px 40px'
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Pulsing horizontal lines (Data Flow) */}
|
||||
<motion.div
|
||||
animate={{ x: ["-100%", "100%"] }}
|
||||
transition={{ duration: 3, repeat: Infinity, ease: "linear" }}
|
||||
className="absolute top-1/3 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-primary to-transparent opacity-50 blur-[2px]"
|
||||
/>
|
||||
<motion.div
|
||||
animate={{ x: ["100%", "-100%"] }}
|
||||
transition={{ duration: 4, repeat: Infinity, ease: "linear" }}
|
||||
className="absolute top-2/3 left-0 w-full h-[2px] bg-gradient-to-r from-transparent via-white to-transparent opacity-30 blur-[2px]"
|
||||
/>
|
||||
|
||||
<div className="relative z-10 w-full max-w-4xl mx-auto flex flex-col items-center text-center">
|
||||
<h3 className="text-sm font-bold uppercase tracking-widest text-primary mb-6">
|
||||
{locale === 'en' ? 'Network Expansion in Numbers' : 'Netzausbau in Zahlen'}
|
||||
</h3>
|
||||
|
||||
<div className="bg-black/40 backdrop-blur-md p-12 md:p-16 rounded-3xl border border-white/10 shadow-2xl">
|
||||
<div className="font-mono text-6xl md:text-8xl font-black text-white tracking-tighter mb-4 leading-none" style={{ fontVariantNumeric: 'tabular-nums' }}>
|
||||
372.161<span className="text-primary text-3xl md:text-5xl ml-2">m</span>
|
||||
</div>
|
||||
<p className="text-white/70 text-lg md:text-xl font-medium max-w-lg mx-auto">
|
||||
{locale === 'en'
|
||||
? 'Cable routes laid since 2023. A massive infrastructure achievement, driven by our own machinery.'
|
||||
: 'Verlegte Kabeltrassen seit 2023. Eine massive Infrastrukturleistung, getragen von unserem eigenen Maschinenpark.'}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
}
|
||||
64
components/blocks/DeepDrillAnimation.tsx
Normal file
64
components/blocks/DeepDrillAnimation.tsx
Normal file
@@ -0,0 +1,64 @@
|
||||
'use client';
|
||||
|
||||
import React, { useRef } from 'react';
|
||||
import { motion, useScroll, useTransform } from 'framer-motion';
|
||||
import { useLocale } from 'next-intl';
|
||||
|
||||
export function DeepDrillAnimation() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const locale = useLocale();
|
||||
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: containerRef,
|
||||
offset: ["start center", "end center"]
|
||||
});
|
||||
|
||||
const drillDepth = useTransform(scrollYProgress, [0, 1], ["0%", "100%"]);
|
||||
|
||||
return (
|
||||
<div ref={containerRef} className="relative w-full py-32 flex flex-col items-center">
|
||||
|
||||
<div className="absolute inset-0 bg-[#050B14] -mx-[50vw] px-[50vw]" />
|
||||
|
||||
<div className="relative z-10 w-full max-w-3xl mx-auto flex flex-col items-center text-center text-white">
|
||||
|
||||
<h3 className="text-3xl font-heading font-extrabold mb-8 tracking-tight">
|
||||
{locale === 'en' ? 'Precision in Depth' : 'Präzision in der Tiefe'}
|
||||
</h3>
|
||||
<p className="text-white/60 text-lg mb-16 max-w-xl">
|
||||
{locale === 'en'
|
||||
? 'Horizontal Directional Drilling (HDD) allows us to cross obstacles and rivers with extreme care.'
|
||||
: 'Horizontalspülbohrverfahren (HDD) erlaubt uns, Hindernisse und Flüsse extrem schonend zu unterqueren.'}
|
||||
</p>
|
||||
|
||||
{/* The Drill Path */}
|
||||
<div className="relative w-2 h-96 bg-white/10 rounded-full mb-16">
|
||||
<motion.div
|
||||
className="absolute top-0 left-0 w-full bg-primary rounded-full"
|
||||
style={{ height: drillDepth, boxShadow: '0 0 20px rgba(130,237,32,0.6)' }}
|
||||
>
|
||||
{/* The Drill Head */}
|
||||
<div className="absolute -bottom-2 -left-2 w-6 h-6 bg-white rounded-full border-4 border-primary shadow-[0_0_15px_rgba(255,255,255,1)]" />
|
||||
</motion.div>
|
||||
</div>
|
||||
|
||||
{/* The Reveal Data */}
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 20 }}
|
||||
whileInView={{ opacity: 1, y: 0 }}
|
||||
viewport={{ once: true, margin: "-100px" }}
|
||||
transition={{ duration: 0.8 }}
|
||||
className="flex flex-col items-center"
|
||||
>
|
||||
<div className="font-mono text-6xl md:text-8xl font-black text-white tracking-tighter mb-4" style={{ fontVariantNumeric: 'tabular-nums' }}>
|
||||
102.771<span className="text-primary text-3xl md:text-5xl ml-2">m</span>
|
||||
</div>
|
||||
<div className="text-sm font-bold uppercase tracking-widest text-primary">
|
||||
{locale === 'en' ? 'Drilled distance since 2023' : 'Gebohrte Strecke seit 2023'}
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
80
components/blocks/GrowthChart.tsx
Normal file
80
components/blocks/GrowthChart.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
'use client';
|
||||
|
||||
import React from 'react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
export function GrowthChart() {
|
||||
const data = [
|
||||
{ year: '2023', hdd: 29436, kabel: 76727 },
|
||||
{ year: '2024', hdd: 28680, kabel: 131964 },
|
||||
{ year: '2025', hdd: 44655, kabel: 163470 },
|
||||
];
|
||||
|
||||
const maxVal = 163470; // Highest value for scaling
|
||||
|
||||
return (
|
||||
<div className="w-full bg-white rounded-3xl p-8 md:p-12 shadow-sm border border-neutral-100 my-16">
|
||||
<div className="mb-10">
|
||||
<h3 className="text-3xl font-heading font-extrabold text-neutral-dark mb-2">Bewiesene Leistungsfähigkeit</h3>
|
||||
<p className="text-neutral-500 font-medium">Unsere verlässliche Baukapazität der letzten drei Jahre (in Metern)</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-8">
|
||||
{data.map((item, index) => {
|
||||
const hddWidth = (item.hdd / maxVal) * 100;
|
||||
const kabelWidth = (item.kabel / maxVal) * 100;
|
||||
|
||||
return (
|
||||
<div key={item.year} className="relative">
|
||||
<div className="text-sm font-extrabold text-neutral-dark mb-2 w-16">{item.year}</div>
|
||||
<div className="space-y-2">
|
||||
{/* Kabelverlegung Bar */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex-1 bg-neutral-100 rounded-full h-6 overflow-hidden relative">
|
||||
<motion.div
|
||||
initial={{ width: 0 }}
|
||||
whileInView={{ width: `${kabelWidth}%` }}
|
||||
viewport={{ once: true, margin: "-50px" }}
|
||||
transition={{ duration: 1.5, delay: 0.1 * index, ease: "easeOut" }}
|
||||
className="absolute top-0 left-0 h-full bg-primary rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-24 text-right text-xs font-bold text-neutral-500 uppercase">
|
||||
Kabel: {new Intl.NumberFormat('de-DE').format(item.kabel)}m
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* HDD Bar */}
|
||||
<div className="flex items-center gap-4">
|
||||
<div className="flex-1 bg-neutral-100 rounded-full h-4 overflow-hidden relative">
|
||||
<motion.div
|
||||
initial={{ width: 0 }}
|
||||
whileInView={{ width: `${hddWidth}%` }}
|
||||
viewport={{ once: true, margin: "-50px" }}
|
||||
transition={{ duration: 1.5, delay: 0.2 + 0.1 * index, ease: "easeOut" }}
|
||||
className="absolute top-0 left-0 h-full bg-neutral-dark rounded-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="w-24 text-right text-xs font-bold text-neutral-500 uppercase">
|
||||
HDD: {new Intl.NumberFormat('de-DE').format(item.hdd)}m
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-8 flex gap-6 border-t border-neutral-100 pt-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-full bg-primary" />
|
||||
<span className="text-xs font-bold text-neutral-500 uppercase">Kabelverlegung</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="w-3 h-3 rounded-full bg-neutral-dark" />
|
||||
<span className="text-xs font-bold text-neutral-500 uppercase">HDD Spülbohrung</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -6,7 +6,10 @@ import { MapPin, Factory, Zap, CheckCircle2, ArrowUpRight } from 'lucide-react';
|
||||
import Image from 'next/image';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { AnimatedGlossyBorder } from '@/components/ui/AnimatedGlossyBorder';
|
||||
import { Location, defaultLocations } from '@/lib/map-data';
|
||||
import { Location, defaultLocations, minorLocations } from '@/lib/map-data';
|
||||
import { useLocale } from 'next-intl';
|
||||
|
||||
const allLocations = [...defaultLocations, ...minorLocations];
|
||||
|
||||
interface Stat {
|
||||
value: string;
|
||||
@@ -31,15 +34,17 @@ export function InteractiveGermanyMap({
|
||||
{ value: '100', suffix: '%', label: 'Überregionale Reichweite' },
|
||||
{ value: '2', suffix: '+', label: 'Operative Standorte' },
|
||||
],
|
||||
locations = defaultLocations,
|
||||
locations = allLocations,
|
||||
isHero = false
|
||||
}: InteractiveGermanyMapProps) {
|
||||
const [activeLocation, setActiveLocation] = useState<Location | null>(null);
|
||||
const router = useRouter();
|
||||
const locale = useLocale();
|
||||
|
||||
const hq = locations.find((l) => l.type === 'hq');
|
||||
const branch = locations.find((l) => l.type === 'branch');
|
||||
const projects = locations.filter((l) => l.type === 'project');
|
||||
const minorNodes = locations.filter((l) => l.type === 'minor_node');
|
||||
|
||||
return (
|
||||
<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"}>
|
||||
@@ -91,80 +96,49 @@ export function InteractiveGermanyMap({
|
||||
</div>
|
||||
|
||||
{/* Map Right */}
|
||||
<div className="xl:col-span-7 relative flex items-center justify-center lg:justify-end mt-8 lg:mt-0 z-10">
|
||||
<div className="xl:col-span-7 relative flex items-center justify-center min-h-[500px] lg:min-h-[700px] z-10 pointer-events-none">
|
||||
{/* Map Container - Enforce strict aspect ratio matching the SVG (1024x1024) */}
|
||||
<div className="relative w-full max-w-[600px] aspect-square z-10">
|
||||
<div className="relative w-full max-w-[600px] aspect-square group pointer-events-auto">
|
||||
|
||||
{/* Map SVG */}
|
||||
<div className="absolute inset-0 opacity-[0.25] mix-blend-screen drop-shadow-2xl brightness-200">
|
||||
<div className="absolute inset-0 opacity-[0.25] mix-blend-screen drop-shadow-2xl brightness-200 pointer-events-none">
|
||||
<Image
|
||||
src="/germany-map.svg"
|
||||
alt="Deutschlandkarte"
|
||||
alt={locale === 'en' ? "Map of Germany" : "Deutschlandkarte"}
|
||||
fill
|
||||
className="object-cover"
|
||||
priority
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Connections (Lines) */}
|
||||
<svg className="absolute inset-0 w-full h-full pointer-events-none z-10">
|
||||
{hq && branch && (
|
||||
<motion.line
|
||||
x1={`${hq.x}%`}
|
||||
y1={`${hq.y}%`}
|
||||
x2={`${branch.x}%`}
|
||||
y2={`${branch.y}%`}
|
||||
stroke="rgba(130,237,32,0.6)"
|
||||
strokeWidth="2"
|
||||
strokeDasharray="6 6"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 1 }}
|
||||
transition={{ duration: 2, ease: "easeOut" }}
|
||||
/>
|
||||
)}
|
||||
{hq && projects.map((proj, idx) => (
|
||||
<motion.line
|
||||
key={proj.id}
|
||||
x1={`${hq.x}%`}
|
||||
y1={`${hq.y}%`}
|
||||
x2={`${proj.x}%`}
|
||||
y2={`${proj.y}%`}
|
||||
stroke="rgba(130,237,32,0.3)"
|
||||
strokeWidth="1.5"
|
||||
initial={{ pathLength: 0, opacity: 0 }}
|
||||
animate={{ pathLength: 1, opacity: 1 }}
|
||||
transition={{ duration: 1.5, delay: 0.5 + idx * 0.2 }}
|
||||
/>
|
||||
))}
|
||||
</svg>
|
||||
{/* Minor Location Markers (The 100+ generic projects) */}
|
||||
{locations.filter(l => l.type === 'minor_node').map((loc, idx) => (
|
||||
<div
|
||||
key={`minor-${idx}`}
|
||||
className="absolute z-10 group/minor cursor-pointer w-10 h-10 flex items-center justify-center"
|
||||
style={{
|
||||
left: `${loc.x}%`,
|
||||
top: `${loc.y}%`,
|
||||
transform: 'translate(-50%, -50%)',
|
||||
}}
|
||||
onMouseEnter={() => setActiveLocation(loc)}
|
||||
onMouseLeave={() => setActiveLocation(null)}
|
||||
>
|
||||
<div className="w-1.5 h-1.5 bg-primary/80 rounded-full group-hover/minor:bg-white group-hover/minor:scale-150 transition-all duration-300" />
|
||||
<div className="absolute inset-0 m-auto w-2 h-2 bg-primary rounded-full opacity-0 group-hover/minor:animate-ping" />
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Location Pins */}
|
||||
{locations.map((loc, idx) => {
|
||||
{/* Major & Reference Location Markers (HQ, Branch, Project) */}
|
||||
{locations.filter(l => l.type !== 'minor_node').map((loc, idx) => {
|
||||
const isHQ = loc.type === 'hq';
|
||||
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] 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 before:absolute before:-top-6 before:left-0 before:w-full before:h-6'
|
||||
: 'bottom-full mb-4 before:absolute before:-bottom-6 before:left-0 before:w-full before:h-6'
|
||||
].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 group cursor-pointer w-16 h-16 flex items-center justify-center ${isActive ? 'z-[60]' : 'z-20'}`}
|
||||
className={`absolute transform -translate-x-1/2 -translate-y-1/2 group/pin 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)}
|
||||
@@ -177,121 +151,125 @@ export function InteractiveGermanyMap({
|
||||
<div className="absolute inset-0 m-auto w-6 h-6 rounded-full animate-ping bg-primary/50 scale-150" />
|
||||
)}
|
||||
|
||||
{/* Marker Dot */}
|
||||
{/* Elegant Marker Dot */}
|
||||
<motion.div
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ type: 'spring', delay: idx * 0.1 }}
|
||||
className={`relative flex items-center justify-center rounded-full shadow-[0_0_20px_rgba(130,237,32,0.4)] transition-transform duration-300 ${
|
||||
isActive ? 'scale-125 z-30 ring-4 ring-primary/30' : 'scale-100'
|
||||
className={`relative flex items-center justify-center rounded-full shadow-[0_0_20px_rgba(130,237,32,0.6)] transition-transform duration-300 ${
|
||||
isActive ? 'scale-125 z-30 ring-4 ring-primary/40' : 'scale-100 group-hover/pin:scale-110'
|
||||
} ${
|
||||
isHQ || isBranch
|
||||
? 'w-6 h-6 bg-primary text-[#050B14]'
|
||||
? 'w-7 h-7 bg-primary text-[#050B14]'
|
||||
: 'w-4 h-4 bg-white ring-[3px] ring-primary'
|
||||
}`}
|
||||
>
|
||||
{(isHQ || isBranch) && <MapPin className="w-3.5 h-3.5" />}
|
||||
{(isHQ || isBranch) && <MapPin className="w-4 h-4" />}
|
||||
</motion.div>
|
||||
|
||||
{/* Tooltip */}
|
||||
<AnimatePresence>
|
||||
{isActive && (
|
||||
<motion.div
|
||||
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`}
|
||||
>
|
||||
{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) => (
|
||||
<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}
|
||||
</motion.li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{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>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Global Tooltip */}
|
||||
<AnimatePresence>
|
||||
{activeLocation && (
|
||||
<motion.div
|
||||
key="tooltip"
|
||||
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.2 }}
|
||||
className="absolute z-[9999] pointer-events-none"
|
||||
style={{
|
||||
left: `${activeLocation.x}%`,
|
||||
top: `${activeLocation.y}%`,
|
||||
transform: activeLocation.x < 50 ? 'translate(20px, -50%)' : 'translate(calc(-100% - 20px), -50%)',
|
||||
}}
|
||||
>
|
||||
<div className="bg-[#050B14]/95 backdrop-blur-xl border border-white/10 rounded-2xl shadow-2xl min-w-[200px] w-max max-w-[300px] text-white overflow-hidden">
|
||||
|
||||
{activeLocation.featuredImage && (
|
||||
<div className="relative w-full h-32 bg-neutral-900">
|
||||
<Image
|
||||
src={activeLocation.featuredImage}
|
||||
alt={activeLocation.name}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-[#050B14] to-transparent opacity-90" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="p-4">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<MapPin className="w-3.5 h-3.5 text-primary" />
|
||||
<span className="text-xs font-bold text-primary uppercase tracking-wider">
|
||||
{activeLocation.type === 'hq' ? 'Hauptsitz' :
|
||||
activeLocation.type === 'branch' ? 'Niederlassung' :
|
||||
activeLocation.type === 'minor_node' ? 'Projekt' : 'Referenz'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="font-heading font-bold text-lg leading-tight mb-2">
|
||||
{activeLocation.name}
|
||||
</div>
|
||||
{activeLocation.type !== 'minor_node' ? (
|
||||
<div className="text-white/60 text-sm line-clamp-3 mb-3">
|
||||
{activeLocation.description}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-white/60 text-xs mb-3">
|
||||
{activeLocation.description === 'wind' ? 'Errichtung Leitungstrassen & Netzanbindung für Windpark-Infrastruktur.' :
|
||||
activeLocation.description === 'pv' ? 'Bau von Mittelspannungstrassen zur Einspeisung der PV-Anlage.' :
|
||||
activeLocation.description === 'fiber' ? 'Komplexer FTTx Breitbandausbau inkl. LWL-Montage & Tiefbau.' :
|
||||
activeLocation.description === 'power' ? '110kV Hochspannungstrasse Erdkabelverlegung.' :
|
||||
activeLocation.description === 'battery' ? 'Infrastrukturausbau für BESS (Batteriespeicher).' :
|
||||
'Komplexes Infrastrukturprojekt (Tiefbau & HDD).'}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{(activeLocation.details || activeLocation.type === 'minor_node') && (
|
||||
<ul className="mb-3 space-y-1.5 border-t border-white/10 pt-3">
|
||||
{activeLocation.type === 'minor_node' ? (
|
||||
<>
|
||||
<li className="text-[11px] text-white/80 flex items-start gap-2 font-medium">
|
||||
<CheckCircle2 className="w-3 h-3 text-primary shrink-0 mt-0.5" />
|
||||
<span>{
|
||||
activeLocation.description === 'wind' ? 'Netzanbindung Windpark' :
|
||||
activeLocation.description === 'pv' ? 'Einspeisung PV-Anlage' :
|
||||
activeLocation.description === 'fiber' ? 'FTTx Infrastruktur' :
|
||||
activeLocation.description === 'power' ? '110kV Trasse' :
|
||||
activeLocation.description === 'battery' ? 'BESS Anschluss' : 'Infrastrukturprojekt'
|
||||
}</span>
|
||||
</li>
|
||||
<li className="text-[11px] text-white/80 flex items-start gap-2 font-medium">
|
||||
<CheckCircle2 className="w-3 h-3 text-primary shrink-0 mt-0.5" />
|
||||
<span>Tiefbau & Spülbohrung (HDD)</span>
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
activeLocation.details?.map((detail, i) => (
|
||||
<li key={i} className="text-[11px] text-white/80 flex items-start gap-2 font-medium">
|
||||
<CheckCircle2 className="w-3 h-3 text-primary shrink-0 mt-0.5" />
|
||||
<span>{detail}</span>
|
||||
</li>
|
||||
))
|
||||
)}
|
||||
</ul>
|
||||
)}
|
||||
|
||||
{activeLocation.href && (
|
||||
<div className="inline-flex items-center text-xs font-bold text-primary">
|
||||
{locale === 'en' ? 'Learn more' : 'Zum Projekt'}
|
||||
<ArrowUpRight className="w-3.5 h-3.5 ml-1" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
102
components/blocks/ScaleOfImpact.tsx
Normal file
102
components/blocks/ScaleOfImpact.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
'use client';
|
||||
|
||||
import React, { useRef } from 'react';
|
||||
import { motion, useScroll, useTransform } from 'framer-motion';
|
||||
import { useLocale } from 'next-intl';
|
||||
|
||||
export function ScaleOfImpact() {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const locale = useLocale();
|
||||
|
||||
// Track scroll progress through this container
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: containerRef,
|
||||
offset: ["start end", "end start"]
|
||||
});
|
||||
|
||||
// Map scroll progress to SVG path length
|
||||
const pathLength = useTransform(scrollYProgress, [0.2, 0.8], [0, 1]);
|
||||
|
||||
// Opacity for the massive background numbers
|
||||
const bgOpacity = useTransform(scrollYProgress, [0.1, 0.4, 0.8, 1], [0, 0.1, 0.1, 0]);
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={containerRef}
|
||||
className="relative w-full min-h-[70vh] bg-[#050B14] flex flex-col items-center justify-center overflow-hidden border-y border-neutral-800"
|
||||
>
|
||||
{/* Massive Watermark Numbers */}
|
||||
<motion.div
|
||||
style={{ opacity: bgOpacity }}
|
||||
className="absolute inset-0 flex flex-col items-center justify-center pointer-events-none select-none overflow-hidden mix-blend-overlay"
|
||||
>
|
||||
<div className="font-heading font-black text-[20vw] leading-none text-white opacity-20 whitespace-nowrap">
|
||||
<span className="font-mono tracking-tighter">474.932</span>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
{/* Foreground Content */}
|
||||
<div className="relative z-10 container max-w-7xl mx-auto px-4 flex flex-col items-center text-center">
|
||||
|
||||
<h2 className="text-3xl md:text-5xl font-heading font-extrabold text-white mb-6 tracking-tight">
|
||||
{locale === 'en' ? (
|
||||
<>An infrastructure <br className="md:hidden"/> that connects the country.</>
|
||||
) : (
|
||||
<>Eine Infrastruktur, <br className="md:hidden"/> die das Land verbindet.</>
|
||||
)}
|
||||
</h2>
|
||||
|
||||
<p className="text-white/60 text-lg md:text-xl max-w-2xl font-medium mb-16">
|
||||
{locale === 'en'
|
||||
? "We don't just talk about the energy transition. We build it. In the last 36 months alone, we have completed a route that stretches from our headquarters in Guben all the way to Munich."
|
||||
: "Wir sprechen nicht nur über die Energiewende. Wir bauen sie. Allein in den letzten 36 Monaten haben wir eine Strecke realisiert, die von unserem Hauptsitz in Guben bis nach München reicht."
|
||||
}
|
||||
</p>
|
||||
|
||||
{/* Abstract SVG Line Animation */}
|
||||
<div className="w-full max-w-4xl h-32 relative">
|
||||
<svg
|
||||
width="100%"
|
||||
height="100%"
|
||||
viewBox="0 0 1000 100"
|
||||
preserveAspectRatio="none"
|
||||
className="absolute inset-0"
|
||||
>
|
||||
{/* Background dim line */}
|
||||
<path
|
||||
d="M0,50 Q250,0 500,50 T1000,50"
|
||||
fill="none"
|
||||
stroke="rgba(255,255,255,0.05)"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
{/* Glowing animated line */}
|
||||
<motion.path
|
||||
d="M0,50 Q250,0 500,50 T1000,50"
|
||||
fill="none"
|
||||
stroke="#82ED20" // primary color
|
||||
strokeWidth="4"
|
||||
style={{ pathLength }}
|
||||
className="drop-shadow-[0_0_15px_rgba(130,237,32,0.8)]"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* Static Data Grid (No jumping text) */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 md:gap-16 w-full max-w-4xl mt-12">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="font-mono text-5xl md:text-6xl font-black text-white tracking-tighter mb-2">100<span className="text-primary">+</span></div>
|
||||
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'Major Projects' : 'Großprojekte'}</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="font-mono text-5xl md:text-6xl font-black text-white tracking-tighter mb-2">372<span className="text-primary text-3xl">km</span></div>
|
||||
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'Cable Laying' : 'Kabelverlegung'}</div>
|
||||
</div>
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="font-mono text-5xl md:text-6xl font-black text-white tracking-tighter mb-2">102<span className="text-primary text-3xl">km</span></div>
|
||||
<div className="text-xs font-bold uppercase tracking-widest text-white/50">{locale === 'en' ? 'HDD Drilling' : 'Spülbohrung'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import Image from 'next/image';
|
||||
import { useLocale } from 'next-intl';
|
||||
import { ShieldCheck, Leaf, Lock, Accessibility, Zap, Mail, Phone } from 'lucide-react';
|
||||
import { LanguageSwitcher } from './LanguageSwitcher';
|
||||
|
||||
import { Tooltip } from '@/components/ui/Tooltip';
|
||||
interface CompanyInfo {
|
||||
contactEmail: string;
|
||||
contactPhone: string;
|
||||
@@ -165,10 +165,18 @@ export function Footer({ companyInfo }: FooterProps) {
|
||||
|
||||
{/* Quality Badges */}
|
||||
<div className="mt-4 md:mt-6 flex flex-wrap justify-center gap-x-4 gap-y-3 md:gap-x-8 md:gap-y-4 text-neutral-400 text-[10px] md:text-xs font-medium uppercase tracking-wider px-2">
|
||||
<div className="flex items-center gap-2"><ShieldCheck className="w-4 h-4 text-neutral-400" /><span>SSL Secured</span></div>
|
||||
<div className="flex items-center gap-2"><Leaf className="w-4 h-4 text-primary" /><span>Green Hosting</span></div>
|
||||
<div className="flex items-center gap-2"><Lock className="w-4 h-4 text-neutral-400" /><span>DSGVO Compliant</span></div>
|
||||
<div className="flex items-center gap-2"><Zap className="w-4 h-4 text-neutral-400" /><span>High Performance</span></div>
|
||||
<Tooltip content={locale === 'de' ? 'Ihre Daten werden sicher und verschlüsselt übertragen.' : 'Your data is transmitted securely and encrypted.'}>
|
||||
<div className="flex items-center gap-2 cursor-help"><ShieldCheck className="w-4 h-4 text-neutral-400" /><span>SSL Secured</span></div>
|
||||
</Tooltip>
|
||||
<Tooltip content={locale === 'de' ? 'Wir nutzen 100% Ökostrom für den Betrieb unserer Website.' : 'We use 100% green energy to run our website.'}>
|
||||
<div className="flex items-center gap-2 cursor-help"><Leaf className="w-4 h-4 text-primary" /><span>Green Hosting</span></div>
|
||||
</Tooltip>
|
||||
<Tooltip content={locale === 'de' ? 'Ihre Privatsphäre ist uns wichtig. Wir halten uns streng an den Datenschutz.' : 'Your privacy is important to us. We strictly adhere to data protection laws.'}>
|
||||
<div className="flex items-center gap-2 cursor-help"><Lock className="w-4 h-4 text-neutral-400" /><span>DSGVO Compliant</span></div>
|
||||
</Tooltip>
|
||||
<Tooltip content={locale === 'de' ? 'Blitzschnelle Ladezeiten für ein optimales Nutzererlebnis.' : 'Lightning-fast loading times for an optimal user experience.'}>
|
||||
<div className="flex items-center gap-2 cursor-help"><Zap className="w-4 h-4 text-neutral-400" /><span>High Performance</span></div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/* Mintel Design & Version */}
|
||||
|
||||
48
components/ui/AnimatedCounter.tsx
Normal file
48
components/ui/AnimatedCounter.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
'use client';
|
||||
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { motion, useMotionValue, useTransform, animate, useInView } from 'framer-motion';
|
||||
|
||||
interface AnimatedCounterProps {
|
||||
value: number;
|
||||
duration?: number;
|
||||
delay?: number;
|
||||
suffix?: string;
|
||||
prefix?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function AnimatedCounter({
|
||||
value,
|
||||
duration = 2,
|
||||
delay = 0,
|
||||
suffix = '',
|
||||
prefix = '',
|
||||
className = '',
|
||||
}: AnimatedCounterProps) {
|
||||
const count = useMotionValue(0);
|
||||
const rounded = useTransform(count, (latest) => {
|
||||
// Format with thousands separator
|
||||
return new Intl.NumberFormat('de-DE').format(Math.round(latest));
|
||||
});
|
||||
|
||||
const ref = React.useRef(null);
|
||||
const inView = useInView(ref, { once: true, margin: "-100px" });
|
||||
|
||||
useEffect(() => {
|
||||
if (inView) {
|
||||
const controls = animate(count, value, {
|
||||
duration: duration,
|
||||
delay: delay,
|
||||
ease: 'easeOut',
|
||||
});
|
||||
return controls.stop;
|
||||
}
|
||||
}, [inView, value, duration, delay, count]);
|
||||
|
||||
return (
|
||||
<motion.span ref={ref} className={className}>
|
||||
{prefix}<motion.span>{rounded}</motion.span>{suffix}
|
||||
</motion.span>
|
||||
);
|
||||
}
|
||||
19
components/ui/Tooltip.tsx
Normal file
19
components/ui/Tooltip.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import React, { ReactNode } from 'react';
|
||||
|
||||
interface TooltipProps {
|
||||
children: ReactNode;
|
||||
content: string;
|
||||
}
|
||||
|
||||
export function Tooltip({ children, content }: TooltipProps) {
|
||||
return (
|
||||
<div className="group relative flex items-center justify-center">
|
||||
{children}
|
||||
<div className="absolute bottom-full mb-3 invisible opacity-0 translate-y-2 group-hover:visible group-hover:opacity-100 group-hover:translate-y-0 w-max max-w-[250px] px-4 py-2.5 text-[11px] md:text-xs text-white bg-neutral-900/95 backdrop-blur-md rounded-xl shadow-2xl border border-white/10 transition-all duration-300 pointer-events-none z-50 text-center leading-relaxed font-normal normal-case tracking-normal">
|
||||
{content}
|
||||
{/* Triangle Arrow */}
|
||||
<div className="absolute left-1/2 top-full -translate-x-1/2 border-4 border-transparent border-t-neutral-900/95" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -7,5 +7,6 @@ export * from './Card';
|
||||
export * from './Badge';
|
||||
export * from './Input';
|
||||
export * from './Textarea';
|
||||
export * from './AnimatedCounter';
|
||||
export * from './Label';
|
||||
export * from './Callout';
|
||||
|
||||
@@ -29,6 +29,8 @@ layout: "fullBleed"
|
||||
Mit unserem spezialisierten Gerätepark beherrschen wir die unterschiedlichsten Verfahren. Beim **Horizontalspülbohrverfahren (HDD)** steuern wir den Bohrkopf punktgenau unter der Erde hindurch. Wir realisieren dabei Bohrlängen von bis zu 250 Metern am Stück und können Schutzrohre mit einem Durchmesser von bis zu 400 mm einziehen.
|
||||
|
||||
Für kürzere Distanzen, wie beispielsweise schnelle und schonende Hausanschlüsse, setzen wir unsere **Erdraketen** (Bodenverdrängungsverfahren) ein. Hierbei erreichen wir Durchörterungslängen von bis zu 15 Metern für Rohre bis 160 mm Durchmesser – ideal um Vorgärten und Einfahrten komplett unversehrt zu lassen.
|
||||
|
||||
<DeepDrillAnimation />
|
||||
</div>
|
||||
|
||||
<ServiceDetailGrid
|
||||
|
||||
@@ -143,5 +143,7 @@ description: "Die E-TIB GmbH ist Ihr zuverlässiger Partner für komplexe Kabelt
|
||||
]}
|
||||
/>
|
||||
|
||||
<ScaleOfImpact />
|
||||
|
||||
<HomeReferencesSlider />
|
||||
|
||||
|
||||
@@ -31,6 +31,8 @@ layout: "fullBleed"
|
||||
Durch unsere langjährige Erfahrung erkennen wir Problemstellungen frühzeitig und erarbeiten für unsere Auftraggeber im Vorfeld sichere und zufriedenstellende Lösungen. Die E-TIB GmbH hat sich voll und ganz auf den Kabelleitungstiefbau spezialisiert.
|
||||
|
||||
Wir bieten Ihnen das komplette Leistungsspektrum zur Errichtung von Kabeltrassen aus einer Hand – mit eigenem, hochmodernem Maschinenpark und festangestelltem Fachpersonal aus der Region. In direkter Zusammenarbeit mit unserem Partnerbüro, der E-TIB Ingenieurgesellschaft mbH, können wir zudem frühzeitig Planungsfehler ausschließen und selbst die komplexesten Dokumentationsanforderungen souverän erfüllen.
|
||||
|
||||
<DataGridPulse />
|
||||
</div>
|
||||
|
||||
<ServiceDetailGrid
|
||||
|
||||
@@ -52,9 +52,9 @@ layout: "fullBleed"
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CompanyTimeline />
|
||||
<InteractiveGermanyMap isHero={false} badge="Bundesweite Präsenz" title="Infrastruktur für ein ganzes Land" description="Seit 2023 haben wir in über 100 Projekten quer durch Deutschland bewiesen, dass wir Infrastrukturprojekte jeder Größenordnung verlässlich umsetzen." />
|
||||
|
||||
<InteractiveGermanyMap />
|
||||
<CompanyTimeline />
|
||||
|
||||
<div id="struktur">
|
||||
<HomeSubCompanyTiles
|
||||
|
||||
@@ -52,6 +52,8 @@ layout: "fullBleed"
|
||||
]}
|
||||
/>
|
||||
|
||||
<DeepDrillAnimation />
|
||||
|
||||
<CallToAction
|
||||
title="Looking for a trenchless solution?"
|
||||
text="We would be happy to advise you on the possibilities of horizontal directional drilling for your project."
|
||||
|
||||
@@ -139,4 +139,6 @@ description: "E-TIB GmbH is your reliable partner for complex cable routes, hori
|
||||
]}
|
||||
/>
|
||||
|
||||
<ScaleOfImpact />
|
||||
|
||||
<HomeReferencesSlider />
|
||||
|
||||
@@ -53,6 +53,8 @@ layout: "fullBleed"
|
||||
]}
|
||||
/>
|
||||
|
||||
<DataGridPulse />
|
||||
|
||||
<CallToAction
|
||||
title="Do you have a specific project?"
|
||||
text="We would be happy to advise you on all questions regarding cable civil engineering and line laying."
|
||||
|
||||
@@ -52,6 +52,8 @@ layout: "fullBleed"
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<InteractiveGermanyMap isHero={false} badge="Nationwide Presence" title="Infrastructure for an entire country" description="Since 2023, we have proven in over 100 projects across Germany that we reliably implement infrastructure projects of any scale." />
|
||||
|
||||
<CompanyTimeline
|
||||
badge="Our History"
|
||||
title="Milestones of Development"
|
||||
|
||||
@@ -40,6 +40,8 @@ services:
|
||||
NPM_TOKEN: ${NPM_TOKEN:-}
|
||||
CI: "true"
|
||||
WATCHPACK_POLLING: "true"
|
||||
ports:
|
||||
- "3001:3001"
|
||||
volumes:
|
||||
- .:/app
|
||||
- etib_node_modules:/app/node_modules
|
||||
|
||||
854
lib/map-data.ts
854
lib/map-data.ts
@@ -1,7 +1,7 @@
|
||||
export interface Location {
|
||||
id: string;
|
||||
name: string;
|
||||
type: 'hq' | 'branch' | 'project';
|
||||
type: 'hq' | 'branch' | 'project' | 'minor_node';
|
||||
x: number;
|
||||
y: number;
|
||||
description: string;
|
||||
@@ -16,7 +16,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Guben (Hauptsitz)',
|
||||
type: 'hq',
|
||||
x: 85,
|
||||
y: 48,
|
||||
y: 41.1,
|
||||
description: 'E-TIB GmbH Holding & Bohrtechnik GmbH',
|
||||
details: ['Zentrale Steuerung', 'Kabelleitungstiefbau', 'Maschinenpark'],
|
||||
},
|
||||
@@ -25,7 +25,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Bülstedt (Ingenieurgesellschaft)',
|
||||
type: 'branch',
|
||||
x: 37,
|
||||
y: 25,
|
||||
y: 25.33,
|
||||
description: 'E-TIB Ingenieurgesellschaft mbH',
|
||||
details: ['Planung & Projektierung', 'Vermessung', 'Dokumentation'],
|
||||
},
|
||||
@@ -34,7 +34,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Spreewald (FTTC)',
|
||||
type: 'project',
|
||||
x: 81,
|
||||
y: 42,
|
||||
y: 36.99,
|
||||
description: 'Breitbandausbau FTTC',
|
||||
href: '/referenzen/spreewald',
|
||||
},
|
||||
@@ -43,7 +43,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Bomlitz (FTTH)',
|
||||
type: 'project',
|
||||
x: 43,
|
||||
y: 30,
|
||||
y: 28.76,
|
||||
description: '88km Leitungstrasse (Tiefbau/HDD)',
|
||||
href: '/referenzen/bomlitz',
|
||||
},
|
||||
@@ -52,7 +52,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Forst (Kabeltrasse)',
|
||||
type: 'project',
|
||||
x: 87,
|
||||
y: 52,
|
||||
y: 43.85,
|
||||
description: 'Neubau MS-Kabeltrasse',
|
||||
href: '/referenzen/forst',
|
||||
},
|
||||
@@ -61,7 +61,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Eisenhüttenstadt (Kabel)',
|
||||
type: 'project',
|
||||
x: 86,
|
||||
y: 44,
|
||||
y: 38.36,
|
||||
description: 'Kabelverbindung U30 - T10',
|
||||
href: '/referenzen/eisenhuettenstadt',
|
||||
},
|
||||
@@ -70,7 +70,7 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Görne (PV-Anlage)',
|
||||
type: 'project',
|
||||
x: 65,
|
||||
y: 35,
|
||||
y: 32.19,
|
||||
description: 'Einspeisung PV-Anlage (MS-Kabel)',
|
||||
href: '/referenzen/goerne',
|
||||
},
|
||||
@@ -79,8 +79,844 @@ export const defaultLocations: Location[] = [
|
||||
name: 'Börde (FTTH-Ausbau)',
|
||||
type: 'project',
|
||||
x: 55,
|
||||
y: 38,
|
||||
y: 34.24,
|
||||
description: '109km Leitungstrasse für Breitband',
|
||||
href: '/referenzen/boerde',
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
export const minorLocations: Location[] = [
|
||||
{
|
||||
id: 'breddin-16845',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 63.88,
|
||||
y: 29.36,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'bad-liebenwerda-04924',
|
||||
name: 'Breitbandausbau / FTTx, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 73.76,
|
||||
y: 46.48,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'hünfelden-65597',
|
||||
name: 'Netzanbindung Windenergie, Rhein-Ruhr-Gebiet',
|
||||
type: 'minor_node',
|
||||
x: 29.35,
|
||||
y: 61.68,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'zachow-19376',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 68.62,
|
||||
y: 34.44,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'schnarup-thumby-24891',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 41.96,
|
||||
y: 7.31,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'bartow-17089',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 73.39,
|
||||
y: 17.66,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'regesbostel-21649',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 42.09,
|
||||
y: 23.17,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'bomlitz-29699',
|
||||
name: 'Breitbandausbau / FTTx, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 42.22,
|
||||
y: 29.09,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'berzhahn-56459',
|
||||
name: 'Netzanbindung Windenergie, Rhein-Ruhr-Gebiet',
|
||||
type: 'minor_node',
|
||||
x: 28.1,
|
||||
y: 58.9,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'oschersleben-39387',
|
||||
name: 'Breitbandausbau / FTTx, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 55.74,
|
||||
y: 40.14,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'jessen-06917',
|
||||
name: 'Netzanbindung Windenergie, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 70.21,
|
||||
y: 42.8,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'dettmannsdorf-18334',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 66.38,
|
||||
y: 14.04,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'werneck-97440',
|
||||
name: 'Netzanbindung Windenergie, Rhein-Main-Gebiet',
|
||||
type: 'minor_node',
|
||||
x: 45.73,
|
||||
y: 65.8,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'badendorf-23619',
|
||||
name: 'PV-Infrastrukturprojekt, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 49.91,
|
||||
y: 17.02,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'hordorf-39387',
|
||||
name: 'Breitbandausbau / FTTx, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 55.17,
|
||||
y: 40.57,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'neißemünde-15898',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 84.95,
|
||||
y: 39.9,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'wiesenhagen-14959',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 72.47,
|
||||
y: 38.31,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'gersdorf-09355',
|
||||
name: 'Netzanbindung Windenergie, Region Leipzig / Dresden',
|
||||
type: 'minor_node',
|
||||
x: 67.92,
|
||||
y: 56.13,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'nauen-14641',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 68.95,
|
||||
y: 32.81,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'eggersdorf-15374',
|
||||
name: 'PV-Infrastrukturprojekt, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 59.59,
|
||||
y: 40.82,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'guben-03172',
|
||||
name: 'Breitbandausbau / FTTx, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 84.55,
|
||||
y: 41.12,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'beratzhausen-93176',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 60.46,
|
||||
y: 76.77,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'felm-24161',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 45.58,
|
||||
y: 10.19,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'neukieritzsch-04575',
|
||||
name: 'Breitbandausbau / FTTx, Region Leipzig / Dresden',
|
||||
type: 'minor_node',
|
||||
x: 65.5,
|
||||
y: 51.2,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'oberbarnim-15377',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 79.52,
|
||||
y: 33.09,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'berne-27804',
|
||||
name: 'Netzanbindung Windenergie, Region Emsland / Ostfriesland',
|
||||
type: 'minor_node',
|
||||
x: 32.1,
|
||||
y: 25.85,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'dossow-16909',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 66.44,
|
||||
y: 26.41,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'krempe-25361',
|
||||
name: 'PV-Infrastrukturprojekt, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 40.7,
|
||||
y: 17.42,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'lübars-39291',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 73.45,
|
||||
y: 32.78,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'taarstedt-24893',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 42.4,
|
||||
y: 8.17,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'rom-19372',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 61.55,
|
||||
y: 22.35,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'bosbüll-25899',
|
||||
name: 'PV-Infrastrukturprojekt, Region Emsland / Ostfriesland',
|
||||
type: 'minor_node',
|
||||
x: 35.36,
|
||||
y: 5,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'schwarzhofen-92447',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 64.76,
|
||||
y: 73.46,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'göhlsdorf-14797',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 68.78,
|
||||
y: 35.98,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'zehdenick-16792',
|
||||
name: 'Trassenbau Hochspannung, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 73.35,
|
||||
y: 28.02,
|
||||
description: 'power',
|
||||
},
|
||||
{
|
||||
id: 'osterburg-39606',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 59.63,
|
||||
y: 30.48,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'holzheim-89438',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 49.58,
|
||||
y: 84.44,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'adelschlag-85111',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 55.23,
|
||||
y: 80.23,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'hoyerswerda-02977',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 80.8,
|
||||
y: 47.74,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'niederhummel-85416',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 60.98,
|
||||
y: 85.4,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'löffingen-79843',
|
||||
name: 'PV-Infrastrukturprojekt, Region Schwarzwald / Bodensee',
|
||||
type: 'minor_node',
|
||||
x: 31.06,
|
||||
y: 92.31,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'holste-27729',
|
||||
name: 'Netzanbindung Windenergie, Region Emsland / Ostfriesland',
|
||||
type: 'minor_node',
|
||||
x: 35.35,
|
||||
y: 23.24,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'lasbek-23847',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 48.1,
|
||||
y: 18.71,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'bernau-bei-berlin-16321',
|
||||
name: 'Netzanbindung Windenergie, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 75.39,
|
||||
y: 31.83,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'gorgast-15328',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 83.44,
|
||||
y: 33.39,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'neustadt-dosse-16845',
|
||||
name: 'Netzanbindung Windenergie, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 65.82,
|
||||
y: 29.83,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'halle-06132',
|
||||
name: 'Breitbandausbau / FTTx, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 61.88,
|
||||
y: 47.76,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'letschin-15324',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 82.02,
|
||||
y: 32.11,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'sallgast-03238',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 77.65,
|
||||
y: 45.69,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'rodleben-dessau-roßlau-06861',
|
||||
name: 'Breitbandausbau / FTTx, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 63.69,
|
||||
y: 41.69,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'gerbstedt-06347',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 58.88,
|
||||
y: 45.36,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'elsterwerda-04910',
|
||||
name: 'Breitbandausbau / FTTx, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 74.88,
|
||||
y: 47.26,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'magdeburg-39106',
|
||||
name: 'PV-Infrastrukturprojekt, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 59.01,
|
||||
y: 38.7,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'staßfurt-39443',
|
||||
name: 'BESS-Anbindung, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 58.97,
|
||||
y: 41.85,
|
||||
description: 'battery',
|
||||
},
|
||||
{
|
||||
id: 'alsleben-06425',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 59.15,
|
||||
y: 44.01,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'nienbüttel-25596',
|
||||
name: 'PV-Infrastrukturprojekt, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 40.06,
|
||||
y: 14.97,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'werneuchen-16356',
|
||||
name: 'Netzanbindung Windenergie, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 76.31,
|
||||
y: 32.58,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'stüdenitz-schönermark-16845',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 64.43,
|
||||
y: 29.18,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'gumtow-16866',
|
||||
name: 'Netzanbindung Windenergie, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 64.12,
|
||||
y: 28.2,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'nöbdenitz-04626',
|
||||
name: 'Breitbandausbau / FTTx, Region Leipzig / Dresden',
|
||||
type: 'minor_node',
|
||||
x: 64.59,
|
||||
y: 54.41,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'kröpelin-18236',
|
||||
name: 'Netzanbindung Windenergie, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 60.24,
|
||||
y: 14.56,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'laer-48366',
|
||||
name: 'Netzanbindung Windenergie, Region Münsterland',
|
||||
type: 'minor_node',
|
||||
x: 22.68,
|
||||
y: 39.78,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'ostbevern-48346',
|
||||
name: 'Netzanbindung Windenergie, Region Münsterland',
|
||||
type: 'minor_node',
|
||||
x: 26.64,
|
||||
y: 39.84,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'schwarmstedt-29690',
|
||||
name: 'Breitbandausbau / FTTx, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 41.89,
|
||||
y: 31.93,
|
||||
description: 'fiber',
|
||||
},
|
||||
{
|
||||
id: 'prötzel-15345',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 78.84,
|
||||
y: 32.5,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'blindheim-89434',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 50.23,
|
||||
y: 82.72,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'großräschen-01983',
|
||||
name: 'Netzanbindung Windenergie, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 78.82,
|
||||
y: 45.64,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'wolkenstein-09429',
|
||||
name: 'Netzanbindung Windenergie, Region Leipzig / Dresden',
|
||||
type: 'minor_node',
|
||||
x: 71.1,
|
||||
y: 57.44,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'fronhausen-35112',
|
||||
name: 'Netzanbindung Windenergie, Rhein-Ruhr-Gebiet',
|
||||
type: 'minor_node',
|
||||
x: 34.1,
|
||||
y: 56.83,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'dammfleth-25554',
|
||||
name: 'Netzanbindung Windenergie, Region Emsland / Ostfriesland',
|
||||
type: 'minor_node',
|
||||
x: 39.62,
|
||||
y: 16.66,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'langwedel-24631',
|
||||
name: 'PV-Infrastrukturprojekt, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 44.46,
|
||||
y: 12.6,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'jerchel-14715',
|
||||
name: 'PV-Infrastrukturprojekt, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 56.22,
|
||||
y: 34.63,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'beeskow-15848',
|
||||
name: 'Netzanbindung Windenergie, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 80.9,
|
||||
y: 38.43,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'perleberg-19348',
|
||||
name: 'Netzanbindung Windenergie, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 60.84,
|
||||
y: 26.25,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'gilching-82205',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 55.84,
|
||||
y: 89.45,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'bodenwöhr-92439',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 64.41,
|
||||
y: 74.55,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'görne-14728',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 66.34,
|
||||
y: 31.66,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'agethorst-25560',
|
||||
name: 'PV-Infrastrukturprojekt, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 40.21,
|
||||
y: 15.07,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'ansbach-91522',
|
||||
name: 'Netzanbindung Windenergie, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 49.8,
|
||||
y: 74.59,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'schinne-39579',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 59.69,
|
||||
y: 32.23,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'neuengörs-23818',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 48.33,
|
||||
y: 16.63,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'denkendorf-85095',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 57.48,
|
||||
y: 79.18,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'lindhorst-31698',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 38.98,
|
||||
y: 35.98,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'rohrenfels-86701',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 54.89,
|
||||
y: 82.18,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'ingoldingen-88456',
|
||||
name: 'PV-Infrastrukturprojekt, Region Schwarzwald / Bodensee',
|
||||
type: 'minor_node',
|
||||
x: 42.75,
|
||||
y: 90.62,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'lichtenau-33165',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 35.64,
|
||||
y: 45.44,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'nochten-02943',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 84.03,
|
||||
y: 47.68,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'dalkendorf-17166',
|
||||
name: 'Netzanbindung Windenergie, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 66.23,
|
||||
y: 17.67,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'schopfheim-79650',
|
||||
name: 'Netzanbindung Windenergie, Region Schwarzwald / Bodensee',
|
||||
type: 'minor_node',
|
||||
x: 26.98,
|
||||
y: 94.96,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'lunow-stolzenhagen-16248',
|
||||
name: 'Trassenbau Hochspannung, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 79.88,
|
||||
y: 28.84,
|
||||
description: 'power',
|
||||
},
|
||||
{
|
||||
id: 'petershagen-15326',
|
||||
name: 'PV-Infrastrukturprojekt, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 36.26,
|
||||
y: 35.79,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'krevese-39606',
|
||||
name: 'Netzanbindung Windenergie, Region Hannover / Braunschweig',
|
||||
type: 'minor_node',
|
||||
x: 59.37,
|
||||
y: 30.29,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'seckeritz-17440',
|
||||
name: 'PV-Infrastrukturprojekt, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 76.91,
|
||||
y: 15.43,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'tempelfelde-16230',
|
||||
name: 'Netzanbindung Windenergie, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 76.55,
|
||||
y: 31.59,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'altenmedingen-29575',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 50.28,
|
||||
y: 26.09,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'neiße-malxetal-03159',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 84.5,
|
||||
y: 45.15,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'eisenhüttenstadt-15890',
|
||||
name: 'PV-Infrastrukturprojekt, Region Berlin / Brandenburg',
|
||||
type: 'minor_node',
|
||||
x: 84.27,
|
||||
y: 38.7,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'groß-pankow-16928',
|
||||
name: 'Netzanbindung Windenergie, Region Mecklenburg-Vorpommern',
|
||||
type: 'minor_node',
|
||||
x: 62.41,
|
||||
y: 26.45,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'dahlhausen-16909',
|
||||
name: 'PV-Infrastrukturprojekt, Rhein-Ruhr-Gebiet',
|
||||
type: 'minor_node',
|
||||
x: 22.21,
|
||||
y: 50.39,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'gnarrenburg-27442',
|
||||
name: 'Netzanbindung Windenergie, Region Emsland / Ostfriesland',
|
||||
type: 'minor_node',
|
||||
x: 36.74,
|
||||
y: 23.17,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'greding-91171',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 56.38,
|
||||
y: 77.43,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'scheeßel-27383',
|
||||
name: 'Netzanbindung Windenergie, Metropolregion Hamburg',
|
||||
type: 'minor_node',
|
||||
x: 40.7,
|
||||
y: 25.88,
|
||||
description: 'wind',
|
||||
},
|
||||
{
|
||||
id: 'egling-an-der-paar-86492',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 53.41,
|
||||
y: 88.51,
|
||||
description: 'pv',
|
||||
},
|
||||
{
|
||||
id: 'ellingen-91792',
|
||||
name: 'PV-Infrastrukturprojekt, Großraum Stuttgart / Franken',
|
||||
type: 'minor_node',
|
||||
x: 52.92,
|
||||
y: 77.37,
|
||||
description: 'pv',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface ReferenceFrontmatter {
|
||||
dateString?: string;
|
||||
featuredImage?: string | null;
|
||||
location: string;
|
||||
category?: string | string[];
|
||||
}
|
||||
|
||||
export interface ReferenceData {
|
||||
|
||||
5
test-build-env.js
Normal file
5
test-build-env.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const val = process.env.NEXT_PUBLIC_APP_VERSION;
|
||||
console.log("val is:", val);
|
||||
if (val) {
|
||||
console.log("replace:", val.replace(/^v/, ''));
|
||||
}
|
||||
Reference in New Issue
Block a user