'use client' import { useState, useEffect } from 'react' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { useToast } from '@/components/ui/use-toast' import Link from 'next/link' import { Mail, Send, CheckCircle, Ban, CreditCard, Map, MapPin, Settings, Shield, UserPlus, ArrowLeft, Loader2, } from 'lucide-react' interface SettingsTabProps { usersCount: number tenantsCount: number iconsCount: number onNavigateTab: (tab: string) => void } export function SettingsTab({ usersCount, tenantsCount, iconsCount, onNavigateTab }: SettingsTabProps) { const { toast } = useToast() // SMTP Settings const [smtpHost, setSmtpHost] = useState('') const [smtpPort, setSmtpPort] = useState('587') const [smtpSecure, setSmtpSecure] = useState(false) const [smtpUser, setSmtpUser] = useState('') const [smtpPass, setSmtpPass] = useState('') const [smtpFromName, setSmtpFromName] = useState('Lageplan') const [smtpFromEmail, setSmtpFromEmail] = useState('') const [smtpTestEmail, setSmtpTestEmail] = useState('') const [smtpLoading, setSmtpLoading] = useState(false) const [smtpStatus, setSmtpStatus] = useState(null) const [contactEmail, setContactEmail] = useState('app@lageplan.ch') const [notifyRegistrationEmail, setNotifyRegistrationEmail] = useState('') // Stripe Settings const [stripePublicKey, setStripePublicKey] = useState('') const [stripeSecretKey, setStripeSecretKey] = useState('') const [stripeWebhookSecret, setStripeWebhookSecret] = useState('') const [stripeLoading, setStripeLoading] = useState(false) const [stripeStatus, setStripeStatus] = useState(null) // Demo Project const [demoProjectId, setDemoProjectId] = useState('') const [allProjects, setAllProjects] = useState<{ id: string; title: string; location?: string }[]>([]) const [demoLoading, setDemoLoading] = useState(false) const [demoStatus, setDemoStatus] = useState(null) // Default Symbol Scale const [defaultSymbolScale, setDefaultSymbolScale] = useState('1.5') const [symbolScaleLoading, setSymbolScaleLoading] = useState(false) const [symbolScaleStatus, setSymbolScaleStatus] = useState(null) // Load settings on mount useEffect(() => { fetch('/api/admin/settings').then(r => r.json()).then(data => { if (data.smtp) { setSmtpHost(data.smtp.host || '') setSmtpPort(data.smtp.port?.toString() || '587') setSmtpSecure(data.smtp.secure || false) setSmtpUser(data.smtp.user || '') setSmtpFromName(data.smtp.fromName || 'Lageplan') setSmtpFromEmail(data.smtp.fromEmail || '') } if (data.stripe) { setStripePublicKey(data.stripe.publicKey || '') setStripeSecretKey(data.stripe.secretKey ? '••••••••' : '') setStripeWebhookSecret(data.stripe.webhookSecret ? '••••••••' : '') } if (data.contactEmail) setContactEmail(data.contactEmail) if (data.notifyRegistrationEmail) setNotifyRegistrationEmail(data.notifyRegistrationEmail) if (data.demoProjectId) setDemoProjectId(data.demoProjectId) if (data.defaultSymbolScale) setDefaultSymbolScale(data.defaultSymbolScale.toString()) }).catch(() => {}) // Load projects for demo selector fetch('/api/projects').then(r => r.json()).then(data => { if (data.projects) setAllProjects(data.projects) }).catch(() => {}) }, []) const handleSmtpSave = async () => { setSmtpLoading(true) setSmtpStatus(null) try { const res = await fetch('/api/admin/settings', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'save_smtp', smtp: { host: smtpHost, port: parseInt(smtpPort), secure: smtpSecure, user: smtpUser, pass: smtpPass, fromName: smtpFromName, fromEmail: smtpFromEmail }, }), }) const data = await res.json() if (data.success) { toast({ title: 'SMTP gespeichert' }) setSmtpStatus('saved') } else throw new Error(data.error) } catch (error) { toast({ title: 'Fehler', description: error instanceof Error ? error.message : 'Fehler', variant: 'destructive' }) } finally { setSmtpLoading(false) } } const handleSmtpTest = async () => { setSmtpLoading(true) setSmtpStatus(null) try { const res = await fetch('/api/admin/settings', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'test_smtp' }), }) const data = await res.json() if (data.success) { setSmtpStatus('connected') toast({ title: 'SMTP-Verbindung erfolgreich' }) } else { setSmtpStatus('error') toast({ title: 'Verbindung fehlgeschlagen', description: data.error, variant: 'destructive' }) } } catch (error) { setSmtpStatus('error') toast({ title: 'Fehler', variant: 'destructive' }) } finally { setSmtpLoading(false) } } const handleSmtpSendTest = async () => { if (!smtpTestEmail) return setSmtpLoading(true) try { const res = await fetch('/api/admin/settings', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'send_test_email', testEmail: smtpTestEmail }), }) const data = await res.json() if (data.success) toast({ title: data.message }) else toast({ title: 'Senden fehlgeschlagen', description: data.error, variant: 'destructive' }) } catch { toast({ title: 'Fehler', variant: 'destructive' }) } finally { setSmtpLoading(false) } } const handleContactEmailSave = async () => { setSmtpLoading(true) try { const res = await fetch('/api/admin/settings', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'save_contact_email', contactEmail }), }) const data = await res.json() if (data.success) toast({ title: 'Kontakt-E-Mail gespeichert' }) else throw new Error(data.error) } catch (error) { toast({ title: 'Fehler', description: error instanceof Error ? error.message : 'Fehler', variant: 'destructive' }) } finally { setSmtpLoading(false) } } const handleStripeSave = async () => { setStripeLoading(true) setStripeStatus(null) try { const res = await fetch('/api/admin/settings', { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ action: 'save_stripe', stripe: { publicKey: stripePublicKey, secretKey: stripeSecretKey, webhookSecret: stripeWebhookSecret, }, }), }) const data = await res.json() if (data.success) { setStripeStatus('saved') toast({ title: 'Stripe-Einstellungen gespeichert' }) } else throw new Error(data.error) } catch (error) { setStripeStatus('error') toast({ title: 'Fehler', description: error instanceof Error ? error.message : 'Fehler', variant: 'destructive' }) } finally { setStripeLoading(false) } } return (
{/* Contact Email */}

Kontakt-E-Mail

E-Mail-Adresse für das Kontaktformular auf der Landing Page. Hierhin werden Anfragen gesendet.

setContactEmail(e.target.value)} placeholder="app@lageplan.ch" />
{/* Registration Notification */}

