195 lines
6.6 KiB
TypeScript
195 lines
6.6 KiB
TypeScript
import { useQuery } from '@tanstack/react-query';
|
|
import { contractApi } from '../../services/api';
|
|
import Modal from '../ui/Modal';
|
|
import Badge from '../ui/Badge';
|
|
import Card from '../ui/Card';
|
|
import CopyButton from '../ui/CopyButton';
|
|
import type { ContractType, ContractStatus } from '../../types';
|
|
|
|
const typeLabels: Record<ContractType, string> = {
|
|
ELECTRICITY: 'Strom',
|
|
GAS: 'Gas',
|
|
DSL: 'DSL',
|
|
CABLE: 'Kabelinternet',
|
|
FIBER: 'Glasfaser',
|
|
MOBILE: 'Mobilfunk',
|
|
TV: 'TV',
|
|
CAR_INSURANCE: 'KFZ-Versicherung',
|
|
};
|
|
|
|
const statusLabels: Record<ContractStatus, string> = {
|
|
DRAFT: 'Entwurf',
|
|
PENDING: 'Ausstehend',
|
|
ACTIVE: 'Aktiv',
|
|
CANCELLED: 'Gekündigt',
|
|
EXPIRED: 'Abgelaufen',
|
|
DEACTIVATED: 'Deaktiviert',
|
|
};
|
|
|
|
const statusVariants: Record<ContractStatus, 'success' | 'warning' | 'danger' | 'default'> = {
|
|
ACTIVE: 'success',
|
|
PENDING: 'warning',
|
|
CANCELLED: 'danger',
|
|
EXPIRED: 'danger',
|
|
DRAFT: 'default',
|
|
DEACTIVATED: 'default',
|
|
};
|
|
|
|
interface ContractDetailModalProps {
|
|
contractId: number;
|
|
isOpen: boolean;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export default function ContractDetailModal({ contractId, isOpen, onClose }: ContractDetailModalProps) {
|
|
const { data, isLoading, error } = useQuery({
|
|
queryKey: ['contract', contractId],
|
|
queryFn: () => contractApi.getById(contractId),
|
|
enabled: isOpen,
|
|
});
|
|
|
|
const c = data?.data;
|
|
|
|
return (
|
|
<Modal isOpen={isOpen} onClose={onClose} title="Vertragsdetails" size="xl">
|
|
{isLoading && (
|
|
<div className="text-center py-8 text-gray-500">Laden...</div>
|
|
)}
|
|
|
|
{error && (
|
|
<div className="text-center py-8 text-red-600">Fehler beim Laden des Vertrags</div>
|
|
)}
|
|
|
|
{c && (
|
|
<div className="space-y-4">
|
|
{/* Header */}
|
|
<div className="flex items-center gap-3 pb-4 border-b">
|
|
<span className="text-xl font-bold font-mono flex items-center gap-2">
|
|
{c.contractNumber}
|
|
<CopyButton value={c.contractNumber} />
|
|
</span>
|
|
<Badge>{typeLabels[c.type as ContractType] || c.type}</Badge>
|
|
<Badge variant={statusVariants[c.status as ContractStatus] || 'default'}>
|
|
{statusLabels[c.status as ContractStatus] || c.status}
|
|
</Badge>
|
|
</div>
|
|
|
|
{/* Anbieter & Tarif */}
|
|
{(c.providerName || c.provider?.name || c.tariffName || c.tariff?.name) && (
|
|
<Card title="Anbieter & Tarif">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
{(c.providerName || c.provider?.name) && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Anbieter</dt>
|
|
<dd className="flex items-center gap-1">
|
|
{c.providerName || c.provider?.name}
|
|
<CopyButton value={c.providerName || c.provider?.name || ''} />
|
|
</dd>
|
|
</div>
|
|
)}
|
|
{(c.tariffName || c.tariff?.name) && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Tarif</dt>
|
|
<dd className="flex items-center gap-1">
|
|
{c.tariffName || c.tariff?.name}
|
|
<CopyButton value={c.tariffName || c.tariff?.name || ''} />
|
|
</dd>
|
|
</div>
|
|
)}
|
|
{c.customerNumberAtProvider && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Kundennummer beim Anbieter</dt>
|
|
<dd className="font-mono flex items-center gap-1">
|
|
{c.customerNumberAtProvider}
|
|
<CopyButton value={c.customerNumberAtProvider} />
|
|
</dd>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Laufzeit */}
|
|
<Card title="Laufzeit">
|
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
{c.startDate && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Vertragsbeginn</dt>
|
|
<dd>{new Date(c.startDate).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })}</dd>
|
|
</div>
|
|
)}
|
|
{c.endDate && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Vertragsende</dt>
|
|
<dd>{new Date(c.endDate).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })}</dd>
|
|
</div>
|
|
)}
|
|
{c.contractDuration && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Laufzeit</dt>
|
|
<dd>{c.contractDuration.description}</dd>
|
|
</div>
|
|
)}
|
|
{c.cancellationPeriod && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Kündigungsfrist</dt>
|
|
<dd>{c.cancellationPeriod.description}</dd>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
|
|
{/* Portal-Zugangsdaten */}
|
|
{(c.portalUsername || c.provider?.portalUrl) && (
|
|
<Card title="Portal-Zugangsdaten">
|
|
<div className="grid grid-cols-2 gap-4">
|
|
{c.provider?.portalUrl && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Portal-URL</dt>
|
|
<dd>
|
|
<a
|
|
href={c.provider.portalUrl}
|
|
target="_blank"
|
|
rel="noopener noreferrer"
|
|
className="text-blue-600 hover:underline"
|
|
>
|
|
{c.provider.portalUrl}
|
|
</a>
|
|
</dd>
|
|
</div>
|
|
)}
|
|
{c.portalUsername && (
|
|
<div>
|
|
<dt className="text-sm text-gray-500">Benutzername</dt>
|
|
<dd className="font-mono flex items-center gap-1">
|
|
{c.portalUsername}
|
|
<CopyButton value={c.portalUsername} />
|
|
</dd>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Adresse */}
|
|
{c.address && (
|
|
<Card title="Lieferadresse">
|
|
<p>
|
|
{c.address.street} {c.address.houseNumber}
|
|
</p>
|
|
<p>{c.address.postalCode} {c.address.city}</p>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Notizen */}
|
|
{c.notes && (
|
|
<Card title="Notizen">
|
|
<p className="whitespace-pre-wrap text-gray-700">{c.notes}</p>
|
|
</Card>
|
|
)}
|
|
</div>
|
|
)}
|
|
</Modal>
|
|
);
|
|
}
|