import { useState, useMemo } from 'react' import { Link, useNavigate } from 'react-router-dom' import { useCustomers } from '../hooks/useCustomers' import { useAuth } from '../context/AuthContext' import { createLead } from '../lib/leads' import { CUSTOMER_TABS, customerBadges, customerTitle, filterCustomers, kundenartFehltAnzahl, stageCounts } from '../lib/customerList' import { isRowActivation } from '../lib/rowClick' import { findDuplicates } from '../lib/leadDuplicates' import DuplicateWarning from '../components/customer/DuplicateWarning' import KundenartAuswahl from '../components/KundenartAuswahl' import { kundenartPruefen, KUNDENART_AUSWAHL_HINWEIS } from '../lib/kundenFelder' import { PageHeader, Tabs, Button, Badge, EmptyState, Field, Dialog } from '../components/ui' export default function CustomersPage() { const { customers, loading, refresh, createCustomer } = useCustomers() const { user, isAdmin } = useAuth() const navigate = useNavigate() const [search, setSearch] = useState('') // 105 von 110 Eintraegen sind Leads der Lead-Automatik, deshalb startet die Liste bei den festen Kunden const [stage, setStage] = useState('customer') // customer | lead | lost | archived | all const [showCreate, setShowCreate] = useState(null) // null | 'lead' | 'customer' const [nurFehlt, setNurFehlt] = useState(false) // Schalter „Kundenart fehlt“ const filtered = useMemo(() => filterCustomers(customers, { stage, search, nurKundenartFehlt: nurFehlt }), [customers, stage, search, nurFehlt]) // Zähler mit derselben Funktion wie die Liste (beachten Suchtext und Schalter); bis zum Laden ohne Zahl const counts = useMemo(() => stageCounts(customers, search, { nurKundenartFehlt: nurFehlt }), [customers, search, nurFehlt]) const tabs = CUSTOMER_TABS.map((tab) => ({ id: tab.id, label: tab.label, count: loading ? undefined : counts[tab.id] })) let content if (loading) { content =
Wird geladen …
} else if (filtered.length === 0) { content = } else { content = ( {filtered.map((c) => { const path = `/customers/${c.$id}` return ( { if (isRowActivation(e)) navigate(path) }} > ) })}
Unternehmen Kundennummer Standort E-Mail Telefon
{customerTitle(c)} {customerBadges(c).map((b) => ( {b.label} ))}
{c.contactName &&
{c.contactName}
}
{c.code || –} {c.location || '–'} {c.email || '–'} {c.phone || '–'}
) } return (
{isAdmin && ( )} } />
setSearch(e.target.value)} />
{content} {showCreate === 'lead' && ( setShowCreate(null)} onDone={async (data) => { const r = await createLead(data, user) setShowCreate(null) refresh() return r }} /> )} {showCreate === 'customer' && isAdmin && ( setShowCreate(null)} onCreate={async (data) => { const r = await createCustomer(data) if (r.success) { setShowCreate(null) setStage('customer') refresh() } return r }} /> )}
) } function CreateLeadForm({ customers, onCancel, onDone }) { const [company, setCompany] = useState('') const [email, setEmail] = useState('') const [phone, setPhone] = useState('') const [kundenart, setKundenart] = useState('') const [busy, setBusy] = useState(false) const [error, setError] = useState(null) // Abgleich mit allen Kunden (auch archivierten und abgesagten), damit niemand doppelt angerufen wird const matches = useMemo(() => findDuplicates(customers, { name: company, email, phone }), [customers, company, email, phone]) const submit = async (e) => { e.preventDefault() if (!company.trim()) { setError('Unternehmen erforderlich'); return } const f = kundenartPruefen(kundenart) if (f) { setError(f); return } setBusy(true); setError(null) try { await onDone({ company: company.trim(), email: email.trim(), phone: phone.trim(), kundenart }) } catch (err) { setError(err.message || 'Fehler') setBusy(false) } } return ( } > {error &&
{error}
}

Fuer einen Lead reichen Unternehmen und E-Mail oder Telefon. Es wird automatisch ein Akquise-Ticket erstellt.

setCompany(e.target.value)} required /> setEmail(e.target.value)} /> setPhone(e.target.value)} />
) } // Fester Kunde mit Zugang zum Kundenportal (nur Admins; legt den Login im Portal an) export function CreateCustomerForm({ customers, onCancel, onCreate }) { const [form, setForm] = useState({ name: '', email: '', code: '', phone: '', location: '', password: '', kundenart: '' }) const [busy, setBusy] = useState(false) const [error, setError] = useState(null) const matches = useMemo( () => findDuplicates(customers, { name: form.name, email: form.email, phone: form.phone }), [customers, form.name, form.email, form.phone] ) const set = (field) => (e) => setForm((f) => ({ ...f, [field]: e.target.value })) const submit = async (e) => { e.preventDefault() if (form.password.length < 8) { setError('Das Portal-Passwort muss mindestens 8 Zeichen haben.'); return } const f = kundenartPruefen(form.kundenart) if (f) { setError(f); return } setBusy(true); setError(null) const r = await onCreate({ ...form, name: form.name.trim(), email: form.email.trim() }) if (!r.success) { setError(r.error || 'Kunde konnte nicht angelegt werden.') setBusy(false) } } return ( } > {error &&
{error}
}
setForm((f) => ({ ...f, kundenart: v }))} disabled={busy} />
) }