import React, { useEffect, useState } from 'react'; import { Box, Text, useInput } from 'ink'; import type { CountryDTO } from '@effigenix/api-client'; import { useNavigation } from '../../../state/navigation-context.js'; import { useSuppliers } from '../../../hooks/useSuppliers.js'; import { FormInput } from '../../shared/FormInput.js'; import { CountryPicker } from '../../shared/CountryPicker.js'; import { LoadingSpinner } from '../../shared/LoadingSpinner.js'; import { ErrorDisplay } from '../../shared/ErrorDisplay.js'; import { client } from '../../../utils/api-client.js'; import { DEFAULT_COUNTRY, DACH_FALLBACK } from '../../shared/country-defaults.js'; type Field = 'name' | 'phone' | 'email' | 'contactPerson' | 'street' | 'houseNumber' | 'postalCode' | 'city' | 'countryPicker' | 'paymentDueDays'; const FIELDS: Field[] = ['name', 'phone', 'email', 'contactPerson', 'street', 'houseNumber', 'postalCode', 'city', 'countryPicker', 'paymentDueDays']; const FIELD_LABELS: Record = { name: 'Name *', phone: 'Telefon *', email: 'E-Mail', contactPerson: 'Ansprechpartner', street: 'Straße', houseNumber: 'Hausnummer', postalCode: 'PLZ', city: 'Stadt', countryPicker: 'Land', paymentDueDays: 'Zahlungsziel (Tage)', }; export function SupplierCreateScreen() { const { replace, back } = useNavigation(); const { createSupplier, loading, error, clearError } = useSuppliers(); const [values, setValues] = useState, string>>({ name: '', phone: '', email: '', contactPerson: '', street: '', houseNumber: '', postalCode: '', city: '', paymentDueDays: '', }); const [activeField, setActiveField] = useState('name'); const [fieldErrors, setFieldErrors] = useState>>({}); const [countryQuery, setCountryQuery] = useState(''); const [countryCode, setCountryCode] = useState(DEFAULT_COUNTRY.code); const [countryName, setCountryName] = useState(DEFAULT_COUNTRY.name); const [countries, setCountries] = useState([]); useEffect(() => { client.countries.search().then(setCountries).catch(() => setCountries(DACH_FALLBACK)); }, []); const setField = (field: Exclude) => (value: string) => { setValues((v) => ({ ...v, [field]: value })); }; useInput((_input, key) => { if (loading) return; if (key.tab || key.downArrow) { setActiveField((f) => { const idx = FIELDS.indexOf(f); return FIELDS[(idx + 1) % FIELDS.length] ?? f; }); } if (key.upArrow) { setActiveField((f) => { const idx = FIELDS.indexOf(f); return FIELDS[(idx - 1 + FIELDS.length) % FIELDS.length] ?? f; }); } if (key.escape) back(); }); const handleSubmit = async () => { const errors: Partial> = {}; if (!values.name.trim()) errors.name = 'Name ist erforderlich.'; if (!values.phone.trim()) errors.phone = 'Telefon ist erforderlich.'; setFieldErrors(errors); if (Object.keys(errors).length > 0) return; const result = await createSupplier({ name: values.name.trim(), phone: values.phone.trim(), ...(values.email.trim() ? { email: values.email.trim() } : {}), ...(values.contactPerson.trim() ? { contactPerson: values.contactPerson.trim() } : {}), ...(values.street.trim() ? { street: values.street.trim() } : {}), ...(values.houseNumber.trim() ? { houseNumber: values.houseNumber.trim() } : {}), ...(values.postalCode.trim() ? { postalCode: values.postalCode.trim() } : {}), ...(values.city.trim() ? { city: values.city.trim() } : {}), ...(countryCode ? { country: countryCode } : {}), ...(values.paymentDueDays.trim() ? { paymentDueDays: parseInt(values.paymentDueDays, 10) } : {}), }); if (result) replace('supplier-list'); }; const handleFieldSubmit = (field: Field) => (_value: string) => { const idx = FIELDS.indexOf(field); if (idx < FIELDS.length - 1) { setActiveField(FIELDS[idx + 1] ?? field); } else { void handleSubmit(); } }; if (loading) { return ( ); } return ( Neuer Lieferant {error && } {FIELDS.map((field) => { if (field === 'countryPicker') { return ( { setCountryCode(c.code); setCountryName(c.name); setCountryQuery(''); const idx = FIELDS.indexOf('countryPicker'); if (idx < FIELDS.length - 1) { setActiveField(FIELDS[idx + 1] ?? 'countryPicker'); } }} focus={activeField === 'countryPicker'} selectedName={countryName} /> ); } const f = field as Exclude; return ( ); })} Tab/↑↓ Feld wechseln · Enter auf letztem Feld speichern · Escape Abbrechen ); }