feat(ui): introduce PferdReiterEingabe, NennungenTabelle, and NennungsMaske components
- Added `PferdReiterEingabe` for horse and rider selection with search functionality and keyboard navigation. - Implemented `NennungenTabelle` to display filtered registrations based on selected horse or rider. - Introduced `NennungsMaske` to combine search, table, and competition views for streamlined user interaction. - Extended types with `Veranstalter` interface and mock data for better context and integration. - Documented ÖTO-compliant tournament structure for frontend reference. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
@@ -0,0 +1,725 @@
|
||||
# Architektur-Dokumentation - Lead-Architekt
|
||||
|
||||
## 🏛️ System-Architektur-Übersicht
|
||||
|
||||
### Architektur-Typ
|
||||
|
||||
**Single Page Application (SPA)** mit Client-Side Routing
|
||||
|
||||
### Architektur-Pattern
|
||||
|
||||
- **Component-Based Architecture** (React)
|
||||
- **Container/Presentational Pattern**
|
||||
- **Data Mode Routing** (React Router v7)
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Architektur-Ziele
|
||||
|
||||
1. **Skalierbarkeit:** Modulare Komponenten für einfache Erweiterung
|
||||
2. **Wartbarkeit:** Klare Trennung von UI und Business Logic
|
||||
3. **Performance:** Code-Splitting, Lazy Loading
|
||||
4. **Type-Safety:** TypeScript für robuste Typisierung
|
||||
5. **Konsistenz:** Design System mit Material-UI
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ Anwendungs-Hierarchie
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ App.tsx │
|
||||
│ (RouterProvider) │
|
||||
└────────────────────────┬────────────────────────────────────┘
|
||||
│
|
||||
├─────────────────────────────────────┐
|
||||
│ │
|
||||
┌────▼─────┐ ┌────▼─────┐
|
||||
│ Login │ │ Dashboard│
|
||||
│ /login │ │ /admin │
|
||||
└──────────┘ └────┬─────┘
|
||||
│
|
||||
┌────────────────────────────────────┼─────────────────┐
|
||||
│ │ │
|
||||
┌────▼─────────────┐ ┌───────────▼──────┐ ┌──────▼─────────┐
|
||||
│ Veranstalter │ │ TurnierErstellen │ │ TurnierAnsicht │
|
||||
│ Verwaltung │ │ /veranstaltung/ │ │ /turnier/ │
|
||||
│ /veranstalter │ │ :id │ │ :veranstaltung │
|
||||
└──────────────────┘ └─────────┬────────┘ │ Id/:nr │
|
||||
│ └────────┬───────┘
|
||||
│ │
|
||||
┌────────────▼────────┐ │
|
||||
│ Veranstaltung- │ │
|
||||
│ Übersicht │ │
|
||||
│ (Turnier-Karten) │ │
|
||||
└─────────────────────┘ │
|
||||
│
|
||||
┌───────────────────────────────────────────────────────┘
|
||||
│
|
||||
┌────────────────┼────────────────┬─────────────────┬──────────────────┐
|
||||
│ │ │ │ │
|
||||
┌─────▼────┐ ┌────────▼──────┐ ┌─────▼──────┐ ┌──────▼───────┐ ┌──────▼──────┐
|
||||
│Stammdaten│ │ Organisation │ │ Bewerbe │ │ Artikel │ │ Abrechnung │
|
||||
│ Tab │ │ Tab │ │ Tab │ │ Tab │ │ Tab │
|
||||
└──────────┘ └───────────────┘ └────────────┘ └──────────────┘ └─────────────┘
|
||||
|
||||
┌────────────────┬─────────────────┬──────────────────┐
|
||||
│ │ │ │
|
||||
┌─────▼────┐ ┌────────▼──────┐ ┌──────▼───────┐ │
|
||||
│Nennungen │ │ Startlisten │ │Ergebnislisten│ │
|
||||
│ Tab │ │ Tab │ │ Tab │ │
|
||||
└──────────┘ └───────────────┘ └──────────────┘ │
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ Komponenten-Architektur
|
||||
|
||||
### Layer-Struktur
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────┐
|
||||
│ Presentation Layer │
|
||||
│ (React Components - UI Only) │
|
||||
│ - Login.tsx │
|
||||
│ - Dashboard.tsx │
|
||||
│ - TurnierAnsicht.tsx │
|
||||
└─────────────────┬───────────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────────┐
|
||||
│ Container Layer │
|
||||
│ (Smart Components - State Management) │
|
||||
│ - StammdatenTab.tsx │
|
||||
│ - BewerbeTab.tsx │
|
||||
│ - AbrechnungTab.tsx │
|
||||
│ - NennungenTab.tsx │
|
||||
└─────────────────┬───────────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────────┐
|
||||
│ Component Library Layer │
|
||||
│ (Reusable Components) │
|
||||
│ - PferdReiterEingabe.tsx │
|
||||
│ - NennungenTabelle.tsx │
|
||||
│ - Bewerbsliste.tsx │
|
||||
│ - VerkaufBuchungen.tsx │
|
||||
└─────────────────┬───────────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────────┐
|
||||
│ Material-UI Layer │
|
||||
│ (Design System - MUI Components) │
|
||||
│ - Box, Paper, Button, TextField, etc. │
|
||||
└─────────────────┬───────────────────────────┘
|
||||
│
|
||||
┌─────────────────▼───────────────────────────┐
|
||||
│ Style Layer │
|
||||
│ (Tailwind CSS v4 + CSS Variables) │
|
||||
│ - theme.css │
|
||||
│ - fonts.css │
|
||||
└─────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Routing-Architektur
|
||||
|
||||
### React Router v7 Data Mode
|
||||
|
||||
```typescript
|
||||
// routes.tsx
|
||||
const router = createBrowserRouter([
|
||||
{
|
||||
path: "/",
|
||||
element: <Login / >,
|
||||
},
|
||||
{
|
||||
path: "/admin",
|
||||
element: <Dashboard / >,
|
||||
},
|
||||
{
|
||||
path: "/veranstalter",
|
||||
element: <VeranstalterVerwaltung / >,
|
||||
},
|
||||
{
|
||||
path: "/veranstaltung/:id",
|
||||
element: <TurnierErstellen / >,
|
||||
},
|
||||
{
|
||||
path: "/turnier/:veranstaltungId/:nr",
|
||||
element: <TurnierAnsicht / >,
|
||||
},
|
||||
]);
|
||||
```
|
||||
|
||||
### URL-Struktur
|
||||
|
||||
```
|
||||
/ → Login
|
||||
/admin → Dashboard (Veranstaltungs-Übersicht)
|
||||
/veranstalter → Veranstalter-Verwaltung
|
||||
/veranstaltung/neu → Neue Veranstaltung (mit Veranstalter-Auswahl)
|
||||
/veranstaltung/:id → Veranstaltung-Übersicht (Turnier-Karten)
|
||||
/turnier/:veranstaltungId/neu → Neues Turnier → Stammdaten
|
||||
/turnier/:veranstaltungId/:nr → Turnier-Ansicht (8 Tabs)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💾 Daten-Architektur
|
||||
|
||||
### Aktueller Stand: **Client-Side Mock Data**
|
||||
|
||||
```typescript
|
||||
// Dashboard.tsx
|
||||
export const veranstaltungenData = [
|
||||
{
|
||||
id: number,
|
||||
name: string,
|
||||
veranstalter: string,
|
||||
ort: string,
|
||||
startDatum: string,
|
||||
endDatum: string,
|
||||
status: 'geplant' | 'laufend' | 'abgeschlossen',
|
||||
turniere: Turnier[]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Datenmodell-Hierarchie
|
||||
|
||||
```
|
||||
┌──────────────────┐
|
||||
│ Veranstalter │
|
||||
│ (Verein/Club) │
|
||||
└────────┬─────────┘
|
||||
│ 1:n
|
||||
│
|
||||
┌────────▼─────────┐
|
||||
│ Veranstaltung │
|
||||
│ (Event) │
|
||||
└────────┬─────────┘
|
||||
│ 1:n
|
||||
│
|
||||
┌────────▼─────────┐
|
||||
│ Turnier │
|
||||
│ (Competition) │
|
||||
└────────┬─────────┘
|
||||
│ 1:n
|
||||
│
|
||||
┌────────▼─────────┐
|
||||
│ Bewerb │
|
||||
│ (Contest) │
|
||||
└──────────────────┘
|
||||
|
||||
┌──────────────────┐
|
||||
│ Reiter │
|
||||
│ (Rider) │
|
||||
└────────┬─────────┘
|
||||
│ n:m
|
||||
│
|
||||
┌────────▼─────────┐
|
||||
│ Nennung │
|
||||
│ (Registration) │
|
||||
└────────┬─────────┘
|
||||
│ n:m
|
||||
│
|
||||
┌────────▼─────────┐
|
||||
│ Pferd │
|
||||
│ (Horse) │
|
||||
└──────────────────┘
|
||||
|
||||
┌──────────────────┐
|
||||
│ Buchung │
|
||||
│ (Transaction) │
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 Design System-Architektur
|
||||
|
||||
### Material-UI Theme
|
||||
|
||||
```typescript
|
||||
// Primärfarbe: Indigo
|
||||
primary: {
|
||||
main: '#3F51B5',
|
||||
light
|
||||
:
|
||||
'#7986CB',
|
||||
dark
|
||||
:
|
||||
'#303F9F',
|
||||
}
|
||||
|
||||
// Font-Größen (kompakt für Desktop)
|
||||
fontSize: {
|
||||
xs: '10px',
|
||||
sm
|
||||
:
|
||||
'11px',
|
||||
md
|
||||
:
|
||||
'13px',
|
||||
lg
|
||||
:
|
||||
'15px',
|
||||
}
|
||||
```
|
||||
|
||||
### Tailwind CSS v4 Integration
|
||||
|
||||
```css
|
||||
/* theme.css */
|
||||
@theme {
|
||||
--color-primary: #3f51b5;
|
||||
--color-primary-hover: #303f9f;
|
||||
--font-size-xs: 10px;
|
||||
--font-size-sm: 11px;
|
||||
--font-size-md: 13px;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Authentifizierung-Architektur
|
||||
|
||||
### Aktuell: **Demo-Modus**
|
||||
|
||||
```typescript
|
||||
// Login.tsx
|
||||
const DEMO_USER = 'admin';
|
||||
const DEMO_PASSWORD = 'Admin#1234';
|
||||
```
|
||||
|
||||
### Geplant: **JWT-basierte Authentifizierung**
|
||||
|
||||
```
|
||||
┌──────────┐ ┌──────────┐ ┌──────────┐
|
||||
│ Client │────────▶│ Backend │────────▶│ Database │
|
||||
│ React │ Login │ API │ Verify │ Users │
|
||||
└────┬─────┘ └────┬─────┘ └──────────┘
|
||||
│ │
|
||||
│◀───────────────────┤
|
||||
│ JWT Token │
|
||||
│ │
|
||||
│ API Calls │
|
||||
│ (with Token) │
|
||||
├───────────────────▶│
|
||||
│ │
|
||||
│◀───────────────────┤
|
||||
│ Response │
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 State Management-Architektur
|
||||
|
||||
### Aktuell: **React useState**
|
||||
|
||||
```typescript
|
||||
// Lokaler Component State
|
||||
const [activeTab, setActiveTab] = useState(0);
|
||||
const [nennungen, setNennungen] = useState<any[]>([]);
|
||||
const [selectedPferd, setSelectedPferd] = useState<any>(null);
|
||||
```
|
||||
|
||||
### Empfehlung für Skalierung:
|
||||
|
||||
#### Option 1: **React Context API** (für mittlere Komplexität)
|
||||
|
||||
```typescript
|
||||
// TurnierContext.tsx
|
||||
const TurnierContext = createContext();
|
||||
|
||||
export function TurnierProvider({children}) {
|
||||
const [turnier, setTurnier] = useState();
|
||||
const [bewerbe, setBewerbe] = useState([]);
|
||||
|
||||
return (
|
||||
<TurnierContext.Provider value = {
|
||||
{
|
||||
turnier, bewerbe
|
||||
}
|
||||
}>
|
||||
{
|
||||
children
|
||||
}
|
||||
</TurnierContext.Provider>
|
||||
)
|
||||
;
|
||||
}
|
||||
```
|
||||
|
||||
#### Option 2: **Zustand** (empfohlen für große Apps)
|
||||
|
||||
```typescript
|
||||
// store/turnierStore.ts
|
||||
import {create} from 'zustand';
|
||||
|
||||
export const useTurnierStore = create((set) => ({
|
||||
turnier: null,
|
||||
bewerbe: [],
|
||||
setTurnier: (turnier) => set({turnier}),
|
||||
addBewerb: (bewerb) => set((state) => ({
|
||||
bewerbe: [...state.bewerbe, bewerb]
|
||||
})),
|
||||
}));
|
||||
```
|
||||
|
||||
#### Option 3: **React Query / TanStack Query** (für Server State)
|
||||
|
||||
```typescript
|
||||
// hooks/useTurnier.ts
|
||||
import {useQuery} from '@tanstack/react-query';
|
||||
|
||||
export function useTurnier(id: string) {
|
||||
return useQuery({
|
||||
queryKey: ['turnier', id],
|
||||
queryFn: () => fetchTurnier(id),
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 Backend-Integration (Geplant)
|
||||
|
||||
### Option 1: **REST API**
|
||||
|
||||
```
|
||||
GET /api/veranstaltungen
|
||||
POST /api/veranstaltungen
|
||||
GET /api/veranstaltungen/:id
|
||||
PUT /api/veranstaltungen/:id
|
||||
DELETE /api/veranstaltungen/:id
|
||||
|
||||
GET /api/veranstaltungen/:id/turniere
|
||||
POST /api/veranstaltungen/:id/turniere
|
||||
GET /api/turniere/:id
|
||||
PUT /api/turniere/:id
|
||||
|
||||
GET /api/turniere/:id/bewerbe
|
||||
POST /api/turniere/:id/bewerbe
|
||||
PUT /api/bewerbe/:id
|
||||
|
||||
GET /api/turniere/:id/nennungen
|
||||
POST /api/nennungen
|
||||
GET /api/reiter/:id/nennungen
|
||||
GET /api/pferde/:id/nennungen
|
||||
|
||||
GET /api/turniere/:id/buchungen
|
||||
POST /api/buchungen
|
||||
GET /api/reiter/:id/buchungen
|
||||
```
|
||||
|
||||
### Option 2: **GraphQL** (empfohlen für komplexe Queries)
|
||||
|
||||
```graphql
|
||||
query GetTurnier($id: ID!) {
|
||||
turnier(id: $id) {
|
||||
id
|
||||
name
|
||||
stammdaten {
|
||||
znsDaten
|
||||
oetoTyp
|
||||
}
|
||||
bewerbe {
|
||||
id
|
||||
name
|
||||
klasse
|
||||
}
|
||||
nennungen {
|
||||
id
|
||||
reiter { vorname, nachname }
|
||||
pferd { name }
|
||||
bewerb { name }
|
||||
}
|
||||
buchungen {
|
||||
id
|
||||
text
|
||||
soll
|
||||
haben
|
||||
saldo
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Option 3: **Supabase** (empfohlen für Rapid Development)
|
||||
|
||||
```typescript
|
||||
// supabase/client.ts
|
||||
import {createClient} from '@supabase/supabase-js';
|
||||
|
||||
export const supabase = createClient(
|
||||
process.env.SUPABASE_URL,
|
||||
process.env.SUPABASE_ANON_KEY
|
||||
);
|
||||
|
||||
// Beispiel: Turniere abrufen
|
||||
const {data, error} = await supabase
|
||||
.from('turniere')
|
||||
.select('*, veranstaltung(name), bewerbe(*)')
|
||||
.eq('id', turnierId);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Performance-Optimierungen
|
||||
|
||||
### 1. **Code-Splitting**
|
||||
|
||||
```typescript
|
||||
// Lazy Loading für Tabs
|
||||
const BewerbeTab = lazy(() => import('./turnier/BewerbeTab'));
|
||||
const AbrechnungTab = lazy(() => import('./turnier/AbrechnungTab'));
|
||||
|
||||
<Suspense fallback = { < Loading / >
|
||||
}>
|
||||
{
|
||||
activeTab === 2 && <BewerbeTab / >
|
||||
}
|
||||
</Suspense>
|
||||
```
|
||||
|
||||
### 2. **Memoization**
|
||||
|
||||
```typescript
|
||||
// React.memo für teure Components
|
||||
export const NennungenTabelle = memo(({nennungen, selectedPferd}) => {
|
||||
// ...
|
||||
});
|
||||
|
||||
// useMemo für teure Berechnungen
|
||||
const gesamtSaldo = useMemo(() => {
|
||||
return buchungen.reduce((sum, b) => sum + b.saldo, 0);
|
||||
}, [buchungen]);
|
||||
```
|
||||
|
||||
### 3. **Virtualisierung** (für große Listen)
|
||||
|
||||
```typescript
|
||||
import {FixedSizeList} from 'react-window';
|
||||
|
||||
<FixedSizeList
|
||||
height = {600}
|
||||
itemCount = {bewerbe.length}
|
||||
itemSize = {50}
|
||||
>
|
||||
{({index, style})
|
||||
=>
|
||||
(
|
||||
<div style = {style} > {bewerbe[index].name} < /div>
|
||||
)
|
||||
}
|
||||
</FixedSizeList>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔒 Sicherheits-Architektur
|
||||
|
||||
### Geplante Security Features:
|
||||
|
||||
1. **Authentication & Authorization**
|
||||
- JWT Tokens mit Refresh
|
||||
- Role-Based Access Control (RBAC)
|
||||
- Session Management
|
||||
|
||||
2. **Input Validation**
|
||||
- Client-Side: React Hook Form + Zod
|
||||
- Server-Side: Express Validator / Joi
|
||||
|
||||
3. **XSS Protection**
|
||||
- Content Security Policy (CSP)
|
||||
- Sanitization von User Inputs
|
||||
|
||||
4. **CSRF Protection**
|
||||
- CSRF Tokens für State-Changing Operations
|
||||
|
||||
---
|
||||
|
||||
## 📦 Deployment-Architektur
|
||||
|
||||
### Empfohlener Stack:
|
||||
|
||||
```
|
||||
┌─────────────────┐
|
||||
│ Vercel/ │ → Frontend Hosting (React SPA)
|
||||
│ Netlify │
|
||||
└────────┬────────┘
|
||||
│
|
||||
│ HTTPS
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ Backend API │ → Node.js / Express / Nest.js
|
||||
│ (Railway/ │
|
||||
│ Render/AWS) │
|
||||
└────────┬────────┘
|
||||
│
|
||||
│
|
||||
┌────────▼────────┐
|
||||
│ Database │ → PostgreSQL (Supabase / RDS)
|
||||
│ (Supabase/ │
|
||||
│ AWS RDS) │
|
||||
└─────────────────┘
|
||||
```
|
||||
|
||||
### CI/CD Pipeline:
|
||||
|
||||
```
|
||||
GitHub Push
|
||||
│
|
||||
▼
|
||||
GitHub Actions
|
||||
│
|
||||
├──▶ Lint & Type Check
|
||||
│
|
||||
├──▶ Unit Tests
|
||||
│
|
||||
├──▶ Build
|
||||
│
|
||||
└──▶ Deploy to Vercel
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Skalierungs-Strategie
|
||||
|
||||
### Phase 1: **Prototyp** (Aktuell)
|
||||
|
||||
- Client-Side Mock Data
|
||||
- React useState
|
||||
- Keine Backend-Integration
|
||||
|
||||
### Phase 2: **MVP**
|
||||
|
||||
- Supabase Backend
|
||||
- REST API Integration
|
||||
- Basic Authentication
|
||||
- React Query für Server State
|
||||
|
||||
### Phase 3: **Production**
|
||||
|
||||
- Dedizierter Backend-Server
|
||||
- GraphQL API (optional)
|
||||
- Redis Caching
|
||||
- WebSocket für Real-Time Updates
|
||||
- Zustand für Global State
|
||||
|
||||
### Phase 4: **Enterprise**
|
||||
|
||||
- Microservices-Architektur
|
||||
- Event-Driven Architecture
|
||||
- CQRS Pattern
|
||||
- Message Queue (RabbitMQ / Kafka)
|
||||
- Multi-Tenant Support
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing-Strategie
|
||||
|
||||
### Unit Tests
|
||||
|
||||
```typescript
|
||||
// BewerbeTab.test.tsx
|
||||
import {render, screen} from '@testing-library/react';
|
||||
import {BewerbeTab} from './BewerbeTab';
|
||||
|
||||
test('renders bewerbe table', () => {
|
||||
render(<BewerbeTab / >);
|
||||
expect(screen.getByText('Bewerbs-Übersicht')).toBeInTheDocument();
|
||||
});
|
||||
```
|
||||
|
||||
### Integration Tests
|
||||
|
||||
```typescript
|
||||
// TurnierAnsicht.integration.test.tsx
|
||||
test('tab navigation works', async () => {
|
||||
render(<TurnierAnsicht / >);
|
||||
|
||||
const bewerbeTab = screen.getByText('Bewerbe');
|
||||
await userEvent.click(bewerbeTab);
|
||||
|
||||
expect(screen.getByText('Bewerbs-Übersicht')).toBeInTheDocument();
|
||||
});
|
||||
```
|
||||
|
||||
### E2E Tests (Playwright / Cypress)
|
||||
|
||||
```typescript
|
||||
// e2e/turnier.spec.ts
|
||||
test('create new turnier', async ({page}) => {
|
||||
await page.goto('/admin');
|
||||
await page.click('text=Neue Veranstaltung');
|
||||
await page.click('text=RFV Musterstadt');
|
||||
await page.fill('[name="name"]', 'Frühjahrsturnier 2026');
|
||||
await page.click('text=Speichern');
|
||||
|
||||
await expect(page.locator('text=Frühjahrsturnier 2026')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📚 Architektur-Entscheidungen (ADRs)
|
||||
|
||||
### ADR-001: React Router Data Mode
|
||||
|
||||
**Status:** Angenommen
|
||||
**Kontext:** Benötigen Client-Side Routing mit mehreren verschachtelten Routen
|
||||
**Entscheidung:** React Router v7 mit Data Mode Pattern
|
||||
**Konsequenzen:** Einfache Navigation, aber keine SSR
|
||||
|
||||
### ADR-002: Material-UI als Design System
|
||||
|
||||
**Status:** Angenommen
|
||||
**Kontext:** Benötigen professionelles Design System für Desktop-App
|
||||
**Entscheidung:** Material-UI v6 (Material Design 3)
|
||||
**Konsequenzen:** Konsistentes Design, aber größere Bundle-Size
|
||||
|
||||
### ADR-003: Tailwind CSS für Custom Styles
|
||||
|
||||
**Status:** Angenommen
|
||||
**Kontext:** Benötigen Utility-First CSS für schnelles Styling
|
||||
**Entscheidung:** Tailwind CSS v4 zusätzlich zu MUI
|
||||
**Konsequenzen:** Flexibles Styling, aber zwei CSS-Systeme
|
||||
|
||||
### ADR-004: TypeScript für Type-Safety
|
||||
|
||||
**Status:** Angenommen
|
||||
**Kontext:** Komplexe Datenstrukturen benötigen Type-Safety
|
||||
**Entscheidung:** TypeScript statt JavaScript
|
||||
**Konsequenzen:** Bessere DX, aber längere Compile-Zeit
|
||||
|
||||
---
|
||||
|
||||
## 🔮 Zukunfts-Roadmap
|
||||
|
||||
### Q2 2026
|
||||
|
||||
- [ ] Supabase Backend-Integration
|
||||
- [ ] REST API für alle CRUD-Operationen
|
||||
- [ ] PDF-Export für Startlisten/Rechnungen
|
||||
- [ ] Excel-Export
|
||||
|
||||
### Q3 2026
|
||||
|
||||
- [ ] Real-Time Collaboration (WebSockets)
|
||||
- [ ] Mobile-Responsive Layout
|
||||
- [ ] Offline-Modus (PWA)
|
||||
- [ ] Multi-Language Support (i18n)
|
||||
|
||||
### Q4 2026
|
||||
|
||||
- [ ] GraphQL API
|
||||
- [ ] Advanced Analytics Dashboard
|
||||
- [ ] Email-Benachrichtigungen
|
||||
- [ ] Zahlungs-Gateway Integration
|
||||
|
||||
---
|
||||
|
||||
**Dokumentiert von:** Lead-Architekt
|
||||
**Version:** 1.0
|
||||
**Datum:** 2026-03-24
|
||||
Reference in New Issue
Block a user