Registrierungs-Benachrichtigung

E-Mail-Adresse, an die bei neuen Registrierungen eine Benachrichtigung gesendet wird. Leer lassen = keine Benachrichtigung.

setNotifyRegistrationEmail(e.target.value)} placeholder="admin@lageplan.ch" />
{/* SMTP Settings */}

E-Mail / SMTP Konfiguration

SMTP-Server für den E-Mail-Versand konfigurieren. Empfohlen: TLS auf Port 587. Passwörter werden verschlüsselt in der Datenbank gespeichert.

setSmtpHost(e.target.value)} placeholder="smtp.gmail.com" />
setSmtpPort(e.target.value)} placeholder="587" />
setSmtpUser(e.target.value)} placeholder="user@example.com" />
setSmtpPass(e.target.value)} placeholder="App-Passwort oder SMTP-Passwort" />
setSmtpFromName(e.target.value)} placeholder="Lageplan" />
setSmtpFromEmail(e.target.value)} placeholder="noreply@lageplan.ch" />
{smtpStatus === 'connected' && Verbunden} {smtpStatus === 'error' && Fehlgeschlagen} {smtpStatus === 'saved' && Gespeichert}
setSmtpTestEmail(e.target.value)} placeholder="empfaenger@example.com" className="max-w-xs" />
{/* Stripe Settings */}

Stripe / Spenden-Konfiguration

Stripe API-Keys für die Spendenseite konfigurieren. Unterstützt Kreditkarte, Twint und weitere Zahlungsmethoden. Keys findest du im Stripe Dashboard.

setStripePublicKey(e.target.value)} placeholder="pk_live_..." />
setStripeSecretKey(e.target.value)} placeholder="sk_live_..." />
setStripeWebhookSecret(e.target.value)} placeholder="whsec_..." />

Webhook-Endpoint: {typeof window !== 'undefined' ? window.location.origin : ''}/api/donate/webhook

{stripeStatus === 'saved' && Gespeichert} {stripeStatus === 'error' && Fehlgeschlagen}
{/* Demo Project */}

Live-Demo auf der Startseite

Wähle ein Projekt als Demo-Karte für die Landing Page. Besucher können die Karte sehen und zoomen, aber nichts bearbeiten.

{demoStatus === 'saved' && Gespeichert}
{demoProjectId && (

Vorschau: /demo

)}
{/* Symbol-Grösse */}

Standard Symbol-Grösse

Bestimmt die Standard-Grösse neuer Symbole auf der Karte. Kleinere Werte = kleinere Symbole.

setDefaultSymbolScale(e.target.value)} className="flex-1" /> {defaultSymbolScale}x
0.5x (klein) 5x (gross)
{symbolScaleStatus === 'saved' && Gespeichert}
{/* App Info */}

System-Info

Version1.0.0
FrameworkNext.js 14.1
DatenbankPostgreSQL 16
Benutzer{usersCount}
Mandanten{tenantsCount}
Symbole{iconsCount}
{/* Quick Actions */}

Schnellaktionen

) }