This commit is contained in:
knuthtimo-lab 2025-09-04 14:37:37 +02:00
parent d21f1c760b
commit 9d78fd16da
3 changed files with 303 additions and 144 deletions

View File

@ -1,138 +1,150 @@
import { Card, CardContent } from "@/components/ui/card";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input"; import {
import { Link } from "react-router-dom"; Mail,
import { Mail, Phone, MapPin, Facebook, Twitter, Linkedin, Instagram } from "lucide-react"; Phone,
MapPin,
Facebook,
Twitter,
Linkedin,
Instagram,
Calculator,
TrendingUp,
Shield,
Award
} from "lucide-react";
const Footer = () => { const Footer = () => {
return ( return (
<footer className="bg-primary text-primary-foreground"> <footer className="bg-gray-900 text-white mt-20">
<div className="container mx-auto px-4 py-16"> <div className="container mx-auto px-4 py-12">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-12"> <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{/* Company Info */} {/* Company Info */}
<div className="space-y-6"> <div className="space-y-4">
<div className="flex items-center space-x-2"> <div className="flex items-center gap-2">
<div className="w-8 h-8 bg-gradient-hero rounded-lg flex items-center justify-center"> <div className="w-8 h-8 bg-gradient-to-r from-orange-500 to-blue-500 rounded-lg flex items-center justify-center">
<span className="text-white font-bold text-lg">E</span> <span className="text-white font-bold text-lg">E</span>
</div> </div>
<span className="text-xl font-bold">EnergieProfis</span> <span className="text-xl font-bold">EnergieProfis</span>
</div> </div>
<p className="text-gray-300 text-sm leading-relaxed">
<p className="text-primary-foreground/80 leading-relaxed"> Ihr vertrauensvoller Partner für erneuerbare Energien.
Ihr vertrauensvoller Partner für erneuerbare Energielösungen in Deutschland. Finden Sie qualifizierte Solar- und Wind-Installateure in Ihrer Region.
Wir verbinden Sie mit den besten Installateuren für eine nachhaltige Zukunft.
</p> </p>
<div className="flex space-x-4">
<div className="space-y-3"> <Button variant="ghost" size="sm" className="text-gray-300 hover:text-white p-2">
<div className="flex items-center space-x-3"> <Facebook className="w-5 h-5" />
<Phone className="w-5 h-5 text-solar" /> </Button>
<span>+49 (0) 800 123 4567</span> <Button variant="ghost" size="sm" className="text-gray-300 hover:text-white p-2">
</div> <Twitter className="w-5 h-5" />
<div className="flex items-center space-x-3"> </Button>
<Mail className="w-5 h-5 text-wind" /> <Button variant="ghost" size="sm" className="text-gray-300 hover:text-white p-2">
<span>info@energieprofis.de</span> <Linkedin className="w-5 h-5" />
</div> </Button>
<div className="flex items-center space-x-3"> <Button variant="ghost" size="sm" className="text-gray-300 hover:text-white p-2">
<MapPin className="w-5 h-5 text-geo" /> <Instagram className="w-5 h-5" />
<span>München, Deutschland</span> </Button>
</div>
</div> </div>
</div> </div>
{/* Energy Types */} {/* Quick Links */}
<div className="space-y-6"> <div className="space-y-4">
<h3 className="text-lg font-semibold">Energielösungen</h3> <h3 className="text-lg font-semibold">Schnellzugriff</h3>
<ul className="space-y-3"> <ul className="space-y-2 text-sm">
<li> <li>
<Link to="/solar" className="text-primary-foreground/80 hover:text-solar transition-colors"> <a href="/" className="text-gray-300 hover:text-white transition-colors">
Solar-Installateure Solar-Installation
</Link> </a>
</li> </li>
<li> <li>
<Link to="/wind" className="text-primary-foreground/80 hover:text-wind transition-colors"> <a href="/" className="text-gray-300 hover:text-white transition-colors">
Wind-Installateure Windenergie
</Link> </a>
</li>
<li>
<a href="/" className="text-gray-300 hover:text-white transition-colors">
Installateur finden
</a>
</li>
<li>
<a href="/" className="text-gray-300 hover:text-white transition-colors">
Förderungen 2025
</a>
</li>
<li>
<a href="/" className="text-gray-300 hover:text-white transition-colors">
Kostenrechner
</a>
</li> </li>
</ul> </ul>
</div> </div>
{/* Services */} {/* Services */}
<div className="space-y-6"> <div className="space-y-4">
<h3 className="text-lg font-semibold">Services</h3> <h3 className="text-lg font-semibold">Unsere Services</h3>
<ul className="space-y-3"> <ul className="space-y-2 text-sm">
<li> <li className="flex items-center gap-2 text-gray-300">
<Link to="/installateur-finden" className="text-primary-foreground/80 hover:text-white transition-colors"> <Calculator className="w-4 h-4" />
Installateur Finden Solar-Einsparungsrechner
</Link>
</li> </li>
<li> <li className="flex items-center gap-2 text-gray-300">
<Link to="/unternehmen-listen" className="text-primary-foreground/80 hover:text-white transition-colors"> <TrendingUp className="w-4 h-4" />
Unternehmen Listen Windenergie-Rechner
</Link>
</li> </li>
<li> <li className="flex items-center gap-2 text-gray-300">
<Link to="/preisvergleich" className="text-primary-foreground/80 hover:text-white transition-colors"> <Shield className="w-4 h-4" />
Preisvergleich Verifizierte Installateure
</Link> </li>
<li className="flex items-center gap-2 text-gray-300">
<Award className="w-4 h-4" />
Zertifizierte Fachbetriebe
</li> </li>
</ul> </ul>
</div> </div>
{/* Newsletter */} {/* Contact Info */}
<div className="space-y-6"> <div className="space-y-4">
<h3 className="text-lg font-semibold">Newsletter</h3> <h3 className="text-lg font-semibold">Kontakt</h3>
<p className="text-primary-foreground/80"> <div className="space-y-3 text-sm">
Bleiben Sie informiert über die neuesten Entwicklungen <div className="flex items-center gap-3 text-gray-300">
in der erneuerbaren Energie. <Mail className="w-4 h-4" />
</p> <span>info@energieprofis.de</span>
</div>
<div className="space-y-3"> <div className="flex items-center gap-3 text-gray-300">
<Input <Phone className="w-4 h-4" />
placeholder="Ihre E-Mail-Adresse" <span>+49 (0) 800 123 456</span>
className="bg-white/10 border-white/20 text-white placeholder:text-white/60" </div>
/> <div className="flex items-start gap-3 text-gray-300">
<Button variant="hero" className="w-full bg-white text-primary hover:bg-white/90"> <MapPin className="w-4 h-4 mt-0.5" />
Anmelden <span>
</Button> EnergieProfis GmbH<br />
Musterstraße 123<br />
10115 Berlin
</span>
</div> </div>
{/* Social Media */}
<div className="flex space-x-4">
<Button variant="ghost" size="icon" className="hover:bg-white/10">
<Facebook className="w-5 h-5" />
</Button>
<Button variant="ghost" size="icon" className="hover:bg-white/10">
<Twitter className="w-5 h-5" />
</Button>
<Button variant="ghost" size="icon" className="hover:bg-white/10">
<Linkedin className="w-5 h-5" />
</Button>
<Button variant="ghost" size="icon" className="hover:bg-white/10">
<Instagram className="w-5 h-5" />
</Button>
</div> </div>
</div> </div>
</div> </div>
{/* Bottom Bar */} {/* Bottom Section */}
<div className="border-t border-white/20 mt-12 pt-8"> <div className="border-t border-gray-700 mt-12 pt-8">
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0"> <div className="flex flex-col md:flex-row justify-between items-center gap-4">
<p className="text-primary-foreground/60 text-sm"> <div className="text-sm text-gray-400">
© 2024 EnergieProfis. Alle Rechte vorbehalten. © 2025 EnergieProfis. Alle Rechte vorbehalten.
</p> </div>
<div className="flex space-x-6 text-sm"> <div className="flex space-x-6 text-sm">
<Link to="/datenschutz" className="text-primary-foreground/60 hover:text-white transition-colors"> <a href="/" className="text-gray-400 hover:text-white transition-colors">
Datenschutz
</Link>
<Link to="/agb" className="text-primary-foreground/60 hover:text-white transition-colors">
AGB
</Link>
<Link to="/impressum" className="text-primary-foreground/60 hover:text-white transition-colors">
Impressum Impressum
</Link> </a>
<Link to="/kontakt" className="text-primary-foreground/60 hover:text-white transition-colors"> <a href="/" className="text-gray-400 hover:text-white transition-colors">
Kontakt Datenschutz
</Link> </a>
<a href="/" className="text-gray-400 hover:text-white transition-colors">
AGB
</a>
<a href="/" className="text-gray-400 hover:text-white transition-colors">
Cookie-Einstellungen
</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -14,28 +14,64 @@ export const installerService = {
// Get all installers with optional filters // Get all installers with optional filters
async getInstallers(filters?: { async getInstallers(filters?: {
energyType?: string; energyType?: string;
location?: string; bundesland?: string;
searchTerm?: string; searchTerm?: string;
limit?: number;
offset?: number;
}) { }) {
let query = supabase // First, get the total count
let countQuery = supabase
.from('installers')
.select('*', { count: 'exact', head: true })
.eq('status', 'active');
if (filters?.energyType && filters.energyType !== 'all') {
countQuery = countQuery.eq('energy_type', filters.energyType);
}
if (filters?.bundesland && filters.bundesland !== 'all') {
countQuery = countQuery.ilike('location', `%${filters.bundesland}%`);
}
if (filters?.searchTerm) {
countQuery = countQuery.or(`name.ilike.%${filters.searchTerm}%,description.ilike.%${filters.searchTerm}%,specialties.cs.{${filters.searchTerm}}`);
}
const { count, error: countError } = await countQuery;
if (countError) {
console.error('Error fetching installer count:', countError);
throw countError;
}
// Then get the actual data with pagination
let dataQuery = supabase
.from('installers') .from('installers')
.select('*') .select('*')
.eq('status', 'active') .eq('status', 'active')
.order('rating', { ascending: false }); .order('rating', { ascending: false });
if (filters?.energyType && filters.energyType !== 'all') { if (filters?.energyType && filters.energyType !== 'all') {
query = query.eq('energy_type', filters.energyType); dataQuery = dataQuery.eq('energy_type', filters.energyType);
} }
if (filters?.location) { if (filters?.bundesland && filters.bundesland !== 'all') {
query = query.ilike('location', `%${filters.location}%`); dataQuery = dataQuery.ilike('location', `%${filters.bundesland}%`);
} }
if (filters?.searchTerm) { if (filters?.searchTerm) {
query = query.or(`name.ilike.%${filters.searchTerm}%,description.ilike.%${filters.searchTerm}%,specialties.cs.{${filters.searchTerm}}`); dataQuery = dataQuery.or(`name.ilike.%${filters.searchTerm}%,description.ilike.%${filters.searchTerm}%,specialties.cs.{${filters.searchTerm}}`);
} }
const { data, error } = await query; // Apply pagination
if (filters?.limit) {
dataQuery = dataQuery.limit(filters.limit);
}
if (filters?.offset) {
dataQuery = dataQuery.range(filters.offset, filters.offset + (filters.limit || 10) - 1);
}
const { data, error } = await dataQuery;
if (error) { if (error) {
console.error('Error fetching installers:', error); console.error('Error fetching installers:', error);
@ -48,7 +84,7 @@ export const installerService = {
throw error; throw error;
} }
return data; return { data: data || [], totalCount: count || 0 };
}, },
// Get installer by ID // Get installer by ID
@ -182,14 +218,16 @@ export const useInstallers = () => {
const fetchInstallers = async (filters?: { const fetchInstallers = async (filters?: {
energyType?: string; energyType?: string;
location?: string; bundesland?: string;
searchTerm?: string; searchTerm?: string;
limit?: number;
offset?: number;
}) => { }) => {
try { try {
setLoading(true); setLoading(true);
setError(null); setError(null);
const data = await installerService.getInstallers(filters); const result = await installerService.getInstallers(filters);
setInstallers(data || []); setInstallers(result.data || []);
} catch (err) { } catch (err) {
setError(err instanceof Error ? err.message : 'An error occurred'); setError(err instanceof Error ? err.message : 'An error occurred');
setInstallers([]); setInstallers([]);

View File

@ -7,6 +7,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@
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";
import Footer from "@/components/Footer";
import { installerService, analyticsService } from "@/lib/database"; import { installerService, analyticsService } from "@/lib/database";
import { cleanAndReseedDatabase } from "@/lib/cleanDatabase"; import { cleanAndReseedDatabase } from "@/lib/cleanDatabase";
import { debugDatabase, forceDeleteAll, testConnection } from "@/lib/debugDatabase"; import { debugDatabase, forceDeleteAll, testConnection } from "@/lib/debugDatabase";
@ -22,7 +23,13 @@ const InstallateurFinden = () => {
const [searchTerm, setSearchTerm] = useState(searchParams.get("search") || ""); const [searchTerm, setSearchTerm] = useState(searchParams.get("search") || "");
const [energyType, setEnergyType] = useState(searchParams.get("type") || "all"); const [energyType, setEnergyType] = useState(searchParams.get("type") || "all");
const [location, setLocation] = useState(searchParams.get("location") || ""); const [bundesland, setBundesland] = useState(searchParams.get("bundesland") || "all");
// Pagination state
const [displayedInstallers, setDisplayedInstallers] = useState<Installer[]>([]);
const [currentPage, setCurrentPage] = useState(0);
const [totalInstallers, setTotalInstallers] = useState(0);
const [showAll, setShowAll] = useState(false);
// SEO: Add structured data for the page // SEO: Add structured data for the page
useEffect(() => { useEffect(() => {
@ -33,8 +40,8 @@ const InstallateurFinden = () => {
"name": "Solar- und Wind-Installateure in Deutschland", "name": "Solar- und Wind-Installateure in Deutschland",
"description": "Qualifizierte Fachbetriebe für Photovoltaik und Windenergie finden und vergleichen", "description": "Qualifizierte Fachbetriebe für Photovoltaik und Windenergie finden und vergleichen",
"url": window.location.href, "url": window.location.href,
"numberOfItems": installers.length, "numberOfItems": displayedInstallers.length,
"itemListElement": installers.map((installer, index) => ({ "itemListElement": displayedInstallers.map((installer, index) => ({
"@type": "ListItem", "@type": "ListItem",
"position": index + 1, "position": index + 1,
"item": { "item": {
@ -152,18 +159,27 @@ const InstallateurFinden = () => {
}, []); }, []);
// Load installers from database // Load installers from database
const loadInstallers = async () => { const loadInstallers = async (resetPagination = true) => {
try { try {
setLoading(true); setLoading(true);
setError(null); setError(null);
if (resetPagination) {
setCurrentPage(0);
setShowAll(false);
}
const filters = { const filters = {
energyType: energyType && energyType !== "all" ? energyType : undefined, energyType: energyType && energyType !== "all" ? energyType : undefined,
location: location || undefined, bundesland: bundesland && bundesland !== "all" ? bundesland : undefined,
searchTerm: searchTerm || undefined searchTerm: searchTerm || undefined,
limit: showAll ? undefined : 10,
offset: showAll ? undefined : (currentPage * 10)
}; };
const data = await installerService.getInstallers(filters); const result = await installerService.getInstallers(filters);
const data = result.data;
const totalCount = result.totalCount;
// If no installers found, automatically seed the database // If no installers found, automatically seed the database
if (!data || data.length === 0) { if (!data || data.length === 0) {
@ -171,19 +187,38 @@ const InstallateurFinden = () => {
try { try {
await cleanAndReseedDatabase(); await cleanAndReseedDatabase();
// Try to load installers again after seeding // Try to load installers again after seeding
const reseededData = await installerService.getInstallers(filters); const reseededResult = await installerService.getInstallers(filters);
setInstallers(reseededData || []); if (resetPagination) {
setInstallers(reseededResult.data || []);
setDisplayedInstallers(reseededResult.data || []);
setTotalInstallers(reseededResult.totalCount || 0);
} else {
const newInstallers = [...displayedInstallers, ...(reseededResult.data || [])];
setDisplayedInstallers(newInstallers);
setTotalInstallers(reseededResult.totalCount || 0);
}
} catch (seedError) { } catch (seedError) {
console.error('Error seeding database:', seedError); console.error('Error seeding database:', seedError);
setError('Datenbank wird initialisiert. Bitte versuchen Sie es in wenigen Sekunden erneut.'); setError('Datenbank wird initialisiert. Bitte versuchen Sie es in wenigen Sekunden erneut.');
setInstallers([]); setInstallers([]);
setDisplayedInstallers([]);
setTotalInstallers(0);
} }
} else { } else {
if (resetPagination) {
setInstallers(data); setInstallers(data);
setDisplayedInstallers(data);
setTotalInstallers(totalCount);
} else {
// Append new data for pagination
const newInstallers = [...displayedInstallers, ...data];
setDisplayedInstallers(newInstallers);
setTotalInstallers(totalCount);
}
} }
// Track search event // Track search event
if (searchTerm || energyType !== "all" || location) { if (searchTerm || energyType !== "all" || bundesland !== "all") {
analyticsService.trackEvent({ analyticsService.trackEvent({
event_type: 'installer_search', event_type: 'installer_search',
page_url: window.location.pathname, page_url: window.location.pathname,
@ -196,6 +231,7 @@ const InstallateurFinden = () => {
console.error('Error loading installers:', err); console.error('Error loading installers:', err);
setError('Fehler beim Laden der Installateure. Bitte versuchen Sie es später erneut.'); setError('Fehler beim Laden der Installateure. Bitte versuchen Sie es später erneut.');
setInstallers([]); setInstallers([]);
setDisplayedInstallers([]);
} finally { } finally {
setLoading(false); setLoading(false);
} }
@ -209,25 +245,65 @@ const InstallateurFinden = () => {
// Reload when filters change // Reload when filters change
useEffect(() => { useEffect(() => {
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
loadInstallers(); loadInstallers(true); // Reset pagination when filters change
}, 500); // Debounce search }, 500); // Debounce search
return () => clearTimeout(timeoutId); return () => clearTimeout(timeoutId);
}, [searchTerm, energyType, location]); }, [searchTerm, energyType, bundesland]);
// Update URL params when filters change // Update URL params when filters change
useEffect(() => { useEffect(() => {
const params = new URLSearchParams(); const params = new URLSearchParams();
if (searchTerm) params.set("search", searchTerm); if (searchTerm) params.set("search", searchTerm);
if (energyType && energyType !== "all") params.set("type", energyType); if (energyType && energyType !== "all") params.set("type", energyType);
if (location) params.set("location", location); if (bundesland && bundesland !== "all") params.set("bundesland", bundesland);
setSearchParams(params); setSearchParams(params);
}, [searchTerm, energyType, location, setSearchParams]); }, [searchTerm, energyType, bundesland, setSearchParams]);
const handleReset = () => { const handleReset = () => {
setSearchTerm(""); setSearchTerm("");
setEnergyType("all"); setEnergyType("all");
setLocation(""); setBundesland("all");
};
// Handle "Show More" button click
const handleShowMore = async (e: React.MouseEvent) => {
e.preventDefault(); // Prevent default button behavior
e.stopPropagation(); // Stop event bubbling
if (currentPage >= 2) {
// After 3 clicks (30 installers), show all remaining
setShowAll(true);
setCurrentPage(0);
await loadInstallers(false);
} else {
// Load next 10 installers
const nextPage = currentPage + 1;
setCurrentPage(nextPage);
try {
setLoading(true);
setError(null);
const filters = {
energyType: energyType && energyType !== "all" ? energyType : undefined,
bundesland: bundesland && bundesland !== "all" ? bundesland : undefined,
searchTerm: searchTerm || undefined,
limit: 10,
offset: nextPage * 10
};
const result = await installerService.getInstallers(filters);
const newInstallers = [...displayedInstallers, ...(result.data || [])];
setDisplayedInstallers(newInstallers);
setTotalInstallers(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);
}
}
}; };
// Test connection // Test connection
@ -258,7 +334,7 @@ const InstallateurFinden = () => {
try { try {
await cleanAndReseedDatabase(); await cleanAndReseedDatabase();
alert('Deutsche Installateure erfolgreich geladen!'); alert('Deutsche Installateure erfolgreich geladen!');
loadInstallers(); // Reload the data loadInstallers(true); // Reload the data with pagination reset
} catch (error) { } catch (error) {
console.error('Error seeding database:', error); console.error('Error seeding database:', error);
alert('Fehler beim Laden der Installateure. Details in der Konsole.'); alert('Fehler beim Laden der Installateure. Details in der Konsole.');
@ -482,15 +558,30 @@ const InstallateurFinden = () => {
</SelectContent> </SelectContent>
</Select> </Select>
<div className="relative"> <Select value={bundesland} onValueChange={setBundesland}>
<MapPin className="absolute left-3 top-1/2 transform -translate-y-1/2 text-muted-foreground w-4 h-4" /> <SelectTrigger>
<Input <SelectValue placeholder="Bundesland wählen" />
placeholder="PLZ oder Stadt" </SelectTrigger>
value={location} <SelectContent>
onChange={(e) => setLocation(e.target.value)} <SelectItem value="all">Alle Bundesländer</SelectItem>
className="pl-10" <SelectItem value="Baden-Württemberg">Baden-Württemberg</SelectItem>
/> <SelectItem value="Bayern">Bayern</SelectItem>
</div> <SelectItem value="Berlin">Berlin</SelectItem>
<SelectItem value="Brandenburg">Brandenburg</SelectItem>
<SelectItem value="Bremen">Bremen</SelectItem>
<SelectItem value="Hamburg">Hamburg</SelectItem>
<SelectItem value="Hessen">Hessen</SelectItem>
<SelectItem value="Mecklenburg-Vorpommern">Mecklenburg-Vorpommern</SelectItem>
<SelectItem value="Niedersachsen">Niedersachsen</SelectItem>
<SelectItem value="Nordrhein-Westfalen">Nordrhein-Westfalen</SelectItem>
<SelectItem value="Rheinland-Pfalz">Rheinland-Pfalz</SelectItem>
<SelectItem value="Saarland">Saarland</SelectItem>
<SelectItem value="Sachsen">Sachsen</SelectItem>
<SelectItem value="Sachsen-Anhalt">Sachsen-Anhalt</SelectItem>
<SelectItem value="Schleswig-Holstein">Schleswig-Holstein</SelectItem>
<SelectItem value="Thüringen">Thüringen</SelectItem>
</SelectContent>
</Select>
<Button onClick={handleReset} variant="outline" className="w-full"> <Button onClick={handleReset} variant="outline" className="w-full">
Filter zurücksetzen Filter zurücksetzen
@ -533,7 +624,7 @@ const InstallateurFinden = () => {
<h3 className="text-lg font-semibold text-red-800 mb-2">Fehler beim Laden</h3> <h3 className="text-lg font-semibold text-red-800 mb-2">Fehler beim Laden</h3>
<p className="text-red-700 mb-4">{error}</p> <p className="text-red-700 mb-4">{error}</p>
<div className="flex gap-2 justify-center"> <div className="flex gap-2 justify-center">
<Button onClick={loadInstallers} variant="outline" className="border-red-300 text-red-700 hover:bg-red-100"> <Button onClick={() => loadInstallers(true)} variant="outline" className="border-red-300 text-red-700 hover:bg-red-100">
Erneut versuchen Erneut versuchen
</Button> </Button>
{process.env.NODE_ENV === 'development' && ( {process.env.NODE_ENV === 'development' && (
@ -562,13 +653,13 @@ const InstallateurFinden = () => {
{/* Results */} {/* Results */}
<div className="mb-4"> <div className="mb-4">
<p className="text-muted-foreground"> <p className="text-muted-foreground">
{installers.length} Installateur{installers.length !== 1 ? 'e' : ''} gefunden {displayedInstallers.length} von {totalInstallers} Installateur{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">
{installers.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>
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
@ -677,7 +768,22 @@ const InstallateurFinden = () => {
))} ))}
</div> </div>
{installers.length === 0 && ( {/* Show More Button */}
{displayedInstallers.length > 0 && displayedInstallers.length < totalInstallers && (
<div className="text-center mt-12 mb-16">
<Button
type="button"
onClick={handleShowMore}
variant="outline"
size="lg"
className="px-12 py-3 text-lg font-semibold"
>
{currentPage >= 2 ? 'Alle anzeigen' : 'Mehr anzeigen'}
</Button>
</div>
)}
{displayedInstallers.length === 0 && (
<Card className="text-center py-12"> <Card className="text-center py-12">
<CardContent> <CardContent>
<p className="text-muted-foreground text-lg mb-4"> <p className="text-muted-foreground text-lg mb-4">
@ -759,6 +865,9 @@ const InstallateurFinden = () => {
</div> </div>
</div> </div>
</div> </div>
{/* Footer */}
<Footer />
</div> </div>
); );
}; };