added invoices and status in cockpit, created info button for contract status types
This commit is contained in:
@@ -4,6 +4,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { contractApi, uploadApi, meterApi, contractTaskApi, appSettingsApi } from '../../services/api';
|
||||
import { ContractEmailsSection } from '../../components/email';
|
||||
import { ContractDetailModal } from '../../components/contracts';
|
||||
import InvoicesSection from '../../components/contracts/InvoicesSection';
|
||||
import { useAuth } from '../../context/AuthContext';
|
||||
import Card from '../../components/ui/Card';
|
||||
import Button from '../../components/ui/Button';
|
||||
@@ -11,7 +12,7 @@ import Badge from '../../components/ui/Badge';
|
||||
import Input from '../../components/ui/Input';
|
||||
import Modal from '../../components/ui/Modal';
|
||||
import FileUpload from '../../components/ui/FileUpload';
|
||||
import { Edit, Trash2, Copy, Eye, EyeOff, ArrowLeft, ArrowRight, Download, ExternalLink, Plus, ChevronDown, ChevronUp, Gauge, CheckCircle, Circle, ClipboardList, MessageSquare, Calculator } from 'lucide-react';
|
||||
import { Edit, Trash2, Copy, Eye, EyeOff, ArrowLeft, ArrowRight, Download, ExternalLink, Plus, ChevronDown, ChevronUp, Gauge, CheckCircle, Circle, ClipboardList, MessageSquare, Calculator, Info, X } from 'lucide-react';
|
||||
import { calculateConsumption, calculateCosts } from '../../utils/energyCalculations';
|
||||
import CopyButton, { CopyableBlock } from '../../components/ui/CopyButton';
|
||||
import type { ContractType, ContractStatus, SimCard, MeterReading, ContractTask, ContractTaskSubtask } from '../../types';
|
||||
@@ -45,6 +46,42 @@ const statusVariants: Record<ContractStatus, 'success' | 'warning' | 'danger' |
|
||||
DEACTIVATED: 'default',
|
||||
};
|
||||
|
||||
// Status-Erklärungen für Info-Modal
|
||||
const statusDescriptions = [
|
||||
{ status: 'DRAFT', label: 'Entwurf', description: 'Vertrag wird noch vorbereitet', color: 'text-gray-600' },
|
||||
{ status: 'PENDING', label: 'Ausstehend', description: 'Wartet auf Aktivierung', color: 'text-yellow-600' },
|
||||
{ status: 'ACTIVE', label: 'Aktiv', description: 'Vertrag läuft normal', color: 'text-green-600' },
|
||||
{ status: 'EXPIRED', label: 'Abgelaufen', description: 'Laufzeit vorbei, läuft aber ohne Kündigung weiter', color: 'text-orange-600' },
|
||||
{ status: 'CANCELLED', label: 'Gekündigt', description: 'Aktive Kündigung eingereicht, Vertrag endet', color: 'text-red-600' },
|
||||
{ status: 'DEACTIVATED', label: 'Deaktiviert', description: 'Manuell beendet/archiviert', color: 'text-gray-500' },
|
||||
];
|
||||
|
||||
function StatusInfoModal({ isOpen, onClose }: { isOpen: boolean; onClose: () => void }) {
|
||||
if (!isOpen) return null;
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center">
|
||||
<div className="fixed inset-0 bg-black/20" onClick={onClose} />
|
||||
<div className="relative bg-white rounded-lg shadow-xl p-4 max-w-sm w-full mx-4">
|
||||
<div className="flex items-center justify-between mb-3">
|
||||
<h3 className="text-sm font-semibold text-gray-900">Vertragsstatus-Übersicht</h3>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600">
|
||||
<X className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
{statusDescriptions.map(({ status, label, description, color }) => (
|
||||
<div key={status} className="flex items-start gap-2">
|
||||
<span className={`font-medium text-sm min-w-[90px] ${color}`}>{label}</span>
|
||||
<span className="text-sm text-gray-600">{description}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
// Prüft ob die Laufzeit als "unbefristet" gilt (≤ 4 Wochen / 1 Monat / 30 Tage)
|
||||
function isUnlimitedDuration(durationCode: string): boolean {
|
||||
const match = durationCode.match(/^(\d+)([TMWJ])$/);
|
||||
@@ -1203,6 +1240,9 @@ export default function ContractDetail() {
|
||||
// Bestätigungsdialog für Folgevertrag
|
||||
const [showFollowUpConfirm, setShowFollowUpConfirm] = useState(false);
|
||||
|
||||
// Status-Info Modal
|
||||
const [showStatusInfo, setShowStatusInfo] = useState(false);
|
||||
|
||||
const { data, isLoading } = useQuery({
|
||||
queryKey: ['contract', id],
|
||||
queryFn: () => contractApi.getById(contractId),
|
||||
@@ -1399,6 +1439,13 @@ export default function ContractDetail() {
|
||||
<h1 className="text-2xl font-bold">{c.contractNumber}</h1>
|
||||
<Badge>{typeLabels[c.type]}</Badge>
|
||||
<Badge variant={statusVariants[c.status]}>{statusLabels[c.status]}</Badge>
|
||||
<button
|
||||
onClick={() => setShowStatusInfo(true)}
|
||||
className="text-gray-400 hover:text-blue-600 transition-colors"
|
||||
title="Status-Erklärung"
|
||||
>
|
||||
<Info className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
{c.customer && (
|
||||
<p className="text-gray-500 ml-10">
|
||||
@@ -2151,6 +2198,14 @@ export default function ContractDetail() {
|
||||
bonus={c.energyDetails.bonus}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Rechnungen */}
|
||||
<InvoicesSection
|
||||
ecdId={c.energyDetails.id}
|
||||
invoices={c.energyDetails.invoices || []}
|
||||
contractId={contractId}
|
||||
canEdit={hasPermission('contracts:update') && !isCustomer}
|
||||
/>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
@@ -2589,6 +2644,9 @@ export default function ContractDetail() {
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
{/* Status-Info Modal */}
|
||||
<StatusInfoModal isOpen={showStatusInfo} onClose={() => setShowStatusInfo(false)} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user