feat(T01): auth + user management + RBAC + base frontend + i18n

- Backend: FastAPI, JWT auth (HS256), bcrypt, RBAC middleware
- User CRUD (admin-only), soft-delete, pagination
- Pydantic BaseSettings config, async SQLAlchemy 2.0
- 50 backend tests, 88% coverage
- Frontend: Next.js 14 App Router, Tailwind, design tokens
- Login page, auth context, API client with auto-refresh
- i18n: next-intl, DE/EN (31 keys each)
- 6 base UI components (Button, Input, Card, Table, Modal, Toast)
- 12 frontend tests, npm build success
This commit is contained in:
2026-07-14 11:51:32 +02:00
parent 5459a43e2b
commit d89304845a
56 changed files with 7581 additions and 9 deletions
+43
View File
@@ -0,0 +1,43 @@
import { ReactNode } from 'react';
interface TableProps<T> {
columns: { key: string; label: string; render?: (row: T) => ReactNode }[];
data: T[];
rowKey: (row: T) => string;
}
export function Table<T extends Record<string, any>>({ columns, data, rowKey }: TableProps<T>) {
return (
<div className="overflow-x-auto">
<table className="w-full border-collapse">
<thead>
<tr className="border-b border-border">
{columns.map((col) => (
<th key={col.key} className="text-left py-3 px-4 font-medium text-text-muted text-sm">
{col.label}
</th>
))}
</tr>
</thead>
<tbody>
{data.map((row) => (
<tr key={rowKey(row)} className="border-b border-border hover:bg-background/50">
{columns.map((col) => (
<td key={col.key} className="py-3 px-4 text-text">
{col.render ? col.render(row) : String(row[col.key] ?? '')}
</td>
))}
</tr>
))}
{data.length === 0 && (
<tr>
<td colSpan={columns.length} className="py-8 text-center text-text-muted">
No data available
</td>
</tr>
)}
</tbody>
</table>
</div>
);
}