refactor(admin): split einwilligungen page.tsx into colocated components

Extract nav tabs, detail modal, table row, stats grid, search/filter,
records table, pagination, and data-loading hook into _components/ and
_hooks/. page.tsx reduced from 833 to 114 LOC.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-15 08:20:50 +02:00
parent cc3a9a37dc
commit 92a730626d
10 changed files with 893 additions and 760 deletions

View File

@@ -0,0 +1,55 @@
'use client'
import { PAGE_SIZE } from '../_types'
interface PaginationProps {
currentPage: number
totalRecords: number
onPageChange: (page: number) => void
}
export function Pagination({ currentPage, totalRecords, onPageChange }: PaginationProps) {
const totalPages = Math.ceil(totalRecords / PAGE_SIZE)
return (
<div className="flex items-center justify-between">
<p className="text-sm text-gray-500">
Zeige {totalRecords === 0 ? 0 : (currentPage - 1) * PAGE_SIZE + 1}
{Math.min(currentPage * PAGE_SIZE, totalRecords)} von {totalRecords} Einträgen
</p>
<div className="flex items-center gap-2">
<button
onClick={() => onPageChange(Math.max(1, currentPage - 1))}
disabled={currentPage === 1}
className="px-3 py-1 text-sm text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200 disabled:opacity-50"
>
Zurück
</button>
{Array.from({ length: Math.min(totalPages, 5) }, (_, i) => {
const page = Math.max(1, Math.min(currentPage - 2, totalPages - 4)) + i
if (page < 1 || page > totalPages) return null
return (
<button
key={page}
onClick={() => onPageChange(page)}
className={`px-3 py-1 text-sm rounded-lg ${
page === currentPage
? 'text-white bg-purple-600'
: 'text-gray-600 bg-gray-100 hover:bg-gray-200'
}`}
>
{page}
</button>
)
})}
<button
onClick={() => onPageChange(Math.min(totalPages || 1, currentPage + 1))}
disabled={currentPage >= (totalPages || 1)}
className="px-3 py-1 text-sm text-gray-600 bg-gray-100 rounded-lg hover:bg-gray-200 disabled:opacity-50"
>
Weiter
</button>
</div>
</div>
)
}