Erweitere VoTiAn NG um Fachfunktionen und verbessere die Listenoberfläche

Ergänze Auftragsbearbeitung, Disposition, Stammdaten, Kunden- und
Transporteurportale, Lagerverwaltung, Abrechnung, Exporte und Statistik.
Füge Kontoeinstellungen, Mitteilungen, Automatikdienste und Betriebsstatus
sowie die zugehörigen Tests und PHP-Abgleichsdokumentation hinzu.

Vergrößere die persönlichen Auftragslisten auf einheitliche Höhen und
richte Statusanzeigen sowie die Ranking-Vorschau-Steuerelemente bündig aus.

Validierung: 44 Frontendtests und Produktionsbuild erfolgreich.
Backend funktional unverändert gegenüber dem vollständigen Lauf mit 1.624
erfolgreichen und drei übersprungenen Tests. Layout im Browser und lokale
Bereitstellung geprüft.
This commit is contained in:
Sven committed 2026-10-20 11:19:43 +02:00
1 parent 363bc27c26
commit 781a2b82dc
1165 files changed
+74986 -1028

No files matched your search

+11
View File
@@ -0,0 +1,11 @@
import {useEffect,useState} from 'react';
import {request} from './api';
import {Modal,useDiscardConfirmation} from './FormElements';
import {CrmContacts} from './CrmContacts';
import type {CrmOptions} from './SalesWorkspace';
export function CustomerContacts({id,label,onClose}:{id:number;label:string;onClose:()=>void}){
const [options,setOptions]=useState<CrmOptions|null>(null),[error,setError]=useState(''),[dirty,setDirty]=useState(false),[ask,dialog]=useDiscardConfirmation();
useEffect(()=>{const c=new AbortController();request<CrmOptions>('/crm/options',{signal:c.signal}).then(v=>{if(!c.signal.aborted)setOptions(v);}).catch(e=>{if(!c.signal.aborted)setError(e.message);});return()=>c.abort();},[]);
async function close(){if(!dirty||await ask('Ungespeicherte Kontaktänderungen verwerfen?'))onClose();}
return <><Modal title={`Kontakte · ${label}`} wide onClose={()=>void close()}><div className="modal-body">{error&&<p className="alert error" role="alert">{error}</p>}{options?<CrmContacts options={options} initialCustomer={{id,label}} onDirtyChange={setDirty}/>:!error&&<p>Kontakte werden geladen …</p>}</div></Modal>{dialog}</>;
}