Kunden: Filter, Zaehler und Abzeichen als reine Funktionen (lib/customerList.js, Tests)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
35e2761e68
commit
4b6ab7505a
3 files changed
+156
-11
No files matched your search
@@ -0,0 +1,82 @@
|
||||
// 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: '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`. Die Stufe `lost` erscheint nur im Reiter `all`.
|
||||
*/
|
||||
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') 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 || ''}`.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: 'plain' })
|
||||
}
|
||||
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 || '–'
|
||||
}
|
||||
+1
-11
@@ -5,17 +5,7 @@ export function isInvoiceReady(c) {
|
||||
return Boolean(c && c.name && c.email && c.street && c.city && c.postalCode)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
export { customerStage, isArchived, filterCustomers, stageCounts } from './customerList'
|
||||
|
||||
/** Kunde archivieren / wiederherstellen. */
|
||||
export async function setCustomerArchived(customer, archived) {
|
||||
|
||||
Reference in new issue
Block a user