MBO-Tech-IT-Webseite/modules/06-kunden-portal/TEMPLATE.md

240 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Modul: Kunden-Portal (Supabase Auth + Dashboard)
> Vollständiges Kundenkonto-System auf Basis von Supabase Auth: Registrierung mit Email-Bestätigung (signierter Confirmation-Link), Login mit Magic Link oder Passwort, Kundendashboard mit Anfragen-Übersicht (Status, Positionen, Admin-Notizen), Profilverwaltung, Logout.
---
## Enthaltene Dateien
| Ziel im neuen Projekt | Inhalt |
|---|---|
| `app/kunden/login/page.tsx` | Login-Seite (Supabase Auth, Redirect nach Login) |
| `app/kunden/registrieren/page.tsx` | Registrierungs-Seite (mit API-Aufruf) |
| `app/kunden/dashboard/page.tsx` | Kundendashboard (Anfragen, Status-Badges, Positionen) |
| `app/auth/callback/page.tsx` | OAuth/Magic-Link Callback Handler |
| `app/api/kunden/anfragen/route.ts` | GET: Anfragen des eingeloggten Kunden |
| `app/api/kunden/registrieren/route.ts` | POST: Registrierung via Supabase Admin API + Email |
---
## Voraussetzungen
```bash
npm install @supabase/supabase-js @supabase/ssr
```
Benötigt außerdem:
- `lib/supabase.ts` mit Browser-Client und Service-Client
- `lib/mailer.ts` (Modul 01) für Registrierungs-Bestätigungs-Email (optional, Supabase sendet selbst)
- Modul 04 (Reservation System) wenn Kunden ihre Anfragen sehen sollen
---
## Umgebungsvariablen (`.env.local`)
```env
NEXT_PUBLIC_SUPABASE_URL=https://xxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJ...
SUPABASE_SERVICE_ROLE_KEY=eyJ... # Für Registrierung via Admin API
APP_URL=https://example.com # Basis-URL für Confirmation-Links
```
---
## Datenbank-Setup (Supabase)
### 1. Supabase Auth aktivieren
Supabase Dashboard → Authentication → Settings:
- Email-Bestätigung aktivieren
- Redirect URL eintragen: `https://example.com/auth/callback`
### 2. Optional: Kunden-Profil-Tabelle
```sql
-- Verknüpft auth.users mit zusätzlichen Kundendaten
CREATE TABLE kunden_profile (
id uuid PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
firma text,
telefon text,
erstellt_am timestamptz DEFAULT now()
);
-- Trigger: Profil automatisch beim User-Create anlegen
CREATE OR REPLACE FUNCTION handle_new_user()
RETURNS trigger AS $$
BEGIN
INSERT INTO public.kunden_profile (id)
VALUES (NEW.id);
RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
CREATE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE PROCEDURE handle_new_user();
```
### 3. Row Level Security für Anfragen
```sql
-- Kunden sehen nur ihre eigenen Anfragen
ALTER TABLE anfragen ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Kunden sehen eigene Anfragen"
ON anfragen FOR SELECT
USING (auth.uid() = kunde_id);
```
---
## Einbindung Schritt für Schritt
### 1. Dateien kopieren
### 2. Supabase Middleware einrichten (`middleware.ts` im Projekt-Root)
```ts
import { createServerClient } from "@supabase/ssr";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export async function middleware(request: NextRequest) {
let response = NextResponse.next({ request });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{ cookies: { /* ... */ } }
);
await supabase.auth.getUser(); // Session refreshen
return response;
}
export const config = { matcher: ["/kunden/:path*"] };
```
### 3. Supabase Browser-Client in `lib/supabase.ts`
```ts
import { createBrowserClient } from "@supabase/ssr";
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}
```
### 4. Dashboard an eigene Datenstruktur anpassen
`app/kunden/dashboard/page.tsx` erwartet:
- `anfragen` Tabelle mit `status`, `firma`, `erstellt_am`
- `anfragen_positionen` mit `maschine_name`, `mietbeginn`, `mietende`, `gesamt_preis`
- RLS-Policy: Kunden sehen nur `anfragen WHERE kunde_id = auth.uid()`
### 5. Navigation ergänzen
```tsx
<Link href="/kunden/login">Mein Konto</Link>
<Link href="/kunden/dashboard">Meine Anfragen</Link>
```
---
## Anpassungspunkte
| Was | Wo |
|---|---|
| Registrierungs-Email | `lib/mailer.ts``sendeRegistrierungsBestaetigung()` |
| Passwort-Mindestlänge (8 Zeichen) | `app/api/kunden/registrieren/route.ts` → Zod-Schema |
| Dashboard-Felder | `app/kunden/dashboard/page.tsx` |
| Auth-Provider (Magic Link, OAuth) | Supabase Dashboard → Auth → Providers |
| Session-Cookie-Dauer | Supabase Dashboard → Auth → Settings → JWT Expiry |
| Kunden-Profil-Felder | `kunden_profile` Tabelle + Profilseite |
---
## Integrations-Prompt
Kopiere diesen Prompt in eine neue KI-Konversation, nachdem du die `files/` in dein Projekt kopiert hast. Ersetze alle `[PLATZHALTER]`.
```
Ich integriere das Kunden-Portal (Supabase Auth, Registrierung, Kundendashboard) in mein Next.js/Supabase-Projekt.
PROJEKT-KONTEXT:
- Modul 01 (Email) ist bereits integriert (mailer.ts verfügbar)
- Modul 04 (Reservierungssystem) ist bereits integriert (anfragen-Tabelle existiert)
- Kundenbereich URL-Prefix: /kunden
- App-URL: [https://beispiel.de]
BEREITS KOPIERTE DATEIEN (aus modules/06-kunden-portal/files/):
- app/kunden/login/page.tsx
- app/kunden/registrieren/page.tsx
- app/kunden/dashboard/page.tsx
- app/auth/callback/page.tsx
- app/api/kunden/anfragen/route.ts
- app/api/kunden/registrieren/route.ts
AUFGABEN führe sie der Reihe nach aus:
1. SUPABASE AUTH KONFIGURIEREN:
Gehe zu Supabase Dashboard → Authentication → URL Configuration.
Trage ein:
- Site URL: [https://beispiel.de]
- Redirect URLs: [https://beispiel.de]/auth/callback
2. SUPABASE-PAKETE installieren (falls noch nicht vorhanden):
npm install @supabase/supabase-js @supabase/ssr
3. SUPABASE CLIENTS in lib/supabase.ts ergänzen:
Lies lib/supabase.ts. Füge hinzu (falls Browser-Client fehlt):
import { createBrowserClient } from "@supabase/ssr";
export function createBrowserSupabaseClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}
4. MIDDLEWARE erstellen: Erstelle middleware.ts im Projekt-Root:
import { createServerClient } from "@supabase/ssr";
import { NextResponse, type NextRequest } from "next/server";
export async function middleware(request: NextRequest) {
let response = NextResponse.next({ request });
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{ cookies: {
getAll() { return request.cookies.getAll(); },
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) =>
response.cookies.set(name, value, options));
},
}}
);
await supabase.auth.getUser();
return response;
}
export const config = { matcher: ["/kunden/:path*", "/auth/:path*"] };
5. RLS-POLICY für Anfragen: Führe im Supabase SQL-Editor aus:
ALTER TABLE anfragen ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Kunden sehen eigene Anfragen"
ON anfragen FOR SELECT USING (auth.uid() = kunde_id);
6. REGISTRIERUNGS-EMAIL anpassen: Lies lib/mailer.ts.
Passe die Funktion sendeRegistrierungsBestaetigung() an (oder erstelle sie falls nicht vorhanden):
- Ersetze "Mietpark Hahn" durch "[PROJEKTNAME]"
- Passe den Betreff an: "Bitte bestätigen Sie Ihre E-Mail [PROJEKTNAME]"
7. DASHBOARD anpassen: Lies app/kunden/dashboard/page.tsx.
- Ersetze "Mietanfrage/Maschine" durch die eigene Bezeichnung
- Passe angezeigte Felder aus anfragen_positionen an
8. NAVIGATION ergänzen: Füge in den öffentlichen Header hinzu:
<Link href="/kunden/login">Mein Konto</Link>
Nach Login: <Link href="/kunden/dashboard">Meine Anfragen</Link>
9. TEST:
a) /kunden/registrieren → Registrierung abschließen
b) Bestätigungs-Email öffnen, Link klicken → /auth/callback → /kunden/dashboard
c) /kunden/dashboard → Anfragen des Kunden erscheinen
d) /kunden/login → Logout → Redirect zu /kunden/login
Lies jede Datei vor dem Bearbeiten. Melde wenn alle Schritte abgeschlossen sind.
```