From 27b3810250677c47d41464f80d84d78285c5fcd0 Mon Sep 17 00:00:00 2001 From: CCS Admin Date: Fri, 27 Feb 2026 15:26:20 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20add=20inline=20preview=20for=20Wochen?= =?UTF-8?q?=C3=BCbersicht=20reports?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Backend stores per-KW summary in report_data (count, ICD status, FG split) - WochenuebersichtViewer component shows expandable KW table with totals - Expand/collapse pattern matching ReportsPage (ChevronRight/Down, useReportData) Co-Authored-By: Claude Opus 4.6 --- backend/app/api/reports.py | 18 ++ frontend/src/pages/WochenuebersichtPage.tsx | 196 ++++++++++++++++---- 2 files changed, 181 insertions(+), 33 deletions(-) diff --git a/backend/app/api/reports.py b/backend/app/api/reports.py index 12f69b7..09dda82 100644 --- a/backend/app/api/reports.py +++ b/backend/app/api/reports.py @@ -360,11 +360,29 @@ def generate_wochenuebersicht( ) .first() ) + # Build per-KW summary for frontend preview + fg1, fg2 = fallgruppen + fg1_label, fg2_label = type_cfg["fg_labels"] + weeks_summary = [] + for kw in sorted(cases_by_kw.keys(), reverse=True): + kw_cases = cases_by_kw[kw] + weeks_summary.append({ + "kw": kw, + "count": len(kw_cases), + "with_icd": sum(1 for c in kw_cases if c.icd), + "fg1_count": sum(1 for c in kw_cases if c.fallgruppe == fg1), + "fg2_count": sum(1 for c in kw_cases if c.fallgruppe == fg2), + "gutachten": sum(1 for c in kw_cases if c.gutachten), + }) + report_data = { "export_type": export_type, "kw_von": kw_von, "kw_bis": kw_bis, "case_count": len(cases), + "fg1_label": fg1_label, + "fg2_label": fg2_label, + "weeks": weeks_summary, } if report: report.report_date = date.today() diff --git a/frontend/src/pages/WochenuebersichtPage.tsx b/frontend/src/pages/WochenuebersichtPage.tsx index dc1d37c..84bd899 100644 --- a/frontend/src/pages/WochenuebersichtPage.tsx +++ b/frontend/src/pages/WochenuebersichtPage.tsx @@ -1,9 +1,10 @@ -import { useCallback, useState } from 'react' -import { Download, FileSpreadsheet, Loader2, Plus, Upload } from 'lucide-react' +import { Fragment, useCallback, useState } from 'react' +import { ChevronDown, ChevronRight, Download, FileSpreadsheet, Loader2, Plus, Upload } from 'lucide-react' import api from '@/services/api' import { useAuth } from '@/context/AuthContext' import { useReports, + useReportData, useGenerateWochenuebersicht, useDeleteReports, useUploadWochenuebersichtIcd, @@ -16,7 +17,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select' import { - Table, TableBody, TableCell, TableHead, TableHeader, TableRow, + Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { Skeleton } from '@/components/ui/skeleton' import { Alert, AlertDescription } from '@/components/ui/alert' @@ -86,6 +87,10 @@ export function WochenuebersichtPage() { const [uploadSuccess, setUploadSuccess] = useState('') const uploadMutation = useUploadWochenuebersichtIcd() + // Inline expansion state + const [expandedId, setExpandedId] = useState(null) + const { data: reportData, isLoading: reportDataLoading } = useReportData(expandedId) + // Drag state const [isDragOver, setIsDragOver] = useState(false) @@ -296,38 +301,72 @@ export function WochenuebersichtPage() { - {reports.map((r) => ( - - {formatDate(r.report_date)} - {r.jahr} - KW {r.kw} - {REPORT_TYPE_LABELS[r.report_type] ?? r.report_type} - {formatDateTime(r.generated_at)} - - - {isAdmin && ( - + + + {isExpanded + ? + : } + {formatDate(r.report_date)} + + + {r.jahr} + KW {r.kw} + {REPORT_TYPE_LABELS[r.report_type] ?? r.report_type} + {formatDateTime(r.generated_at)} + e.stopPropagation()}> + + {isAdmin && ( + + )} + + + {isExpanded && ( + + + {reportDataLoading ? ( +
+ +
+ ) : reportData ? ( +
+ +
+ ) : ( +
+ Keine Vorschaudaten verfügbar. +
+ )} +
+
)} - - - ))} + + ) + })}
) : ( @@ -445,3 +484,94 @@ export function WochenuebersichtPage() { ) } + + +// --------------------------------------------------------------------------- +// Wochenübersicht Viewer (inline preview) +// --------------------------------------------------------------------------- + +interface WeekSummary { + kw: number + count: number + with_icd: number + fg1_count: number + fg2_count: number + gutachten: number +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +function WochenuebersichtViewer({ data }: { data: Record }) { + const weeks: WeekSummary[] = data?.weeks ?? [] + const fg1Label: string = data?.fg1_label ?? 'FG1' + const fg2Label: string = data?.fg2_label ?? 'FG2' + const kwVon: number = data?.kw_von ?? '?' + const kwBis: number = data?.kw_bis ?? '?' + const totalCases: number = data?.case_count ?? 0 + + if (!weeks.length) { + return ( +

+ Keine Vorschaudaten verfügbar. +

+ ) + } + + const totals = weeks.reduce( + (acc, w) => ({ + count: acc.count + w.count, + with_icd: acc.with_icd + w.with_icd, + fg1: acc.fg1 + w.fg1_count, + fg2: acc.fg2 + w.fg2_count, + gutachten: acc.gutachten + w.gutachten, + }), + { count: 0, with_icd: 0, fg1: 0, fg2: 0, gutachten: 0 }, + ) + + return ( +
+
+ KW {kwVon}–{kwBis} + {totalCases} Fälle gesamt + {totals.with_icd} mit ICD +
+ + + + KW + Fälle + {fg1Label} + {fg2Label} + Gutachten + mit ICD + + + + {weeks.map((w) => ( + + KW {w.kw} + {w.count} + {w.fg1_count} + {w.fg2_count} + {w.gutachten} + + {w.with_icd}/{w.count} + + + ))} + + + + Gesamt + {totals.count} + {totals.fg1} + {totals.fg2} + {totals.gutachten} + + {totals.with_icd}/{totals.count} + + + +
+
+ ) +}