- Kundenliste mit Reiter "Abgesagt" (vorher nur unter "Alle"), rotes Abzeichen, Suche auch nach Telefon - Kundenseite: "Absage eintragen" fuer Leads (Grund freiwillig); Vermerk "Abgesagt am TT.MM.JJJJ (Name): Grund" oben in die Notizen, offene Akquise-Tickets auf "Abgesagt"; roter Hinweis "nicht erneut anrufen" und "Wieder als Lead fuehren" - Neuer Lead (jetzt mit Telefon) und Neuer Kunde gleichen live mit allen Kunden ab (auch archivierte/abgesagte): Name ohne Rechtsform, E-Mail, Firmen-Domain (ohne Freemailer), Telefon; Abgesagte rot und zuerst, Knopf heisst dann "Trotzdem anlegen" - Uebersicht wird nach Speichern neu aufgebaut (key), damit kein alter Notizstand den Vermerk ueberschreibt Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
84 lines
3.2 KiB
JavaScript
84 lines
3.2 KiB
JavaScript
// Reine Funktionen der Kundenliste und der Kundenseite: Stufe, Filter, Zähler und Abzeichen.
|
||
// Ohne Importe, damit Liste, Zähler und Tests dieselbe Logik benutzen.
|
||
|
||
export function customerStage(c) {
|
||
const s = (c?.customerStatus || '').toLowerCase()
|
||
if (s === 'lead') return 'lead'
|
||
if (s === 'lost') return 'lost'
|
||
return 'customer' // Bestandsdaten ohne Status gelten als fester Kunde
|
||
}
|
||
|
||
/** Archiviert = aus der Standardansicht ausgeblendet (orthogonal zur CRM-Stufe). */
|
||
export function isArchived(c) {
|
||
return Boolean(c?.archived)
|
||
}
|
||
|
||
/** Reiter der Kundenliste in Anzeigereihenfolge. */
|
||
export const CUSTOMER_TABS = [
|
||
{ id: 'customer', label: 'Feste Kunden' },
|
||
{ id: 'lead', label: 'Leads' },
|
||
{ id: 'lost', label: 'Abgesagt' },
|
||
{ id: 'archived', label: 'Archiviert' },
|
||
{ id: 'all', label: 'Alle' },
|
||
]
|
||
|
||
/**
|
||
* Filtert die Kundenliste nach Reiter und Suchtext. Die Reihenfolge der Eingabe bleibt.
|
||
* Archivierte erscheinen nur im Reiter `archived`.
|
||
*/
|
||
export function filterCustomers(customers, { stage = 'customer', search = '' } = {}) {
|
||
const s = String(search || '').toLowerCase()
|
||
const matchesStage = (c) => {
|
||
const archived = isArchived(c)
|
||
if (stage === 'archived') return archived
|
||
if (archived) return false
|
||
if (stage === 'all') return true
|
||
if (stage === 'customer' || stage === 'lead' || stage === 'lost') return customerStage(c) === stage
|
||
return false
|
||
}
|
||
return (customers || []).filter((c) => {
|
||
if (!matchesStage(c)) return false
|
||
if (!s) return true
|
||
return `${c.name || ''} ${c.code || ''} ${c.location || ''} ${c.email || ''} ${c.contactName || ''} ${c.phone || ''}`.toLowerCase().includes(s)
|
||
})
|
||
}
|
||
|
||
/** Zähler je Reiter, berechnet mit derselben Filterfunktion wie die Liste (beachtet den Suchtext). */
|
||
export function stageCounts(customers, search = '') {
|
||
const counts = {}
|
||
for (const tab of CUSTOMER_TABS) counts[tab.id] = filterCustomers(customers, { stage: tab.id, search }).length
|
||
return counts
|
||
}
|
||
|
||
const STAGE_LABELS = { customer: 'Fester Kunde', lead: 'Lead', lost: 'Abgesagt' }
|
||
|
||
export function stageLabel(stage) {
|
||
return STAGE_LABELS[stage] || ''
|
||
}
|
||
|
||
/**
|
||
* Abzeichen eines Kunden in fester Reihenfolge: Wichtig, Stufe, Archiviert.
|
||
* Die Stufe „Fester Kunde“ ist kein Abzeichen. Mit `stage: false` entfällt die Stufe (Kundenseite, dort steht sie in der Eyebrow).
|
||
*/
|
||
export function customerBadges(c, { stage = true } = {}) {
|
||
const badges = []
|
||
if (c?.importantCustomer) badges.push({ key: 'important', label: 'Wichtig', tone: 'warn' })
|
||
if (stage) {
|
||
const st = customerStage(c)
|
||
if (st === 'lead') badges.push({ key: 'lead', label: stageLabel('lead'), tone: 'muted' })
|
||
else if (st === 'lost') badges.push({ key: 'lost', label: stageLabel('lost'), tone: 'danger' })
|
||
}
|
||
if (isArchived(c)) badges.push({ key: 'archived', label: 'Archiviert', tone: 'plain' })
|
||
return badges
|
||
}
|
||
|
||
/** Kleine Zeile über dem Titel der Kundenseite: „Kundennummer · Stufe“. */
|
||
export function customerEyebrow(c) {
|
||
return [String(c?.code || '').trim(), stageLabel(customerStage(c))].filter(Boolean).join(' · ')
|
||
}
|
||
|
||
/** Titel der Kundenseite: Name, sonst E-Mail, sonst Gedankenstrich. */
|
||
export function customerTitle(c) {
|
||
return c?.name || c?.email || '–'
|
||
}
|