diff --git a/Frontend/ausfuehrliche_erklaerung_frontend.md b/Frontend/ausfuehrliche_erklaerung_frontend.md new file mode 100644 index 0000000..0608ad0 --- /dev/null +++ b/Frontend/ausfuehrliche_erklaerung_frontend.md @@ -0,0 +1,169 @@ +# Technische Dokumentation: Frontend Architektur (IHK/Ausbildung) + +## 1. Einleitung & Technologiewahl +Diese Dokumentation beschreibt die Frontend-Architektur des IT-Ticketsystems. Ziel ist es, die Funktionsweise, die verwendeten Patterns und die TypeScript-spezifische Implementierung für die IHK-Abschlussprüfung verständlich darzulegen. + +**Techn Stack:** +- **Framework**: Next.js (React) + - *Begründung*: Next.js bietet "Server-Side Rendering" (SSR) und einfaches Routing, was die Performance und SEO verbessert. Es strukturiert React-Anwendungen klar. +- **Sprache**: TypeScript + - *Begründung*: Typsicherheit minimiert Laufzeitfehler. Interfaces (`User`, `Ticket`) definieren klare Datenstrukturen, was besonders bei Teamarbeit und Wartung essenziell ist. +- **State Management**: React Context API + - *Begründung*: Vermeidung von "Prop Drilling" (Weiterreichen von Daten über viele Ebenen). Zustände wie `user` oder `tickets` werden global verfügbar gemacht. + +--- + +## 2. Projektstruktur & Scopes + +Die Dateien sind logisch getrennt: +- `app/`: Enthält die **Seiten (Pages)** und **Routen**. (Next.js App Router). +- `components/`: Enthält wiederverwendbare **UI-Elemente** (Buttons, Cards, Tabellen). +- `lib/`: Enthält **Logik**, **Typen** und **Konfigurationen** (z.B. `auth-context.tsx`, `types.ts`). + +### TypeScript Besonderheit: Interfaces (`lib/types.ts`) +In JavaScript wüssten wir nicht, welche Eigenschaften ein "Ticket" hat. In TypeScript definieren wir einen Bauplan (Interface): + +```typescript +// lib/types.ts +export type TicketStatus = "OPEN" | "IN_PROGRESS" | "CLOSED" // Union Type: Nur diese 3 Werte sind erlaubt + +export interface User { + id: number; + name: string; + role: "LEHRKRAFT" | "RAUMBETREUER"; // Enforced Role + supervisedRooms?: Room[]; // Optionales Array (?): Nicht jeder User hat Räume +} + +export interface Ticket { + id: number; + description: string; + status: TicketStatus; // Verwendet den Type von oben + owner: User; // Referenziert das User Interface +} +``` +**Warum?** Wenn ich nun `ticket.statu` schreibe, warnt mich VS Code sofort ("Did you mean 'status'?"). Das verhindert Tippfehler und Logikfehler. + +--- + +## 3. Kernlogik: Der AuthContext (`lib/auth-context.tsx`) + +Das "Gehirn" der Anwendung. Hier passiert die Kommunikation mit dem Backend. + +### Konzept: Provider Pattern +Der `AuthProvider` ist eine Komponente, die um die gesamte App gewickelt wird. Alle Komponenten *innerhalb* dieses Providers können auf seine Daten zugreifen. + +**Code-Analyse (vereinfacht):** + +```typescript +// Definition des Context-Typs (Was bietet der Context an?) +interface AuthContextType { + user: User | null; // Kann null sein, wenn ausgeloggt + tickets: Ticket[]; + login: (e: string, p: string) => Promise; // Asynchrone Funktion, gibt true/false zurück +} + +// Erstellen des Contexts +const AuthContext = createContext(null); + +// Der Provider (Die Komponente, die Daten bereitstellt) +export function AuthProvider({ children }: { children: ReactNode }) { + // Lokaler State im Provider + const [user, setUser] = useState(null); // Generics: + + // Funktion zum Daten holen + const fetchTickets = useCallback(async (authHeader: string) => { + // API Call + const res = await fetch(\`\${process.env.NEXT_PUBLIC_API_URL}/tickets\`, { + headers: { Authorization: authHeader } + }); + const data = await res.json(); + setTickets(data); // TypeScript weiß: data muss Ticket[] sein + }, []); // Empty dependency array: Funktion wird nicht ständig neu erstellt + + // Diese Werte werden "nach unten" gegeben + return ( + + {children} + + ); +} +``` + +**Erklärung für die Doku:** +1. **State**: Wir nutzen `useState`, um Daten zu speichern. TypeScript sorgt dafür, dass wir in `tickets` nur echte Tickets speichern können. +2. **Generics**: `useState` sagt: "Dieser State darf nur ein User-Objekt oder null sein". +3. **Hooks**: + - `useEffect`: "Mach das, wenn die App lädt" (z.B. User prüfen). + - `useCallback`: Speichert eine Funktion, damit sie nicht bei jedem Neuladen der Seite neu erstellt wird (Performance). + +--- + +## 4. Komponenten-Logik (Beispiel: `SupervisorDashboard`) + +Hier sehen wir, wie die Daten konsumiert werden. + +```typescript +export function SupervisorDashboard() { + // 1. Hook nutzen: Zugriff auf globale Daten + const { user, tickets } = useAuth(); + + // 2. Optional Chaining (?.) + // Wenn user null ist, stürzt die App nicht ab, sondern gibt undefined zurück. + // || [] bedeutet: Wenn undefined/null, nutze leeres Array. + const supervisedRooms = user?.supervisedRooms || []; + + // 3. Computed Values (useMemo) + // Berechne 'roomTickets' nur neu, wenn sich 'tickets' oder 'supervisedRooms' ändern. + const roomTickets = useMemo(() => { + if (!supervisedRooms.length) return []; + + // Array Methoden: map() und filter() + const roomIds = supervisedRooms.map(r => r.id); // [101, 102] + return tickets.filter((t) => roomIds.includes(t.room.id)); + }, [tickets, supervisedRooms]); + + return ( +
+ {/* Conditional Rendering: Zeige Badge nur wenn count > 0 */} + {stats.open > 0 && {stats.open}} +
+ ); +} +``` + +**Wichtige Konzepte:** +- **Destructuring**: `const { user } = useAuth()` zieht nur die `user`-Variable aus dem Context. +- **Array High-Order Functions**: `map`, `filter`, `reduce` sind Standard in modernem JS/TS, um Daten umzuwandeln. +- **Dependency Arrays**: `[tickets, supervisedRooms]` sagt React: "Führe diese Berechnung nur aus, wenn sich EINE dieser Variablen geändert hat". + +--- + +## 5. Authentifizierung (NextAuth & Middleware) + +**Ablauf:** +1. User gibt Daten ein -> `signIn("credentials", ...)` +2. NextAuth sendet Request an unser Backend (`route.ts`). +3. Backend antwortet: "OK, hier ist der User". +4. Frontend speichert User in der **Session**. +5. Der `NextAuthSessionProvider` in `layout.tsx` hält die Session aktiv. + +**Code (`route.ts`):** +```typescript +async authorize(credentials) { + // API Anfrage an eigenes Java Backend + const res = await fetch(API_URL + "/login", { ...body }); + + if (res.ok) { + const user = await res.json(); + return user; // NextAuth speichert diesen User + } + return null; // Login fehlgeschlagen +} +``` +Wir nutzen NextAuth als "Mittelsmann". Es kümmert sich um Cookies und Security, während unser Backend die eigentliche Prüfung macht. + +--- + +## Zusammenfassung für die Präsentation + +"Die Architektur basiert auf einer klaren Trennung von UI (Components) und Logik (Context/Hooks). Durch den Einsatz von TypeScript werden Datenstrukturen wie User und Tickets strikt typisiert, was die Fehleranfälligkeit drastisch reduziert. Das State Management erfolgt effizient über React Context, wodurch alle Komponenten stets synchronen Zugriff auf den aktuellen Anwendungszustand haben, ohne dass Daten mühsam durchgereicht werden müssen (`Prop Drilling`)." diff --git a/docker-compose.yml b/docker-compose.yml index a5e9fe0..47bc85a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -30,7 +30,7 @@ services: container_name: ticketsystem-frontend environment: NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL:-http://projekt.lona-development.org/api} - API_URL: http://backend:8080 + API_URL: ${API_URL:-http://projekt.lona-development.org/api} NEXTAUTH_SECRET: ${NEXTAUTH_SECRET} NEXTAUTH_URL: ${NEXTAUTH_URL} depends_on: