# Les 7 — Docenttekst
## Van In-Memory naar Supabase

---

## Lesoverzicht

| Gegeven | Details |
|---------|---------|
| **Les** | 7 van 18 |
| **Onderwerp** | Supabase: database koppelen aan Next.js |
| **Duur** | 3 uur (09:00 – 12:00) |
| **Voorbereiding** | Werkend QuickPoll project uit Les 6, Supabase account |
| **Benodigdheden** | Laptop, Cursor/VS Code, browser, GitHub account |

---

## Leerdoelen

Na deze les kunnen studenten:
1. Uitleggen wat Supabase is en waarvoor je het gebruikt
2. Via de Supabase GUI tabellen aanmaken met relaties (foreign keys)
3. RLS policies instellen voor publieke toegang
4. De Supabase JavaScript client gebruiken in een Next.js project
5. Data ophalen en muteren via de Supabase client (select, update, insert)
6. Environment variables gebruiken voor API keys

---

## Tijdsplanning

### 09:00 – 09:10 | Welkom & Terugblik (10 min)

- Vraag: "Wie heeft het huiswerk gemaakt? Waar liep je tegenaan?"
- Kort terugblikken: wat hebben we gebouwd in Les 6?
- Aankondigen: "Vandaag maken we de app echt werkend én koppelen we een database"

### 09:10 – 09:30 | DEEL 1: Poll afmaken (20 min)

**Stap 1.1** — `votePoll()` in data.ts (5 min)
- Leg uit: we missen een functie om stemmen te verwerken
- Typ de functie, leg de logica uit

**Stap 1.2** — POST route fixen (5 min)
- Laat zien dat de huidige route alleen logt
- Vervang met werkende versie: body uitlezen, votePoll aanroepen, response sturen

**Stap 1.3** — Server Component + VoteForm split (10 min)
- DIT IS HET KERNMOMENT: leg het patroon uit
- Maak `components/VoteForm.tsx` — Client Component met useState + fetch
- Herschrijf `app/poll/[id]/page.tsx` als Server Component (geen 'use client'!)
- Server Component haalt data → geeft als prop door → Client Component doet interactie
- Dit patroon verandert NIET meer als we Supabase koppelen

**Stap 1.4** — GET route + visuele feedback (5 min)
- Voeg GET route toe (nodig voor VoteForm na het stemmen)
- Update PollItem met percentage bars

**✅ Check:** Demo op localhost — stem, zie de bar groeien

> **Tip:** Als studenten vastlopen, laat ze de browser console openen. Fouten in fetch calls verschijnen daar.

### 09:30 – 10:15 | DEEL 2: Supabase Introductie — No Code (45 min)

Dit is voor veel studenten hun EERSTE database-ervaring. Neem de tijd!

**Stap 2.1** — Wat is Supabase? (5 min)
- Open-source Firebase alternatief
- PostgreSQL = echte database, 30+ jaar oud
- Gratis tier voor leren

**Stap 2.2** — Project aanmaken (5 min)
- Iedereen logt in op supabase.com (GitHub)
- Maak samen een project aan
- Wacht tot het klaar is (~30 sec)

> **Tip:** Zorg dat iedereen een GitHub account heeft! Dit is een veelvoorkomend blokpunt.

**Stap 2.3** — polls tabel (10 min)
- Table Editor → New Table
- Leg uit: id (uuid), created_at (timestamp), question (text)
- Leg uit: NOT NULL — het veld mag niet leeg zijn

**Stap 2.4** — options tabel + foreign key (10 min)
- Vier kolommen: poll_id, text, votes
- Foreign key: leg uit wat dat is en waarom
- CASCADE: als poll weg is, opties ook

**Stap 2.5** — RLS policies (5 min)
- Leg uit: standaard mag niemand iets → we geven toestemming
- Maak SELECT policy op polls, SELECT + UPDATE op options

**Stap 2.6** — Testdata invoeren (5 min)
- Voeg 2 polls + 8 opties toe via de GUI

