import React, { useEffect, useState } from 'react'; import { formatDate, type Company, type DirectoryUser, type Tristate } from '../../types'; import { companiesApi, historyApi, type CompanyDetail } from '../../lib/api'; import { Modal, ConfirmDialog } from '../ui/Modal'; import { AvatarPicker } from '../ui/AvatarPicker'; import { Avatar } from '../ui/Avatar'; import { StarRating } from '../ui/StarRating'; import { Field, Pill, PrimaryButton, SecondaryButton, inputClass, labelClass } from '../ui/form'; import { MentionField } from '../../lib/mentions'; import { DictateButton } from '../ui/Dictate'; import { HistoryFeed } from '../history/HistoryFeed'; import { TRISTATE_LABELS } from '../contacts/contactUi'; import { useToast } from '../Toast'; import { useNavigation } from '../../lib/navigation'; import { useOptions, sortByLabel } from '../../lib/options'; import { useAuth } from '../../lib/auth'; interface CompanyModalProps { companyId: number | null; open: boolean; onClose: () => void; onSaved: () => void; users: DirectoryUser[]; industries: string[]; groups: string[]; } type Tab = 'stamm' | 'stammbaum' | 'historie'; const EMPTY = { name: '', group_name: '', industry: '', employees: '', website: '', address: '', rating: 0, is_customer: false, customer_state: 'aktiv' as 'aktiv' | 'alumni', freelancers: 'unbekannt' as Tristate, notes: '', owner_id: '' as number | '', primary_contact_id: '' as number | '', logo: null as string | null, }; export const CompanyModal: React.FC = ({ companyId, open, onClose, onSaved, users, industries, groups, }) => { const { toast } = useToast(); const { open: openEntity } = useNavigation(); const { industries: industryOptions } = useOptions(); const { user } = useAuth(); const [tab, setTab] = useState('stamm'); const [form, setForm] = useState({ ...EMPTY }); const [detail, setDetail] = useState(null); const [loading, setLoading] = useState(false); const [saving, setSaving] = useState(false); const [confirmDelete, setConfirmDelete] = useState(false); const isNew = companyId === null; useEffect(() => { if (!open) return; setTab('stamm'); if (isNew) { setDetail(null); /* * Beim Anlegen ist der angemeldete Benutzer voreingestellt - in aller Regel * kümmert sich der, der den Datensatz erfasst. Ändern lässt es sich weiterhin. */ setForm({ ...EMPTY, owner_id: user?.id ?? '' }); return; } let cancelled = false; setLoading(true); companiesApi .detail(companyId) .then((data) => { if (cancelled) return; setDetail(data); setForm({ ...EMPTY, ...toForm(data.company) }); }) .catch((err) => toast(err instanceof Error ? err.message : 'Laden fehlgeschlagen.', 'error')) .finally(() => !cancelled && setLoading(false)); return () => { cancelled = true; }; // eslint-disable-next-line react-hooks/exhaustive-deps }, [open, companyId]); const set = (key: K, value: (typeof EMPTY)[K]) => setForm((current) => ({ ...current, [key]: value })); const save = async () => { if (!form.name.trim()) { toast('Der Name des Unternehmens ist erforderlich.', 'error'); return; } setSaving(true); try { const body = { ...form, employees: form.employees === '' ? null : Number(form.employees), owner_id: form.owner_id === '' ? null : Number(form.owner_id), primary_contact_id: form.primary_contact_id === '' ? null : Number(form.primary_contact_id), }; if (isNew) { await companiesApi.create(body); toast(`${form.name} angelegt.`, 'success'); } else { await companiesApi.update(companyId, body); toast('Gespeichert.', 'success'); } onSaved(); onClose(); } catch (err) { toast(err instanceof Error ? err.message : 'Speichern fehlgeschlagen.', 'error'); } finally { setSaving(false); } }; const remove = async () => { if (isNew) return; try { await companiesApi.remove(companyId); toast('Unternehmen gelöscht.', 'success'); onSaved(); onClose(); } catch (err) { toast(err instanceof Error ? err.message : 'Löschen fehlgeschlagen.', 'error'); } finally { setConfirmDelete(false); } }; const addNote = async (text: string) => { if (!companyId) return; await historyApi.add('company', companyId, text); setDetail(await companiesApi.detail(companyId)); }; const tabs: Array<{ id: Tab; label: string; count?: number }> = [ { id: 'stamm', label: 'Stammdaten' }, { id: 'stammbaum', label: 'Stammbaum', count: (detail?.contacts.length ?? 0) + (detail?.former.length ?? 0), }, { id: 'historie', label: 'Historie', count: detail?.history.length }, ]; return ( <> {!isNew && ( )} Abbrechen {saving ? 'Speichern …' : 'Speichern'} } > {loading ? (

Wird geladen …

) : ( <> {!isNew && ( )} {(isNew || tab === 'stamm') && (
set('logo', value)} square />
set('name', event.target.value)} className={inputClass} /> set('group_name', event.target.value)} className={inputClass} list="company-groups" /> {groups.map((group) => ( set('employees', event.target.value)} className={inputClass} /> set('website', event.target.value)} placeholder="https://…" className={inputClass} /> {!isNew && (detail?.contacts.length ?? 0) > 0 && ( )}