gdpr audit implemented, email log, vollmachten, pdf delete cancel data privacy and vollmachten, removed message no id card in engergy car, and other contracts that are not telecom contracts, added insert counter for engery

This commit is contained in:
2026-03-21 11:59:53 +01:00
parent 09e87c951b
commit c3edb8ad2e
1491 changed files with 265550 additions and 1292 deletions
+47 -4
View File
@@ -9,7 +9,8 @@ import Input from '../../components/ui/Input';
import Select from '../../components/ui/Select';
import Badge from '../../components/ui/Badge';
import CopyButton from '../../components/ui/CopyButton';
import { Plus, Search, Eye, Edit, Trash2, User, Users, ChevronDown, ChevronRight, Info, X } from 'lucide-react';
import { Plus, Search, Eye, Edit, Trash2, User, Users, ChevronDown, ChevronRight, Info, X, ShieldAlert } from 'lucide-react';
import { gdprApi } from '../../services/api';
import type { Contract, ContractType, ContractStatus } from '../../types';
const typeLabels: Record<ContractType, string> = {
@@ -137,6 +138,26 @@ export default function ContractList() {
return [...ids];
}, [data?.data, isCustomerPortal, user?.customerId]);
// Vollmacht-Status für vertretene Kunden (Portal)
const { data: authStatusData } = useQuery({
queryKey: ['my-authorization-status'],
queryFn: () => gdprApi.getMyAuthorizationStatus(),
enabled: isCustomerPortal,
});
const unauthorizedCustomers = useMemo(() => {
if (!isCustomerPortal || !authStatusData?.data || !user?.representedCustomers) return [];
return authStatusData.data
.filter((s) => !s.hasAuthorization)
.map((s) => {
const cust = user.representedCustomers?.find((c) => c.id === s.customerId);
return {
customerId: s.customerId,
customerName: cust ? `${cust.firstName} ${cust.lastName}` : `Kunde ${s.customerId}`,
};
});
}, [authStatusData?.data, isCustomerPortal, user?.representedCustomers]);
// Baumstruktur für alle Kunden laden (Kundenportal)
const treeQueries = useQueries({
queries: allCustomerIds.map(customerId => ({
@@ -250,10 +271,10 @@ export default function ContractList() {
<div className="w-6" /> // Platzhalter für Ausrichtung
) : null}
<span className="font-mono flex items-center gap-1">
<Link to={`/contracts/${contract.id}`} className="font-mono flex items-center gap-1 hover:text-blue-600 hover:underline">
{contract.contractNumber}
<CopyButton value={contract.contractNumber} />
</span>
</Link>
<Badge>{typeLabels[contract.type as ContractType] || contract.type}</Badge>
<Badge variant={statusVariants[contract.status as ContractStatus] || 'default'}>
{statusLabels[contract.status as ContractStatus] || contract.status}
@@ -383,6 +404,24 @@ export default function ContractList() {
)}
</Card>
))}
{/* Kunden ohne Vollmacht */}
{unauthorizedCustomers.map((uc) => (
<Card key={`no-auth-${uc.customerId}`}>
<div className="flex items-center gap-3 mb-2 pb-3 border-b">
<ShieldAlert className="w-5 h-5 text-amber-500" />
<h2 className="text-lg font-semibold text-gray-900">
Verträge von {uc.customerName}
</h2>
</div>
<div className="flex items-center gap-3 py-6 text-center justify-center">
<ShieldAlert className="w-5 h-5 text-amber-500" />
<p className="text-sm text-gray-600">
Einwilligung / Vollmacht fehlt. {uc.customerName} muss Ihnen zuerst eine Vollmacht erteilen.
</p>
</div>
</Card>
))}
</div>
) : (
/* Standard-Ansicht für Mitarbeiter */
@@ -416,7 +455,11 @@ export default function ContractList() {
<tbody>
{data.data.map((contract) => (
<tr key={contract.id} className="border-b hover:bg-gray-50">
<td className="py-3 px-4 font-mono text-sm">{contract.contractNumber}</td>
<td className="py-3 px-4 font-mono text-sm">
<Link to={`/contracts/${contract.id}`} className="text-blue-600 hover:underline">
{contract.contractNumber}
</Link>
</td>
{!isCustomer && (
<td className="py-3 px-4">
{contract.customer && (