From fd8be1d5c4351d771cbf9a4b905db3aebf6b24ba Mon Sep 17 00:00:00 2001 From: duffyduck Date: Mon, 27 Jul 2026 16:48:24 +0200 Subject: [PATCH] =?UTF-8?q?Kundenportal:=20Toggle=20"Deaktivierte=20Vertr?= =?UTF-8?q?=C3=A4ge=20anzeigen"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Admin-/Mitarbeiter-Blick (CustomerDetail) hatte den Toggle schon; jetzt auch in der Kundenportal-Vertragsübersicht (ContractList, Portal-Zweig). Button nur bei isCustomerPortal, reicht includeDeactivated an die getTreeForCustomer-Queries durch (showDeactivated im Query-Key → frischer Fetch beim Umschalten). Security: derselbe Endpoint hinter canAccessCustomer (R120) – der Portal-Kunde bekommt nur eigene/vertretene Bäume, das Flag weitet nur den Status-Filter innerhalb der erlaubten Daten. Keine neue Exposition. Co-Authored-By: Claude Opus 4.7 --- docs/todo.md | 11 ++++++ frontend/src/pages/contracts/ContractList.tsx | 36 +++++++++++++------ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/docs/todo.md b/docs/todo.md index 9449c920..ef170cd5 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -97,6 +97,17 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung ## ✅ Erledigt +- [x] **👁 Kundenportal: Toggle „Deaktivierte Verträge anzeigen"** + - Der Admin-/Mitarbeiter-Blick (CustomerDetail) hatte den Toggle schon; + jetzt auch in der Kundenportal-Vertragsübersicht (`ContractList`, + Portal-Zweig). Button nur bei `isCustomerPortal`, reicht + `includeDeactivated` an die `getTreeForCustomer`-Queries durch + (`showDeactivated` im Query-Key → frischer Fetch beim Umschalten). + - Security: nutzt denselben Endpoint hinter `canAccessCustomer` + (R120) – Portal-Kunde sieht nur eigene/vertretene Bäume, das Flag + weitet nur den Status-Filter innerhalb der erlaubten Daten. Keine + neue Exposition. + - [x] **🔒 Mobilfunknetz: server-seitige Whitelist (Pentest-INFO)** - `mobileNetwork` akzeptierte serverseitig jeden (stripHtml-bereinigten) String – das Frontend-Dropdown beschränkte nur clientseitig. Jetzt diff --git a/frontend/src/pages/contracts/ContractList.tsx b/frontend/src/pages/contracts/ContractList.tsx index 5265a5d1..dfea187f 100644 --- a/frontend/src/pages/contracts/ContractList.tsx +++ b/frontend/src/pages/contracts/ContractList.tsx @@ -10,7 +10,7 @@ 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, ShieldAlert } from 'lucide-react'; +import { Plus, Search, Eye, EyeOff, Edit, Trash2, User, Users, ChevronDown, ChevronRight, Info, X, ShieldAlert } from 'lucide-react'; import { gdprApi } from '../../services/api'; import { formatDate } from '../../utils/dateFormat'; import { getContractTypeInfo } from '../../utils/contractInfo'; @@ -100,6 +100,9 @@ export default function ContractList() { // Status-Info Modal const [showStatusInfo, setShowStatusInfo] = useState(false); + // Toggle: deaktivierte Verträge im Kundenportal-Baum mit anzeigen + const [showDeactivated, setShowDeactivated] = useState(false); + const { hasPermission, isCustomer, isCustomerPortal, user } = useAuth(); const queryClient = useQueryClient(); @@ -167,8 +170,8 @@ export default function ContractList() { // Baumstruktur für alle Kunden laden (Kundenportal) const treeQueries = useQueries({ queries: allCustomerIds.map(customerId => ({ - queryKey: ['contract-tree', customerId], - queryFn: () => contractApi.getTreeForCustomer(customerId), + queryKey: ['contract-tree', customerId, showDeactivated], + queryFn: () => contractApi.getTreeForCustomer(customerId, showDeactivated), enabled: isCustomerPortal, })), }); @@ -341,14 +344,27 @@ export default function ContractList() {

Verträge

- {hasPermission('contracts:create') && !isCustomer && ( - - - - )} + )} + {hasPermission('contracts:create') && !isCustomer && ( + + + + )} +