kleinigkeiten und dropdownmenu
This commit is contained in:
parent
36067596e6
commit
1be8b2e9bd
|
|
@ -1,5 +1,6 @@
|
||||||
import { Card, CardContent } from "@/components/ui/card";
|
import { Card, CardContent } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
import {
|
import {
|
||||||
Mail,
|
Mail,
|
||||||
Phone,
|
Phone,
|
||||||
|
|
@ -52,29 +53,63 @@ const Footer = () => {
|
||||||
<h3 className="text-lg font-semibold">Schnellzugriff</h3>
|
<h3 className="text-lg font-semibold">Schnellzugriff</h3>
|
||||||
<ul className="space-y-2 text-sm">
|
<ul className="space-y-2 text-sm">
|
||||||
<li>
|
<li>
|
||||||
<a href="/" className="text-gray-300 hover:text-white transition-colors">
|
<Link
|
||||||
|
to="/solar"
|
||||||
|
className="text-gray-300 hover:text-white transition-colors"
|
||||||
|
onClick={() => window.scrollTo(0, 0)}
|
||||||
|
>
|
||||||
Solar-Installation
|
Solar-Installation
|
||||||
</a>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/" className="text-gray-300 hover:text-white transition-colors">
|
<Link
|
||||||
|
to="/wind"
|
||||||
|
className="text-gray-300 hover:text-white transition-colors"
|
||||||
|
onClick={() => window.scrollTo(0, 0)}
|
||||||
|
>
|
||||||
Windenergie
|
Windenergie
|
||||||
</a>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/" className="text-gray-300 hover:text-white transition-colors">
|
<Link to="/installateur-finden" className="text-gray-300 hover:text-white transition-colors">
|
||||||
Installateur finden
|
Installateur finden
|
||||||
</a>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/" className="text-gray-300 hover:text-white transition-colors">
|
<Link
|
||||||
Förderungen 2025
|
to="/solar"
|
||||||
</a>
|
className="text-gray-300 hover:text-white transition-colors"
|
||||||
|
onClick={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const calculatorElement = document.querySelector('[data-calculator]') ||
|
||||||
|
document.querySelector('.calculator') ||
|
||||||
|
document.querySelector('h2');
|
||||||
|
if (calculatorElement) {
|
||||||
|
calculatorElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Solar-Kostenrechner
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="/" className="text-gray-300 hover:text-white transition-colors">
|
<Link
|
||||||
Kostenrechner
|
to="/wind"
|
||||||
</a>
|
className="text-gray-300 hover:text-white transition-colors"
|
||||||
|
onClick={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const calculatorElement = document.querySelector('[data-calculator]') ||
|
||||||
|
document.querySelector('.calculator') ||
|
||||||
|
document.querySelector('h2');
|
||||||
|
if (calculatorElement) {
|
||||||
|
calculatorElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Wind-Kostenrechner
|
||||||
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ const HeroSection = () => {
|
||||||
|
|
||||||
{/* Content */}
|
{/* Content */}
|
||||||
<div className="container mx-auto px-4 relative z-10">
|
<div className="container mx-auto px-4 relative z-10">
|
||||||
<div className="max-w-2xl text-white">
|
<div className="max-w-4xl text-white">
|
||||||
{/* Clean headline with subtle color accents */}
|
{/* Clean headline with subtle color accents */}
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
|
<h1 className="text-4xl md:text-5xl lg:text-6xl font-bold leading-tight">
|
||||||
|
|
@ -47,30 +47,50 @@ const HeroSection = () => {
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Clean search box */}
|
{/* Clean search box */}
|
||||||
<div className="bg-white/15 backdrop-blur-sm border border-white/30 rounded-2xl p-6 mb-8">
|
<div className="bg-white/15 backdrop-blur-sm border border-white/30 rounded-2xl px-12 py-8 mb-8 max-w-4xl mx-auto">
|
||||||
<div className="flex flex-col md:flex-row gap-4">
|
<div className="flex flex-col md:flex-row gap-6">
|
||||||
<div className="flex-1 relative group">
|
<div className="flex-1 relative group min-w-0">
|
||||||
<MapPin className="absolute left-3 top-1/2 transform -translate-y-1/2 text-cyan-200 w-5 h-5" />
|
<MapPin className="absolute left-3 top-1/2 transform -translate-y-1/2 text-cyan-200 w-5 h-5 z-10" />
|
||||||
<Input
|
<select className="pl-10 bg-white border-gray-300 text-gray-900 h-12 w-full rounded-md border px-3 py-2 text-sm focus:border-cyan-200 focus:ring-2 focus:ring-cyan-200/20 focus:outline-none min-w-[200px]">
|
||||||
placeholder="PLZ oder Stadt eingeben..."
|
<option value="">Bundesland wählen</option>
|
||||||
className="pl-10 bg-white/20 border-white/30 text-white placeholder:text-white/70 h-12 focus:border-cyan-200 focus:ring-cyan-200/20 transition-all duration-300"
|
<option value="all">Alle Bundesländer</option>
|
||||||
/>
|
<option value="Baden-Württemberg">Baden-Württemberg</option>
|
||||||
|
<option value="Bayern">Bayern</option>
|
||||||
|
<option value="Berlin">Berlin</option>
|
||||||
|
<option value="Brandenburg">Brandenburg</option>
|
||||||
|
<option value="Bremen">Bremen</option>
|
||||||
|
<option value="Hamburg">Hamburg</option>
|
||||||
|
<option value="Hessen">Hessen</option>
|
||||||
|
<option value="Mecklenburg-Vorpommern">Mecklenburg-Vorpommern</option>
|
||||||
|
<option value="Niedersachsen">Niedersachsen</option>
|
||||||
|
<option value="Nordrhein-Westfalen">Nordrhein-Westfalen</option>
|
||||||
|
<option value="Rheinland-Pfalz">Rheinland-Pfalz</option>
|
||||||
|
<option value="Saarland">Saarland</option>
|
||||||
|
<option value="Sachsen">Sachsen</option>
|
||||||
|
<option value="Sachsen-Anhalt">Sachsen-Anhalt</option>
|
||||||
|
<option value="Schleswig-Holstein">Schleswig-Holstein</option>
|
||||||
|
<option value="Thüringen">Thüringen</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 relative group">
|
<div className="flex-1 relative group min-w-0">
|
||||||
<Zap className="absolute left-3 top-1/2 transform -translate-y-1/2 text-yellow-200 w-5 h-5" />
|
<Zap className="absolute left-3 top-1/2 transform -translate-y-1/2 text-yellow-200 w-5 h-5 z-10" />
|
||||||
<select className="w-full h-12 pl-10 pr-4 bg-white/20 border-white/30 rounded-lg text-white appearance-none focus:border-yellow-200 focus:ring-yellow-200/20 transition-all duration-300">
|
<select className="pl-10 bg-white border-gray-300 text-gray-900 h-12 w-full rounded-md border px-3 py-2 text-sm focus:border-yellow-200 focus:ring-2 focus:ring-yellow-200/20 focus:outline-none min-w-[200px]">
|
||||||
<option value="">Energieart wählen</option>
|
<option value="">Energieart wählen</option>
|
||||||
|
<option value="all">Alle Energiearten</option>
|
||||||
<option value="solar">Solar</option>
|
<option value="solar">Solar</option>
|
||||||
<option value="wind">Wind</option>
|
<option value="wind">Wind</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
|
asChild
|
||||||
variant="hero"
|
variant="hero"
|
||||||
size="lg"
|
size="lg"
|
||||||
className="bg-cyan-600 hover:bg-cyan-700 text-white border-0 shadow-lg hover:shadow-xl transition-all duration-300"
|
className="bg-cyan-600 hover:bg-cyan-700 text-white border-0 shadow-lg hover:shadow-xl transition-all duration-300"
|
||||||
>
|
>
|
||||||
<Search className="w-5 h-5 mr-2" />
|
<Link to="/installateur-finden">
|
||||||
Installateur Finden
|
<Search className="w-5 h-5 mr-2" />
|
||||||
|
Installateur Finden
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -80,15 +100,11 @@ const HeroSection = () => {
|
||||||
{/* Clean floating stats */}
|
{/* Clean floating stats */}
|
||||||
<div className="absolute bottom-8 right-8 hidden xl:block">
|
<div className="absolute bottom-8 right-8 hidden xl:block">
|
||||||
<div className="bg-white/20 backdrop-blur-sm border border-white/30 rounded-2xl p-6 text-white shadow-lg">
|
<div className="bg-white/20 backdrop-blur-sm border border-white/30 rounded-2xl p-6 text-white shadow-lg">
|
||||||
<div className="grid grid-cols-3 gap-6 text-center">
|
<div className="grid grid-cols-2 gap-6 text-center">
|
||||||
<div>
|
<div>
|
||||||
<div className="text-3xl font-bold text-yellow-200">500+</div>
|
<div className="text-3xl font-bold text-yellow-200">60+</div>
|
||||||
<div className="text-sm text-white/90 font-medium">Installateure</div>
|
<div className="text-sm text-white/90 font-medium">Installateure</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<div className="text-3xl font-bold text-cyan-200">2,500+</div>
|
|
||||||
<div className="text-sm text-white/90 font-medium">Projekte</div>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<div className="text-3xl font-bold text-green-200">4.8★</div>
|
<div className="text-3xl font-bold text-green-200">4.8★</div>
|
||||||
<div className="text-sm text-white/90 font-medium">Bewertung</div>
|
<div className="text-sm text-white/90 font-medium">Bewertung</div>
|
||||||
|
|
@ -98,19 +114,14 @@ const HeroSection = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* SEO: Additional content section for better indexing */}
|
{/* SEO: Additional content section for better indexing */}
|
||||||
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent py-8 hidden lg:block">
|
<div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/60 to-transparent py-3 hidden lg:block">
|
||||||
<div className="container mx-auto px-4">
|
<div className="container mx-auto px-4">
|
||||||
<div className="grid grid-cols-3 gap-8 text-white/90">
|
<div className="grid grid-cols-2 gap-8 text-white/90 max-w-2xl mx-auto">
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Calculator className="w-8 h-8 mx-auto mb-2 text-yellow-300" />
|
<Calculator className="w-8 h-8 mx-auto mb-2 text-yellow-300" />
|
||||||
<h3 className="font-semibold mb-1">Kostenlose Rechner</h3>
|
<h3 className="font-semibold mb-1">Kostenlose Rechner</h3>
|
||||||
<p className="text-sm">Solar- und Windenergie berechnen</p>
|
<p className="text-sm">Solar- und Windenergie berechnen</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="text-center">
|
|
||||||
<Award className="w-8 h-8 mx-auto mb-2 text-cyan-300" />
|
|
||||||
<h3 className="font-semibold mb-1">Förderprogramme</h3>
|
|
||||||
<p className="text-sm">BAFA, KfW & kommunale Zuschüsse</p>
|
|
||||||
</div>
|
|
||||||
<div className="text-center">
|
<div className="text-center">
|
||||||
<Shield className="w-8 h-8 mx-auto mb-2 text-green-300" />
|
<Shield className="w-8 h-8 mx-auto mb-2 text-green-300" />
|
||||||
<h3 className="font-semibold mb-1">Verifizierte Experten</h3>
|
<h3 className="font-semibold mb-1">Verifizierte Experten</h3>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import React, { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
||||||
import { HelpCircle } from 'lucide-react';
|
import { HelpCircle } from 'lucide-react';
|
||||||
import { analyticsService, quoteService } from '@/lib/database';
|
import { analyticsService, quoteService } from '@/lib/database';
|
||||||
|
|
||||||
|
|
@ -290,17 +289,16 @@ const SolarCalculator = () => {
|
||||||
Dachtyp
|
Dachtyp
|
||||||
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
||||||
</label>
|
</label>
|
||||||
<Select value={roofType} onValueChange={setRoofType}>
|
<select
|
||||||
<SelectTrigger className="h-12 border-2 border-gray-200">
|
value={roofType}
|
||||||
<SelectValue />
|
onChange={(e) => setRoofType(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-12 w-full rounded-md border-2 border-gray-200 bg-white px-3 py-2 text-sm focus:border-blue-500 focus:outline-none"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="asphalt">Ziegeldach</SelectItem>
|
<option value="asphalt">Ziegeldach</option>
|
||||||
<SelectItem value="tile">Tonziegel</SelectItem>
|
<option value="tile">Tonziegel</option>
|
||||||
<SelectItem value="metal">Metalldach</SelectItem>
|
<option value="metal">Metalldach</option>
|
||||||
<SelectItem value="flat">Flachdach</SelectItem>
|
<option value="flat">Flachdach</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
@ -314,18 +312,17 @@ const SolarCalculator = () => {
|
||||||
Tägliche Sonnenstunden
|
Tägliche Sonnenstunden
|
||||||
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
||||||
</label>
|
</label>
|
||||||
<Select value={sunlightHours} onValueChange={setSunlightHours}>
|
<select
|
||||||
<SelectTrigger className="h-12 border-2 border-gray-200">
|
value={sunlightHours}
|
||||||
<SelectValue />
|
onChange={(e) => setSunlightHours(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-12 w-full rounded-md border-2 border-gray-200 bg-white px-3 py-2 text-sm focus:border-blue-500 focus:outline-none"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="4">4 Stunden (Weniger sonnige Gebiete)</SelectItem>
|
<option value="4">4 Stunden (Weniger sonnige Gebiete)</option>
|
||||||
<SelectItem value="5">5 Stunden (Mäßige Sonne)</SelectItem>
|
<option value="5">5 Stunden (Mäßige Sonne)</option>
|
||||||
<SelectItem value="6">6 Stunden (Gute Sonneneinstrahlung)</SelectItem>
|
<option value="6">6 Stunden (Gute Sonneneinstrahlung)</option>
|
||||||
<SelectItem value="7">7 Stunden (Sehr sonnig)</SelectItem>
|
<option value="7">7 Stunden (Sehr sonnig)</option>
|
||||||
<SelectItem value="8">8+ Stunden (Ausgezeichnete Sonne)</SelectItem>
|
<option value="8">8+ Stunden (Ausgezeichnete Sonne)</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import React, { useState, useEffect } from 'react';
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
|
||||||
import { HelpCircle, Wind, Zap } from 'lucide-react';
|
import { HelpCircle, Wind, Zap } from 'lucide-react';
|
||||||
import { analyticsService } from '@/lib/database';
|
import { analyticsService } from '@/lib/database';
|
||||||
|
|
||||||
|
|
@ -285,17 +284,16 @@ const WindCalculator = () => {
|
||||||
Grundstücksart
|
Grundstücksart
|
||||||
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
||||||
</label>
|
</label>
|
||||||
<Select value={zoning} onValueChange={setZoning}>
|
<select
|
||||||
<SelectTrigger className="h-12 border-2 border-green-200">
|
value={zoning}
|
||||||
<SelectValue />
|
onChange={(e) => setZoning(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-12 w-full rounded-md border-2 border-green-200 bg-white px-3 py-2 text-sm focus:border-emerald-500 focus:outline-none"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="rural">Ländlich</SelectItem>
|
<option value="rural">Ländlich</option>
|
||||||
<SelectItem value="suburban">Vorstädtisch</SelectItem>
|
<option value="suburban">Vorstädtisch</option>
|
||||||
<SelectItem value="urban">Städtisch</SelectItem>
|
<option value="urban">Städtisch</option>
|
||||||
<SelectItem value="agricultural">Landwirtschaftlich</SelectItem>
|
<option value="agricultural">Landwirtschaftlich</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|
@ -309,18 +307,17 @@ const WindCalculator = () => {
|
||||||
Durchschnittliche Windgeschwindigkeit (km/h)
|
Durchschnittliche Windgeschwindigkeit (km/h)
|
||||||
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
||||||
</label>
|
</label>
|
||||||
<Select value={windSpeed} onValueChange={setWindSpeed}>
|
<select
|
||||||
<SelectTrigger className="h-12 border-2 border-green-200">
|
value={windSpeed}
|
||||||
<SelectValue />
|
onChange={(e) => setWindSpeed(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-12 w-full rounded-md border-2 border-green-200 bg-white px-3 py-2 text-sm focus:border-emerald-500 focus:outline-none"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="8">13 km/h (Schwache Windzone)</SelectItem>
|
<option value="8">13 km/h (Schwache Windzone)</option>
|
||||||
<SelectItem value="10">16 km/h (Mäßiger Wind)</SelectItem>
|
<option value="10">16 km/h (Mäßiger Wind)</option>
|
||||||
<SelectItem value="12">19 km/h (Gute Windressource)</SelectItem>
|
<option value="12">19 km/h (Gute Windressource)</option>
|
||||||
<SelectItem value="15">24 km/h (Ausgezeichneter Wind)</SelectItem>
|
<option value="15">24 km/h (Ausgezeichneter Wind)</option>
|
||||||
<SelectItem value="18">29+ km/h (Hervorragender Wind)</SelectItem>
|
<option value="18">29+ km/h (Hervorragender Wind)</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -328,18 +325,17 @@ const WindCalculator = () => {
|
||||||
Max. erlaubte Anlagenhöhe (m)
|
Max. erlaubte Anlagenhöhe (m)
|
||||||
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
<HelpCircle className="inline w-4 h-4 ml-1 text-gray-400" />
|
||||||
</label>
|
</label>
|
||||||
<Select value={turbineHeight} onValueChange={setTurbineHeight}>
|
<select
|
||||||
<SelectTrigger className="h-12 border-2 border-green-200">
|
value={turbineHeight}
|
||||||
<SelectValue />
|
onChange={(e) => setTurbineHeight(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-12 w-full rounded-md border-2 border-green-200 bg-white px-3 py-2 text-sm focus:border-emerald-500 focus:outline-none"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="40">12 m (Eingeschränkte Gebiete)</SelectItem>
|
<option value="40">12 m (Eingeschränkte Gebiete)</option>
|
||||||
<SelectItem value="60">18 m (Vorstädtisches Limit)</SelectItem>
|
<option value="60">18 m (Vorstädtisches Limit)</option>
|
||||||
<SelectItem value="80">24 m (Standard Wohngebiet)</SelectItem>
|
<option value="80">24 m (Standard Wohngebiet)</option>
|
||||||
<SelectItem value="100">30 m (Ländliche Gebiete)</SelectItem>
|
<option value="100">30 m (Ländliche Gebiete)</option>
|
||||||
<SelectItem value="120">36+ m (Keine Beschränkungen)</SelectItem>
|
<option value="120">36+ m (Keine Beschränkungen)</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -73,9 +73,9 @@ const SelectContent = React.forwardRef<
|
||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md [&]:!transition-none [&]:!duration-0 [&]:!animate-none",
|
||||||
position === "popper" &&
|
position === "popper" &&
|
||||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
"",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
position={position}
|
position={position}
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ const Index = () => {
|
||||||
{/* SEO: Rich content section for better indexing */}
|
{/* SEO: Rich content section for better indexing */}
|
||||||
<section className="py-16 bg-gradient-to-b from-background to-secondary/10">
|
<section className="py-16 bg-gradient-to-b from-background to-secondary/10">
|
||||||
<div className="container mx-auto px-4">
|
<div className="container mx-auto px-4">
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8 mb-12">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12 max-w-4xl mx-auto">
|
||||||
{/* SEO Content Block 1: Installateur finden */}
|
{/* SEO Content Block 1: Installateur finden */}
|
||||||
<Card className="border-l-4 border-l-orange-500">
|
<Card className="border-l-4 border-l-orange-500">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
|
@ -191,37 +191,7 @@ const Index = () => {
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* SEO Content Block 2: Förderprogramme */}
|
{/* SEO Content Block 2: Regionale Expertise */}
|
||||||
<Card className="border-l-4 border-l-green-500">
|
|
||||||
<CardHeader>
|
|
||||||
<CardTitle className="flex items-center gap-2 text-green-700">
|
|
||||||
<Award className="w-5 h-5" />
|
|
||||||
Förderprogramme 2025
|
|
||||||
</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent>
|
|
||||||
<p className="text-muted-foreground mb-4">
|
|
||||||
Aktuelle Förderungen für erneuerbare Energien: BAFA, KfW und kommunale
|
|
||||||
Zuschüsse je nach Bundesland und Projektgröße.
|
|
||||||
</p>
|
|
||||||
<div className="space-y-2 text-sm">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<CheckCircle className="w-4 h-4 text-green-600" />
|
|
||||||
<span>BAFA bis 500€ für Balkonkraftwerke</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<CheckCircle className="w-4 h-4 text-green-600" />
|
|
||||||
<span>KfW-Kredite mit Tilgungszuschuss</span>
|
|
||||||
</div>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<CheckCircle className="w-4 h-4 text-green-600" />
|
|
||||||
<span>Kommunale Förderprogramme</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* SEO Content Block 3: Regionale Expertise */}
|
|
||||||
<Card className="border-l-4 border-l-blue-500">
|
<Card className="border-l-4 border-l-blue-500">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<CardTitle className="flex items-center gap-2 text-blue-700">
|
<CardTitle className="flex items-center gap-2 text-blue-700">
|
||||||
|
|
@ -271,13 +241,6 @@ const Index = () => {
|
||||||
regionale Expertise vergleichen. Lokale Installateure kennen die regionalen Vorgaben.
|
regionale Expertise vergleichen. Lokale Installateure kennen die regionalen Vorgaben.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="bg-white p-6 rounded-lg shadow-sm">
|
|
||||||
<h3 className="font-semibold mb-3 text-lg">Welche Förderungen gibt es 2025?</h3>
|
|
||||||
<p className="text-muted-foreground">
|
|
||||||
BAFA-Förderung für Balkonkraftwerke (bis 500€), KfW-Kredite mit Tilgungszuschuss,
|
|
||||||
EEG-Vergütung für Überschussstrom und kommunale Zuschüsse je nach Bundesland.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-white p-6 rounded-lg shadow-sm">
|
<div className="bg-white p-6 rounded-lg shadow-sm">
|
||||||
<h3 className="font-semibold mb-3 text-lg">Was kostet eine Solar- oder Windanlage?</h3>
|
<h3 className="font-semibold mb-3 text-lg">Was kostet eine Solar- oder Windanlage?</h3>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
|
|
@ -309,7 +272,21 @@ const Index = () => {
|
||||||
Berechnen Sie Ihre Solareinsparungen und vergleichen Sie Angebote
|
Berechnen Sie Ihre Solareinsparungen und vergleichen Sie Angebote
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" className="w-full" asChild>
|
<Button variant="outline" className="w-full" asChild>
|
||||||
<Link to="/solar">Zum Solarrechner</Link>
|
<Link
|
||||||
|
to="/solar"
|
||||||
|
onClick={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const calculatorElement = document.querySelector('[data-calculator]') ||
|
||||||
|
document.querySelector('.calculator') ||
|
||||||
|
document.querySelector('h2');
|
||||||
|
if (calculatorElement) {
|
||||||
|
calculatorElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Zum Solarrechner
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="text-center p-8 hover:shadow-lg transition-shadow">
|
<Card className="text-center p-8 hover:shadow-lg transition-shadow">
|
||||||
|
|
@ -319,7 +296,21 @@ const Index = () => {
|
||||||
Windenergie berechnen: Ertrag, Kosten & Angebote vergleichen
|
Windenergie berechnen: Ertrag, Kosten & Angebote vergleichen
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" className="w-full" asChild>
|
<Button variant="outline" className="w-full" asChild>
|
||||||
<Link to="/wind">Zum Windrechner</Link>
|
<Link
|
||||||
|
to="/wind"
|
||||||
|
onClick={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const calculatorElement = document.querySelector('[data-calculator]') ||
|
||||||
|
document.querySelector('.calculator') ||
|
||||||
|
document.querySelector('h2');
|
||||||
|
if (calculatorElement) {
|
||||||
|
calculatorElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Zum Windrechner
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="text-center p-8 hover:shadow-lg transition-shadow">
|
<Card className="text-center p-8 hover:shadow-lg transition-shadow">
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useSearchParams } from "react-router-dom";
|
import { useSearchParams, Link } from "react-router-dom";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
|
|
||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Search, MapPin, Star, Phone, Mail, Globe, Filter, AlertCircle, Calculator, Award, Shield, TrendingUp, Map, Users, Clock, CheckCircle } from "lucide-react";
|
import { Search, MapPin, Star, Phone, Mail, Globe, Filter, AlertCircle, Calculator, Award, Shield, TrendingUp, Map, Users, Clock, CheckCircle } from "lucide-react";
|
||||||
import Header from "@/components/Header";
|
import Header from "@/components/Header";
|
||||||
|
|
@ -271,38 +270,39 @@ const InstallateurFinden = () => {
|
||||||
e.preventDefault(); // Prevent default button behavior
|
e.preventDefault(); // Prevent default button behavior
|
||||||
e.stopPropagation(); // Stop event bubbling
|
e.stopPropagation(); // Stop event bubbling
|
||||||
|
|
||||||
if (currentPage >= 2) {
|
// Hard cut at 69 installers - don't load more after that
|
||||||
// After 3 clicks (30 installers), show all remaining
|
if (displayedInstallers.length >= 69) {
|
||||||
setShowAll(true);
|
return;
|
||||||
setCurrentPage(0);
|
}
|
||||||
await loadInstallers(false);
|
|
||||||
} else {
|
|
||||||
// Load next 10 installers
|
|
||||||
const nextPage = currentPage + 1;
|
|
||||||
setCurrentPage(nextPage);
|
|
||||||
|
|
||||||
try {
|
// Load next 10 installers, but limit to 69 total
|
||||||
setLoading(true);
|
const nextPage = currentPage + 1;
|
||||||
setError(null);
|
setCurrentPage(nextPage);
|
||||||
|
|
||||||
const filters = {
|
try {
|
||||||
energyType: energyType && energyType !== "all" ? energyType : undefined,
|
setLoading(true);
|
||||||
bundesland: bundesland && bundesland !== "all" ? bundesland : undefined,
|
setError(null);
|
||||||
searchTerm: searchTerm || undefined,
|
|
||||||
limit: 10,
|
|
||||||
offset: nextPage * 10
|
|
||||||
};
|
|
||||||
|
|
||||||
const result = await installerService.getInstallers(filters);
|
const filters = {
|
||||||
const newInstallers = [...displayedInstallers, ...(result.data || [])];
|
energyType: energyType && energyType !== "all" ? energyType : undefined,
|
||||||
setDisplayedInstallers(newInstallers);
|
bundesland: bundesland && bundesland !== "all" ? bundesland : undefined,
|
||||||
setTotalInstallers(result.totalCount || 0);
|
searchTerm: searchTerm || undefined,
|
||||||
} catch (err) {
|
limit: 10,
|
||||||
console.error('Error loading more installers:', err);
|
offset: nextPage * 10
|
||||||
setError('Fehler beim Laden weiterer Installateure. Bitte versuchen Sie es später erneut.');
|
};
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
const result = await installerService.getInstallers(filters);
|
||||||
}
|
const newInstallers = [...displayedInstallers, ...(result.data || [])];
|
||||||
|
|
||||||
|
// Hard cut at 69 installers
|
||||||
|
const limitedInstallers = newInstallers.slice(0, 69);
|
||||||
|
setDisplayedInstallers(limitedInstallers);
|
||||||
|
setTotalInstallers(Math.max(limitedInstallers.length, result.totalCount || 0));
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error loading more installers:', err);
|
||||||
|
setError('Fehler beim Laden weiterer Installateure. Bitte versuchen Sie es später erneut.');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -547,41 +547,39 @@ const InstallateurFinden = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Select value={energyType} onValueChange={setEnergyType}>
|
<select
|
||||||
<SelectTrigger>
|
value={energyType}
|
||||||
<SelectValue placeholder="Energieart wählen" />
|
onChange={(e) => setEnergyType(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="all">Alle Energiearten</SelectItem>
|
<option value="all">Alle Energiearten</option>
|
||||||
<SelectItem value="solar">Solar</SelectItem>
|
<option value="solar">Solar</option>
|
||||||
<SelectItem value="wind">Wind</SelectItem>
|
<option value="wind">Wind</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select value={bundesland} onValueChange={setBundesland}>
|
<select
|
||||||
<SelectTrigger>
|
value={bundesland}
|
||||||
<SelectValue placeholder="Bundesland wählen" />
|
onChange={(e) => setBundesland(e.target.value)}
|
||||||
</SelectTrigger>
|
className="h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||||
<SelectContent>
|
>
|
||||||
<SelectItem value="all">Alle Bundesländer</SelectItem>
|
<option value="all">Alle Bundesländer</option>
|
||||||
<SelectItem value="Baden-Württemberg">Baden-Württemberg</SelectItem>
|
<option value="Baden-Württemberg">Baden-Württemberg</option>
|
||||||
<SelectItem value="Bayern">Bayern</SelectItem>
|
<option value="Bayern">Bayern</option>
|
||||||
<SelectItem value="Berlin">Berlin</SelectItem>
|
<option value="Berlin">Berlin</option>
|
||||||
<SelectItem value="Brandenburg">Brandenburg</SelectItem>
|
<option value="Brandenburg">Brandenburg</option>
|
||||||
<SelectItem value="Bremen">Bremen</SelectItem>
|
<option value="Bremen">Bremen</option>
|
||||||
<SelectItem value="Hamburg">Hamburg</SelectItem>
|
<option value="Hamburg">Hamburg</option>
|
||||||
<SelectItem value="Hessen">Hessen</SelectItem>
|
<option value="Hessen">Hessen</option>
|
||||||
<SelectItem value="Mecklenburg-Vorpommern">Mecklenburg-Vorpommern</SelectItem>
|
<option value="Mecklenburg-Vorpommern">Mecklenburg-Vorpommern</option>
|
||||||
<SelectItem value="Niedersachsen">Niedersachsen</SelectItem>
|
<option value="Niedersachsen">Niedersachsen</option>
|
||||||
<SelectItem value="Nordrhein-Westfalen">Nordrhein-Westfalen</SelectItem>
|
<option value="Nordrhein-Westfalen">Nordrhein-Westfalen</option>
|
||||||
<SelectItem value="Rheinland-Pfalz">Rheinland-Pfalz</SelectItem>
|
<option value="Rheinland-Pfalz">Rheinland-Pfalz</option>
|
||||||
<SelectItem value="Saarland">Saarland</SelectItem>
|
<option value="Saarland">Saarland</option>
|
||||||
<SelectItem value="Sachsen">Sachsen</SelectItem>
|
<option value="Sachsen">Sachsen</option>
|
||||||
<SelectItem value="Sachsen-Anhalt">Sachsen-Anhalt</SelectItem>
|
<option value="Sachsen-Anhalt">Sachsen-Anhalt</option>
|
||||||
<SelectItem value="Schleswig-Holstein">Schleswig-Holstein</SelectItem>
|
<option value="Schleswig-Holstein">Schleswig-Holstein</option>
|
||||||
<SelectItem value="Thüringen">Thüringen</SelectItem>
|
<option value="Thüringen">Thüringen</option>
|
||||||
</SelectContent>
|
</select>
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Button onClick={handleReset} variant="outline" className="w-full">
|
<Button onClick={handleReset} variant="outline" className="w-full">
|
||||||
Filter zurücksetzen
|
Filter zurücksetzen
|
||||||
|
|
@ -653,12 +651,12 @@ const InstallateurFinden = () => {
|
||||||
{/* Results */}
|
{/* Results */}
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<p className="text-muted-foreground">
|
<p className="text-muted-foreground">
|
||||||
{displayedInstallers.length} von {totalInstallers} Installateur{totalInstallers !== 1 ? 'e' : ''} angezeigt
|
{displayedInstallers.length} von {Math.max(displayedInstallers.length, totalInstallers)} Installateur{Math.max(displayedInstallers.length, totalInstallers) !== 1 ? 'e' : ''} angezeigt
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Installer Cards */}
|
{/* Installer Cards */}
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-16">
|
||||||
{displayedInstallers.map((installer) => (
|
{displayedInstallers.map((installer) => (
|
||||||
<Card key={installer.id} className="hover:shadow-lg transition-shadow">
|
<Card key={installer.id} className="hover:shadow-lg transition-shadow">
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
|
|
@ -769,7 +767,7 @@ const InstallateurFinden = () => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Show More Button */}
|
{/* Show More Button */}
|
||||||
{displayedInstallers.length > 0 && displayedInstallers.length < totalInstallers && (
|
{displayedInstallers.length > 0 && displayedInstallers.length < 69 && displayedInstallers.length < totalInstallers && (
|
||||||
<div className="text-center mt-12 mb-16">
|
<div className="text-center mt-12 mb-16">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -778,7 +776,7 @@ const InstallateurFinden = () => {
|
||||||
size="lg"
|
size="lg"
|
||||||
className="px-12 py-3 text-lg font-semibold"
|
className="px-12 py-3 text-lg font-semibold"
|
||||||
>
|
>
|
||||||
{currentPage >= 2 ? 'Alle anzeigen' : 'Mehr anzeigen'}
|
Mehr anzeigen
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -848,8 +846,22 @@ const InstallateurFinden = () => {
|
||||||
<p className="text-muted-foreground mb-4">
|
<p className="text-muted-foreground mb-4">
|
||||||
Berechnen Sie Ihre Solareinsparungen und vergleichen Sie Angebote
|
Berechnen Sie Ihre Solareinsparungen und vergleichen Sie Angebote
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" className="w-full">
|
<Button variant="outline" className="w-full" asChild>
|
||||||
Zum Solarrechner
|
<Link
|
||||||
|
to="/solar"
|
||||||
|
onClick={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const calculatorElement = document.querySelector('[data-calculator]') ||
|
||||||
|
document.querySelector('.calculator') ||
|
||||||
|
document.querySelector('h2');
|
||||||
|
if (calculatorElement) {
|
||||||
|
calculatorElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Zum Solarrechner
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
<Card className="text-center p-6 hover:shadow-md transition-shadow">
|
<Card className="text-center p-6 hover:shadow-md transition-shadow">
|
||||||
|
|
@ -858,8 +870,22 @@ const InstallateurFinden = () => {
|
||||||
<p className="text-muted-foreground mb-4">
|
<p className="text-muted-foreground mb-4">
|
||||||
Windenergie berechnen: Ertrag, Kosten & Angebote vergleichen
|
Windenergie berechnen: Ertrag, Kosten & Angebote vergleichen
|
||||||
</p>
|
</p>
|
||||||
<Button variant="outline" className="w-full">
|
<Button variant="outline" className="w-full" asChild>
|
||||||
Zum Windrechner
|
<Link
|
||||||
|
to="/wind"
|
||||||
|
onClick={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const calculatorElement = document.querySelector('[data-calculator]') ||
|
||||||
|
document.querySelector('.calculator') ||
|
||||||
|
document.querySelector('h2');
|
||||||
|
if (calculatorElement) {
|
||||||
|
calculatorElement.scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Zum Windrechner
|
||||||
|
</Link>
|
||||||
</Button>
|
</Button>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue