import { useRef, useState } from 'react'; import { Modal } from '../../components/Modal'; import { useContracts, useCreateContract, useUpdateContract, useDeleteContract, useContractFiles, useUploadContractFile, useDeleteContractFile, } from '../hooks'; import { contractFilesApi } from '../api'; import type { Contract, ContractFile, ContractStatus, CreateContractPayload, } from '../types'; import styles from './CompanyDetailPage.module.css'; // ============================================================ // Constants // ============================================================ const STATUS_LABELS: Record = { DRAFT: 'Entwurf', ACTIVE: 'Aktiv', EXPIRED: 'Abgelaufen', CANCELLED: 'Storniert', }; const STATUS_COLORS: Record = { DRAFT: { bg: '#f3f4f6', color: '#6b7280' }, ACTIVE: { bg: '#dcfce7', color: '#16a34a' }, EXPIRED: { bg: '#fef3c7', color: '#d97706' }, CANCELLED: { bg: '#fee2e2', color: '#dc2626' }, }; const ALLOWED_TYPES = '.pdf,.doc,.docx,.xlsx,.xls'; const MAX_FILE_SIZE = 25 * 1024 * 1024; // 25 MB // ============================================================ // Helpers // ============================================================ function formatDate(iso: string | null): string { if (!iso) return '—'; return new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', }); } function formatValue(val: string | null, currency = 'EUR'): string { if (!val) return '—'; const num = parseFloat(val); if (isNaN(num)) return val; return new Intl.NumberFormat('de-DE', { style: 'currency', currency, minimumFractionDigits: 0, maximumFractionDigits: 2, }).format(num); } function formatFileSize(bytes: number): string { if (bytes < 1024) return `${bytes} B`; if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(0)} KB`; return `${(bytes / (1024 * 1024)).toFixed(1)} MB`; } function fileIcon(mimeType: string): string { if (mimeType === 'application/pdf') return '📄'; if (mimeType.includes('word')) return '📝'; if (mimeType.includes('excel') || mimeType.includes('spreadsheet')) return '📊'; return '📎'; } // ============================================================ // Props // ============================================================ interface ContractsCardProps { companyId: string; } // ============================================================ // Component // ============================================================ export function ContractsCard({ companyId }: ContractsCardProps) { const { data, isLoading } = useContracts(companyId); const deleteMut = useDeleteContract(companyId); const [isAddOpen, setAddOpen] = useState(false); const [editContract, setEditContract] = useState(null); const contracts: Contract[] = data?.data ?? []; const handleDelete = (contract: Contract) => { if ( window.confirm( `Vertrag "${contract.title}" wirklich löschen? Alle angehängten Dateien werden ebenfalls gelöscht.`, ) ) { deleteMut.mutate(contract.id); } }; return (

Verträge ({contracts.length})

{isLoading ? (

Laden...

) : contracts.length === 0 ? (

Keine Verträge vorhanden

) : (
{contracts.map((c) => (
{c.title}
{STATUS_LABELS[c.status]} {c.value && ( {formatValue(c.value, c.currency)} )} {formatDate(c.startDate)} {c.endDate ? ` – ${formatDate(c.endDate)}` : ''}
))}
)} {/* Create Modal */} setAddOpen(false)} companyId={companyId} mode="create" /> {/* Edit Modal */} {editContract && ( setEditContract(null)} companyId={companyId} mode="edit" contract={editContract} /> )}
); } // ============================================================ // Contract Form Modal (Create + Edit) // ============================================================ interface ContractFormModalProps { isOpen: boolean; onClose: () => void; companyId: string; mode: 'create' | 'edit'; contract?: Contract; } const labelStyle: React.CSSProperties = { fontSize: '0.875rem', fontWeight: 500, color: 'var(--color-text)', marginBottom: '0.25rem', display: 'block', }; const inputStyle: React.CSSProperties = { width: '100%', padding: '0.625rem 0.75rem', border: '1px solid var(--color-border)', borderRadius: 'var(--radius-sm)', fontSize: '0.9375rem', outline: 'none', boxSizing: 'border-box', background: 'var(--color-bg-card)', color: 'var(--color-text)', }; function ContractFormModal({ isOpen, onClose, companyId, mode, contract, }: ContractFormModalProps) { const createMut = useCreateContract(companyId); const updateMut = useUpdateContract(companyId); const [title, setTitle] = useState(contract?.title ?? ''); const [status, setStatus] = useState(contract?.status ?? 'DRAFT'); const [startDate, setStartDate] = useState( contract?.startDate ? contract.startDate.substring(0, 10) : '', ); const [endDate, setEndDate] = useState( contract?.endDate ? contract.endDate.substring(0, 10) : '', ); const [value, setValue] = useState(contract?.value ?? ''); const [currency, setCurrency] = useState(contract?.currency ?? 'EUR'); const [notes, setNotes] = useState(contract?.notes ?? ''); const [error, setError] = useState(''); const isPending = createMut.isPending || updateMut.isPending; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); setError(''); if (!title.trim()) { setError('Titel ist ein Pflichtfeld.'); return; } const payload: CreateContractPayload = { title: title.trim(), status, startDate: startDate || null, endDate: endDate || null, value: value.trim() || null, currency: currency || 'EUR', notes: notes.trim() || null, }; if (mode === 'create') { createMut.mutate(payload, { onSuccess: () => onClose(), onError: (err: unknown) => { const msg = (err as { response?: { data?: { error?: { message?: string } } } }) ?.response?.data?.error?.message ?? 'Fehler beim Erstellen'; setError(msg); }, }); } else if (contract) { updateMut.mutate( { contractId: contract.id, data: payload }, { onSuccess: () => onClose(), onError: (err: unknown) => { const msg = (err as { response?: { data?: { error?: { message?: string } } } }) ?.response?.data?.error?.message ?? 'Fehler beim Speichern'; setError(msg); }, }, ); } }; return (
{error && (
{error}
)} {/* Titel */}
setTitle(e.target.value)} placeholder="z.B. Wartungsvertrag 2026" required autoFocus />
{/* Status */}
{/* Laufzeit */}
setStartDate(e.target.value)} />
setEndDate(e.target.value)} />
{/* Wert + Währung */}
setValue(e.target.value)} placeholder="0.00" />
{/* Notizen */}