**Stap 2.7** — SQL Editor (5 min)
- Laat SELECT, WHERE en JOIN zien
- Dit is een mooi "aha-moment" — de data die ze net hebben ingevoerd komt terug

> **Tip:** Laat studenten ook zelf een query proberen. Bijv: "Hoeveel opties heeft poll X?"

### 10:15 – 10:30 | PAUZE (15 min)

### 10:30 – 11:30 | DEEL 3: Supabase koppelen aan Next.js (60 min)

**Stap 3.1** — npm install (2 min)
- `npm install @supabase/supabase-js`

**Stap 3.2** — .env.local (5 min)
- Kopieer URL + anon key uit Supabase dashboard
- Leg uit: NEXT_PUBLIC_ prefix, .gitignore
- ⚠️ Check: staat .env.local in .gitignore?

**Stap 3.3** — supabase.ts client (3 min)
- Drie regels code, simpel

**Stap 3.4** — Types updaten (5 min)
- Poll + Option interfaces
- Leg uit: waarom twee types? Matcht de twee tabellen

**Stap 3.5** — data.ts herschrijven (15 min)
- Dit is het kernstuk. Neem de tijd.
- `getPolls()`: select met options(*)
- `getPollById()`: select met eq + single
- `votePoll()`: twee stappen (fetch → update)
- Leg de Supabase syntax stap voor stap uit

> **Tip:** Als studenten TypeScript errors krijgen, check of ze de types correct hebben geüpdatet.

**Stap 3.6** — Homepage async maken (5 min)
- `async function Home()` + `await getPolls()`
- Leg uit: Server Component mag async zijn

**Stap 3.7** — PollItem aanpassen (5 min)
- option.text, option.votes, option.id

**Stap 3.8** — VoteForm + detail pagina + API routes (10 min)
- VoteForm: optionId (uuid) i.p.v. optionIndex (number)
- Page.tsx: alleen `await` toevoegen — structuur verandert niet!
- Benadruk: "Dát is de kracht van het Server Component + Client Component patroon"

**Stap 3.9** — Testen! (10 min)
- Samen testen op localhost
- Stem, refresh, check Supabase Table Editor
- Het "aha-moment": data overleeft een server restart!

> **Tip:** Open het Supabase dashboard naast de app. Stem in de app, refresh de Table Editor — studenten zien het live veranderen.

### 11:30 – 11:45 | Vragen & Reflectie (15 min)

Mogelijke vragen:
- "Kan iedereen nu stemmen?" → Ja, via de anon key + RLS policies
- "Is dit veilig?" → Voor een leerproject ja. In productie: auth + strakkere RLS
- "Hoe voorkom je dubbel stemmen?" → Met authenticatie (volgende les!)
- "Wat als de database offline is?" → Error handling in onze functies

### 11:45 – 12:00 | Huiswerk & Afsluiting (15 min)

**Opdracht:**
1. Maak een /create pagina (formulier → INSERT in Supabase)
2. Voeg navbar link toe
3. Extra: SQL queries schrijven

**Vooruitblik:** "Volgende les: Supabase Auth — inloggen, registreren, en bijhouden wie er stemt."

---

## Veelvoorkomende problemen

| Probleem | Oplossing |
|----------|-----------|
| "supabase.com laadt niet" | Probeer een andere browser of incognito |
| "Kan geen project aanmaken" | Check of ze een org hebben, anders aanmaken |
| Foreign key lukt niet | Check of de polls tabel al bestaat en data heeft |
| RLS blokkeert alles | Check of de policies correct zijn (anon, SELECT, true) |
| .env.local werkt niet | Server herstarten na aanmaken .env.local! |
| TypeScript errors na type change | Check imports, rebuild, herstart TS server |
| "Data verschijnt niet" | Check browser console voor Supabase errors |
| Votes updaten niet | Check of UPDATE RLS policy op options staat |
