# 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 Mein Konto Meine Anfragen ``` --- ## 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: Mein Konto Nach Login: Meine Anfragen 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. ```