fix: add les 8
This commit is contained in:
324
Les08-Van-InMemory-naar-Supabase/Les08-Docenttekst.md
Normal file
324
Les08-Van-InMemory-naar-Supabase/Les08-Docenttekst.md
Normal file
@@ -0,0 +1,324 @@
|
||||
# Les 8 — Docenttekst
|
||||
## Van In-Memory naar Supabase
|
||||
|
||||
---
|
||||
|
||||
## Lesoverzicht
|
||||
|
||||
| Gegeven | Details |
|
||||
|---------|---------|
|
||||
| **Les** | 8 van 18 |
|
||||
| **Onderwerp** | Supabase koppelen aan Next.js |
|
||||
| **Duur** | 3 uur (09:00 – 12:00) |
|
||||
| **Voorbereiding** | Werkend QuickPoll project, Supabase project met polls/options tabellen |
|
||||
| **Benodigdheden** | Laptop, Cursor/VS Code, browser, Supabase account |
|
||||
| **Aanpak** | Deel 1-3 klassikaal (docent loopt PDF door met studenten). Deel 4 zelfstandig. |
|
||||
|
||||
## Leerdoelen
|
||||
|
||||
Na deze les kunnen studenten:
|
||||
1. De Supabase JavaScript client installeren en configureren
|
||||
2. Environment variables gebruiken voor API keys
|
||||
3. Data ophalen via Supabase queries (select met relaties, eq, single)
|
||||
4. Het verschil uitleggen tussen Server en Client Components
|
||||
5. Een formulier bouwen dat data INSERT in Supabase
|
||||
|
||||
---
|
||||
|
||||
## Lesplanning
|
||||
|
||||
### 09:00–09:15 | Welkom & Intro (15 min)
|
||||
📌 Slide 1, 2, 3
|
||||
|
||||
**Doel:** Studenten welkom heten, plan uitleggen, en PDF uitdelen.
|
||||
|
||||
**Wat te zeggen:**
|
||||
- "Vorige week hebben we een werkend polling app gebouwd met in-memory data."
|
||||
- "Vandaag koppelen we Supabase: onze database-as-a-service."
|
||||
- "Jullie krijgen een PDF met de volledige lesopdracht. We lopen Deel 1 t/m 3 samen door. Deel 4 doen jullie zelfstandig."
|
||||
- "In de PDF staan grijze blokken die je kunt copy-pasten, en TODO-blokken die je zelf moet invullen."
|
||||
|
||||
**Check vooraf:**
|
||||
- Iedereen heeft Supabase account met polls en options tabellen
|
||||
- Iedereen heeft QuickPoll project lokaal runnen op localhost:3000
|
||||
- Deel de Lesopdracht PDF uit (digitaal)
|
||||
|
||||
---
|
||||
|
||||
### 09:15–09:45 | KLASSIKAAL: PDF Deel 1 — Setup (30 min)
|
||||
📌 Slide 4 + PDF Deel 1
|
||||
|
||||
**Doel:** Samen de setup doorlopen. Iedereen heeft aan het einde: supabase client geïnstalleerd, .env.local, supabase.ts, en types.
|
||||
|
||||
**Toon Slide 4** — Van Array naar Database. Leg uit:
|
||||
- "Tot nu toe sloegen we data op in een array. Dat verdwijnt bij restart."
|
||||
- "Supabase geeft ons een echte PostgreSQL database in de cloud."
|
||||
- Toon links de oude array, rechts de database structuur.
|
||||
|
||||
**Open de PDF bij Deel 1 en loop stap voor stap door:**
|
||||
|
||||
#### Stap 1.1 — npm install
|
||||
- "Open je terminal, voer uit: `npm install @supabase/supabase-js`"
|
||||
- Wacht tot iedereen klaar is
|
||||
- "Herstart je dev server!"
|
||||
|
||||
#### Stap 1.2 — .env.local
|
||||
- "Open Supabase dashboard → Settings → API"
|
||||
- "Kopieer je Project URL en anon key"
|
||||
- "Maak `.env.local` aan in de root van je project"
|
||||
- Laat ze het invullen, loop rond en check
|
||||
- **Let op:** herstart dev server na aanmaken .env.local!
|
||||
|
||||
#### Stap 1.3 — lib/supabase.ts
|
||||
- "Dit is onze client — zo praat je app met Supabase"
|
||||
- Laat ze de code copy-pasten uit de PDF
|
||||
- Leg uit: `createClient` maakt de verbinding, `process.env.NEXT_PUBLIC_...` leest de env vars
|
||||
|
||||
#### Stap 1.4 — types/index.ts
|
||||
- "Dit zijn de TypeScript types die matchen met onze database tabellen"
|
||||
- Laat ze copy-pasten
|
||||
- Wijs op: `id: number`, `options: Option[]` (de relatie)
|
||||
|
||||
#### Stap 1.5 — vote_option SQL functie aanmaken
|
||||
- "Voordat we kunnen stemmen, hebben we een PostgreSQL functie nodig in Supabase."
|
||||
- "Open Supabase dashboard → SQL Editor"
|
||||
- Laat ze deze SQL uitvoeren (staat in PDF):
|
||||
```sql
|
||||
create or replace function public.vote_option(option_id bigint)
|
||||
returns void
|
||||
language sql
|
||||
security definer
|
||||
as $$
|
||||
update public.options
|
||||
set votes = votes + 1
|
||||
where id = option_id;
|
||||
$$;
|
||||
```
|
||||
- **Leg uit:** "Dit is een database functie. We roepen 'm straks aan met `supabase.rpc('vote_option', { option_id })`. Een RPC = Remote Procedure Call — je voert PostgreSQL code uit vanuit je app."
|
||||
- **Waarom?** "We hadden ook een gewone UPDATE kunnen doen, maar met een functie hou je de logica in de database. Volgende les met Auth gaan we deze functie uitbreiden."
|
||||
- **Let op:** "Zonder deze functie krijg je later een PGRST202 error bij het stemmen — 'Could not find the function public.vote_option'."
|
||||
|
||||
**Check:** "Heeft iedereen de setup af? Geen errors? Handen omhoog als je klaar bent."
|
||||
|
||||
---
|
||||
|
||||
### 09:45–10:00 | KLASSIKAAL: PDF Deel 2 — Supabase Queries (15 min)
|
||||
📌 Slide 5 + PDF Deel 2
|
||||
|
||||
**Doel:** Studenten begrijpen de queries en vullen de TODO-blokken in lib/data.ts in.
|
||||
|
||||
**Toon Slide 5** — Supabase Queries. Leg de vier operaties uit:
|
||||
1. **SELECT alles:** `.from("polls").select("*, options(*)")` — de `*` haalt alles op, `options(*)` volgt de relatie
|
||||
2. **SELECT een:** `.eq("id", 5).single()` — filter + verwacht 1 resultaat
|
||||
3. **INSERT:** `.insert({ question }).select().single()` — maak nieuw record, krijg het terug
|
||||
4. **RPC:** `.rpc("vote_option", { option_id })` — roep een database function aan
|
||||
|
||||
**Tip:** Schrijf deze vier queries op het whiteboard. Studenten kijken hier de rest van de les naar.
|
||||
|
||||
**Open de PDF bij Deel 2 — Stap 2.1:**
|
||||
- "Vervang de inhoud van `lib/data.ts`. De imports staan er al."
|
||||
- "Nu de TODO-blokken. Laten we de eerste samen doen."
|
||||
|
||||
**getPolls() — doe samen voor:**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from("polls")
|
||||
.select("*, options(*)");
|
||||
|
||||
if (error) {
|
||||
console.error(error);
|
||||
return [];
|
||||
}
|
||||
return data || [];
|
||||
```
|
||||
- "Zie je? `.from("polls")` kiest de tabel, `.select("*, options(*)")` haalt alles op inclusief de relatie."
|
||||
|
||||
**getPollById() — laat ze zelf proberen (2 min), loop dan door:**
|
||||
```typescript
|
||||
const { data, error } = await supabase
|
||||
.from("polls")
|
||||
.select("*, options(*)")
|
||||
.eq("id", id)
|
||||
.single();
|
||||
|
||||
if (error) return null;
|
||||
return data;
|
||||
```
|
||||
- "`.eq("id", id)` filtert op 1 specifieke poll. `.single()` zegt: ik verwacht 1 resultaat."
|
||||
|
||||
**votePoll() — laat ze zelf proberen (2 min), loop dan door:**
|
||||
```typescript
|
||||
const { error } = await supabase
|
||||
.rpc("vote_option", { option_id: optionId });
|
||||
|
||||
if (error) {
|
||||
console.error(error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
```
|
||||
- "`.rpc()` roept een PostgreSQL function aan die we eerder hebben aangemaakt."
|
||||
|
||||
**Check:** "Heeft iedereen alle drie de functies ingevuld?"
|
||||
|
||||
---
|
||||
|
||||
### 10:00–10:15 | KLASSIKAAL: PDF Deel 3 — Componenten (15 min)
|
||||
📌 Slide 6 + PDF Deel 3
|
||||
|
||||
**Doel:** Studenten copy-pasten de vier componenten uit de PDF en testen de app.
|
||||
|
||||
**Toon Slide 6** — Server vs Client. Leg kort uit:
|
||||
- "Server Components: async, kunnen `await getPolls()` doen. Draaien op de server."
|
||||
- "Client Components: `'use client'` bovenaan, kunnen `useState`/`onClick` gebruiken. Draaien in de browser."
|
||||
- "Vuistregel: Server haalt data, Client maakt het interactief."
|
||||
|
||||
**Open de PDF bij Deel 3 en loop door:**
|
||||
|
||||
#### Stap 3.1 — app/page.tsx
|
||||
- "Dit is de homepage. Let op: `async function` en `await getPolls()` — dit is een Server Component."
|
||||
- "Copy-paste uit de PDF."
|
||||
- "De `<Link href="/create">` link werkt straks na Deel 4."
|
||||
|
||||
#### Stap 3.2 — components/PollItem.tsx
|
||||
- "Dit is een Client Component — zie `'use client'` bovenaan."
|
||||
- "Het berekent percentages en toont bars. Copy-paste."
|
||||
|
||||
#### Stap 3.3 — components/VoteForm.tsx
|
||||
- "Nog een Client Component. Hier wordt `votePoll()` aangeroepen — de functie die jullie net geschreven hebben!"
|
||||
- "Copy-paste."
|
||||
|
||||
#### Stap 3.4 — app/poll/[id]/page.tsx
|
||||
- "De detailpagina. Weer een Server Component met `await getPollById()`."
|
||||
- "Copy-paste."
|
||||
|
||||
**Test samen:**
|
||||
- "Open http://localhost:3000 — zien jullie polls?"
|
||||
- "Klik op een poll — kun je stemmen?"
|
||||
- "Check in Supabase dashboard: stijgt het aantal votes?"
|
||||
|
||||
**Troubleshooting als het niet werkt:**
|
||||
- Lege pagina → RLS SELECT policy mist
|
||||
- `Cannot find module` → check import paths
|
||||
- Stemmen werkt niet → vote_option RPC functie mist
|
||||
|
||||
---
|
||||
|
||||
### 10:15–10:30 | Pauze (15 min)
|
||||
📌 Slide 7
|
||||
|
||||
**Zeg voor de pauze:** "Na de pauze gaan jullie zelfstandig Deel 4 doen: de /create pagina. De volledige UI staat in de PDF — jullie schrijven alleen de INSERT query."
|
||||
|
||||
---
|
||||
|
||||
### 10:30–10:45 | Uitleg INSERT + start Deel 4 (15 min)
|
||||
📌 Slide 8 + PDF Deel 4 intro
|
||||
|
||||
**Doel:** INSERT concept uitleggen voordat ze zelfstandig aan de slag gaan.
|
||||
|
||||
**Wat te zeggen:**
|
||||
- "Het formulier staat compleet in de PDF (Stap 4.3). Jullie hoeven alleen de handleSubmit functie in te vullen."
|
||||
- "Maar eerst: Stap 4.1 — de RLS policy. Zonder INSERT policy blokkeert Supabase je."
|
||||
|
||||
**Loop door Stap 4.1 (RLS policy):**
|
||||
- "Open Supabase dashboard → SQL Editor"
|
||||
- "Voer de twee CREATE POLICY statements uit de PDF uit"
|
||||
- "Dit is tijdelijk — volgende les beperken we dit met Auth"
|
||||
|
||||
**Leg Stap 4.2 (INSERT theorie) uit:**
|
||||
- "Er zijn twee INSERT stappen:"
|
||||
1. Insert de poll: `.from("polls").insert({ question }).select().single()` → je krijgt de poll met id terug
|
||||
2. Insert de options: `.from("options").insert(options.map(...))` → gebruik het `poll.id` van stap 1
|
||||
- Toon op whiteboard:
|
||||
```
|
||||
1. INSERT poll → { id: 5, question: "..." }
|
||||
2. INSERT options → [{ poll_id: 5, text: "A" }, { poll_id: 5, text: "B" }]
|
||||
3. router.push("/") → terug naar homepage
|
||||
```
|
||||
|
||||
**Zeg:** "Nu zijn jullie aan de beurt. Stap 4.3 in de PDF: copy-paste het hele bestand, en vul het TODO-blok in. Ik loop rond."
|
||||
|
||||
---
|
||||
|
||||
### 10:45–11:30 | ZELFSTANDIG: PDF Deel 4 — /create pagina (45 min)
|
||||
📌 Studenten werken met PDF Stap 4.3
|
||||
|
||||
**Wat ze doen:**
|
||||
1. `app/create/page.tsx` aanmaken met de code uit de PDF (Stap 4.3)
|
||||
2. handleSubmit TODO-blok invullen (de INSERT logica)
|
||||
3. Testen: poll aanmaken → verschijnt op homepage
|
||||
|
||||
**Jouw rol — loop rond en help:**
|
||||
|
||||
Typische problemen:
|
||||
- RLS INSERT policy vergeten → "new row violates row-level security" → Stap 4.1 niet gedaan
|
||||
- `options` niet gekoppeld aan poll → `poll_id` vergeten in de insert
|
||||
- `router.push` werkt niet → check `import { useRouter } from "next/navigation"` (niet `"next/router"`)
|
||||
- Form submit herlaadt pagina → `e.preventDefault()` check
|
||||
- `poll` is undefined na insert → `.select().single()` vergeten
|
||||
|
||||
**Check-in na 15 min:**
|
||||
- "Wie heeft de RLS policy al toegevoegd?"
|
||||
- "Wie kan al een poll aanmaken?"
|
||||
|
||||
**Check-in na 30 min:**
|
||||
- "Wie heeft een werkende /create pagina?"
|
||||
- Help studenten die vastlopen
|
||||
|
||||
**Snelle studenten:**
|
||||
- Validatie toevoegen (vraag niet leeg, min 2 opties)
|
||||
- Styling verbeteren met Tailwind
|
||||
- Delete functionaliteit bouwen
|
||||
|
||||
---
|
||||
|
||||
### 11:30–12:00 | Vragen + Huiswerk (30 min)
|
||||
📌 Slide 9, 10
|
||||
|
||||
**Vragen beantwoorden:**
|
||||
- Open ronde: waar liepen jullie tegenaan?
|
||||
- Concepten herhalen die onduidelijk waren
|
||||
- Eventueel: laat een werkende /create pagina zien van een student
|
||||
|
||||
**Huiswerk bespreken (Slide 9):**
|
||||
|
||||
Verplicht:
|
||||
- /create pagina afmaken (als niet klaar)
|
||||
- Validatie toevoegen (vraag niet leeg, min 2 opties)
|
||||
|
||||
Extra:
|
||||
- Delete functionaliteit
|
||||
- SQL queries direct in Supabase testen
|
||||
- Realtime subscriptions uittesten
|
||||
- Styling verbeteren
|
||||
|
||||
**Vooruitblik (Slide 10):**
|
||||
- "Volgende week: Supabase Auth"
|
||||
- "Inloggen, registreren, en bepalen wie wat mag doen"
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting Overzicht
|
||||
|
||||
| Probleem | Oorzaak | Oplossing |
|
||||
|----------|---------|-----------|
|
||||
| `NEXT_PUBLIC_SUPABASE_URL is undefined` | .env.local niet geladen | Dev server herstarten |
|
||||
| Lege pagina, geen polls | RLS policy mist | SELECT policy toevoegen in Supabase |
|
||||
| "new row violates row-level security" | INSERT policy mist | INSERT policy toevoegen |
|
||||
| `Cannot find module '@/types'` | Import path fout | Check tsconfig.json paths |
|
||||
| `PGRST202 Could not find the function public.vote_option` | vote_option SQL functie mist | Stap 1.5 uitvoeren in SQL Editor |
|
||||
| Options verschijnen niet bij poll | Foreign key mismatch | Check poll_id in options tabel |
|
||||
| Stemmen werkt niet | RPC functie mist | vote_option function aanmaken in SQL editor |
|
||||
| Form submit herlaadt pagina | preventDefault mist | `e.preventDefault()` in handleSubmit |
|
||||
| poll is undefined na insert | .select().single() mist | Toevoegen aan insert query |
|
||||
|
||||
---
|
||||
|
||||
## Voorbereiding Checklist
|
||||
|
||||
- [ ] Eigen QuickPoll project werkt lokaal
|
||||
- [ ] Supabase project met polls + options tabellen
|
||||
- [ ] vote_option RPC functie aangemaakt
|
||||
- [ ] SELECT RLS policies staan aan
|
||||
- [ ] Lesopdracht PDF gedeeld met studenten (digitaal)
|
||||
- [ ] Whiteboard/marker beschikbaar voor queries
|
||||
346
Les08-Van-InMemory-naar-Supabase/Les08-Lesopdracht.pdf
Normal file
346
Les08-Van-InMemory-naar-Supabase/Les08-Lesopdracht.pdf
Normal file
@@ -0,0 +1,346 @@
|
||||
%PDF-1.4
|
||||
%<25><><EFBFBD><EFBFBD> ReportLab Generated PDF document (opensource)
|
||||
1 0 obj
|
||||
<<
|
||||
/F1 2 0 R /F2 3 0 R /F3 5 0 R /F4 6 0 R /F5 9 0 R /F6 19 0 R
|
||||
>>
|
||||
endobj
|
||||
2 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
3 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
4 0 obj
|
||||
<<
|
||||
/Contents 25 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
5 0 obj
|
||||
<<
|
||||
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
6 0 obj
|
||||
<<
|
||||
/BaseFont /Helvetica-Oblique /Encoding /WinAnsiEncoding /Name /F4 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
7 0 obj
|
||||
<<
|
||||
/Contents 26 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
8 0 obj
|
||||
<<
|
||||
/Contents 27 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
9 0 obj
|
||||
<<
|
||||
/BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F5 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
10 0 obj
|
||||
<<
|
||||
/Contents 28 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
11 0 obj
|
||||
<<
|
||||
/Contents 29 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
12 0 obj
|
||||
<<
|
||||
/Contents 30 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
13 0 obj
|
||||
<<
|
||||
/Contents 31 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
14 0 obj
|
||||
<<
|
||||
/Contents 32 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
15 0 obj
|
||||
<<
|
||||
/Contents 33 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
16 0 obj
|
||||
<<
|
||||
/Contents 34 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
17 0 obj
|
||||
<<
|
||||
/Contents 35 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
18 0 obj
|
||||
<<
|
||||
/Contents 36 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
19 0 obj
|
||||
<<
|
||||
/BaseFont /ZapfDingbats /Name /F6 /Subtype /Type1 /Type /Font
|
||||
>>
|
||||
endobj
|
||||
20 0 obj
|
||||
<<
|
||||
/Contents 37 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
21 0 obj
|
||||
<<
|
||||
/Contents 38 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 24 0 R /Resources <<
|
||||
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
|
||||
>> /Rotate 0 /Trans <<
|
||||
|
||||
>>
|
||||
/Type /Page
|
||||
>>
|
||||
endobj
|
||||
22 0 obj
|
||||
<<
|
||||
/PageMode /UseNone /Pages 24 0 R /Type /Catalog
|
||||
>>
|
||||
endobj
|
||||
23 0 obj
|
||||
<<
|
||||
/Author (\(anonymous\)) /CreationDate (D:20260407143958+02'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260407143958+02'00') /Producer (ReportLab PDF Library - \(opensource\))
|
||||
/Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False
|
||||
>>
|
||||
endobj
|
||||
24 0 obj
|
||||
<<
|
||||
/Count 14 /Kids [ 4 0 R 7 0 R 8 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R
|
||||
17 0 R 18 0 R 20 0 R 21 0 R ] /Type /Pages
|
||||
>>
|
||||
endobj
|
||||
25 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 952
|
||||
>>
|
||||
stream
|
||||
Gatm:9iKe#&A@sBCi?#<#YVI>WA?]aThlS0Rc;a'(LrB]`3C?'T``'D/(lXP#/c#QbAqd6]C5.9-59^4;Yq=b!5=2,GX?s:#k*:i`.RO\^4jk\Trk6=Lp*2_L%5KaJ\Z]Zj@'<q3esPaTpf%?FYF3j&s"d!U<2]RXN]b$gaC6E$6?td7R&Q0ces.)eZ8JZ-o/;@/:aKO\Bqh0dTM#!i=*Sa0](ZAPtqUA':_TcLPt>;A&m;kcN6lBiR6hF!E%W7?@_#n=;Z:K6"[AU7YG`WCp@7/(!$R[/rMKaUA2Ij&8Z^.Jq-bYo0<dP&5mW\Lk3-:q%S"U],3R3XG7qf80GSU_0)![=[)hY(Ie!&Gna7t[4\6/BVdd-gKTD@#U'I[q(N5W3eug?Xc/`Y.1M)@Z>DUeVI1o%D?0<N#G]&FRR<gA1i-i\<?7@o:_Zp98oR3M#`HP6kAuut^lPcp_k48T>U8%u7lBK;U(#J_C$7+=!D9^kB6Q3[l=bb1>$%\0OcCO%a*dD859?t\P27fU$<a(H#OXb0hbpIg.r)XWA=0dFV[q8lL/=Yl9qCM=\oK@NK/"f5O%UY.ck7Br4B2%7^T1s<D;=1E]%VAQD.jD@Z/8Qb#].kO,$s`/j>M0/\p7/=3n$*:K#>+H;6?ONVJ.+=%1TcoE-.,G:C:Cr)c.K&pCt#*liE7)N5Ecu9=W6(q-<)A#CAh8D!#M=l#]qkI,E#6n7Ea+4FtU8NT\'6/Ak5*@*>R;l+#'=3W8.9SiK1g!t'4T^J>joi1H3C2W_gX\FPIjY%R/X\?^j>oaQ/T0mL!B^q5SWH$oeO)8fuuA2,P&2cpLg1LN?/*-Oe4[h>Qe1W24()Q)9uX!pp`IC;7$ZYq62SYA_qfXL-r045$/P%pBCkud++ISi:hbG]2rZOIF>Dj+1g*UcR'_ZFsukPUOhm[f^=U":[0$TS.eIO$@u~>endstream
|
||||
endobj
|
||||
26 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1229
|
||||
>>
|
||||
stream
|
||||
Gau0BD0+\p&H9tYf\@ip;iKfsCbk63\`VU>BjM:tQRNqE(aTH(aX7IZ]:8`m8hpm0K>Y54?n;gpXe+?sSm<SFeJFWhS-#5ST_TW0EhIUaaKn"mFl9?&qcH2nbJ:B7aGCJ8r0E&2+B&*dA'51KQKNn^L:/$]?q%6tJ@MX/T4m>R?E0$)^bJ@CCBs,h'9W?16^Pks#5rk.;o0Y'&k4u19_Ju-Tf7PZ>E.`JI5g,)4`dOkCbuElV1A],CkWqHqRR0h.063Zj<QR4]+Sb,/-LCABu)gQ,u,(>"E\8o*o`^V`Z#'.GJN_U33#Bf_!ql(b=naJ69l0G;MGjX%)scDf/"=@YBZ3q-MW84&sV4B/"ACFgD)F=p+"'9d`$q5otrF?bD5t`'a8b2oO*)I0ed9oqWERH'rl,DZ6fjI^,>(S%Gi[gG9JfJ,83/^;AH>`!;r'7dbcTo)O%g#Qqjk(VHZl@I=7,F8Rt*r&!1Yt'O:VNa(#F=92gCUK!><E>OX-T$D^L_<rXkTb;CJbaGH8tENgCX*sVV>Y>`gBN6S?[9M&!r*".XZ$)s"D5<p`L^1M)qbp?H#6\bI+(f.sfBs8NQ\jb9,8pH;Y`KS_K*AD)oj!+VWF,eo#ImNW4`:dL/9#Pnj'k0C#$7`?5MQA@"r2lc"SGgtW>htoncJK)B2chB)-f),Fc%jU7=NW152k(IE]5K6P[S"PD0fSXg"Di7$EcH@Zq!IG:A$[75c5KXPWA18<<61Tcg0F;K&;:OYZIgcWW;f0:8/G#)V)sl-TrVAj:o0D(4QKV'b[cg"h<",NS6VUhE.L=("7GF71VG$7XjgD:lQrS%K%@Y9jVFkBMBYfo;H<rLT(BO>9'GcD03U-g,cV4"EJ*bGU_>fDUuR4`PR^DDY,Lgn@R74Dmn=&G&T.bJiQ]@sn`K%,2F]ag_75<3ROq@i_=9=BrVBE,7CpZ2WA5fGDHb[N*?Y4Kh7H;d+"TSI&!&1ScO'>?GH[Zdmo*7uBXkL_2j3'/,?9T(BJ)0*VWo_n@2$gKF1'38jqLHOWqC/)*l_<N&m(.pnm6*XTU*9>Hiu):_1KLfWRo!k*"t#EJmYsKNiG"\B'GD5UMV>"B-`h.X)=D"U"]$;_a5WD!L>fAH)<aeD7DD]s89K<q7':bbCGI%s!sm=j^_3(:6LCgZ-9a(q+b#K9[7,OqUoQ>,5)BVC]&gZ+OIgi_!R*"OqKnq;EQ7A%3*gr"!`SM-i~>endstream
|
||||
endobj
|
||||
27 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 746
|
||||
>>
|
||||
stream
|
||||
Gasal;,<]I&:VB$n^ZCsg31X@a$G]%@^J>K`9QmBR$\%Hh",F"?-orQs*GQB'0X$2Q7uinB(h^4k2UFJinZOt!f%(GIH06,P&'Q;"\;C.S;cl*]_;gt(<0\)0b%U3j"Ro]p=KT?a':_rZ36f,_-K+YVISDhrqqK#"e;nFC;Oh_'IfE<Q:l"3-r$gh+HSHF8lHOpB'6)%DH'Y0JgthE5Ut!H8u0<8_c]EC(WdZ=T"WkDYBJJ,aG%/r9;-ES6(@.!QZ]:>L]OIWHf'6C)NCg_YL?VmcL#q3MU6F::r/kcEr?iEp>TW$-?pB43-;&qJ5*)&Oi#/;I=l4M+r^aS:SA)MHelZe8`kKB11.<Q,C5:/9Tu\3QeJ=<(*]NFaAS^HdY5otI9G$!=g_J#:02XD\:a3nD-#h$1.Nf%WTq=gEd.<1<&[tu9;B^dh1\Zo,79%5>7A,uZ:<%6(NR*QMY(j3%*%=E5aj0@lfk[X@$tlWL2+*W)'&;B4npquLE!P#gBnJ\=RH+G4<Et+4VX).G[2Cl>Wh4RkH.o(J@f+Ur9ei=gYNsuDgIq#>uJ'CL8hSj2%[XMWtad\f^BJ7AuuGHAXC]fPP4El^n7;Yr9[]IJ8s5Q7-A3^EiXol.>1nWk6:"]1f#`9M<B1-XmL5,Ec/9hYBA(gK<+L0JD;RFVA$2\O$+P9H#YpaX["dXCfq`W^>dW;^(<V@B`[:\+?P>.=.BQWV1kf#UEcK:]QY=!0_u%8a\rN~>endstream
|
||||
endobj
|
||||
28 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1400
|
||||
>>
|
||||
stream
|
||||
Gb!SlD,91]&H88.1$+Tba2[FhVc?_og>968*X>QW1tB]f-HUjLL\7*O"T8#>Y&0=u65"UH6j\a7h-&(Jo?9<<i*b#lS+h"/E70O0NuYY3r@r8PH-h$O5P.%h*Ssm&%LZ_njq.A4j)GXZ3SJ(?i.R[4b`-EtG(@Q7rW,%Dcoq2^S,S@O38bViqY`QZVhc3M4ZH/8!a1[[@,O!f>ZC<*R$7m.'hX&=+nRF]J#!2C8?\qCipKE8CS#gQ?#s@71c]Rs!95ujo=nSm"KYr\Qm?X-@/T;_lSDQgL><Gqb#I&1[C<JMMR#pR;I&'dcJTD1W(%%OZmlV630]]<;BYPj)9rT"J4.Oj;)7oL>XEjXXP,e=`rN@2#R#-T5%t.k2Xm%;`7r<0f?nYChKWF#,;Qo;W+6AJj#(,W'Q\gR@3cNqYuF:Yg*'dhYCs7Ee(^4nhb`/Tq#gtBO\Z:.TW`^I2a[a;4sIF76K'/b`<Zp4r=>eJ@$h[1=.$n,+M19U9]S-4Q=9dC%Z0b4fo@"f,fYn2#"2-!lV<&PfCPUqb_OLb('f""H1:T$`8tqXl!H+7=[^<GNBe\X*#ZNW9i5EECQ)PT[QuHVo0Oq:KsE;THPjq8"p_6a/ff=VcnH44@"23ffn8[9?+$&0fbcm\Rnr.WK$',8aredVXd.+plNEI_UE!Bg_n'C9-:nCJ0aMj6!QBGALtqK,ie[`j^luAX:&(W;4Xh1m$KEU3PpgZTc+aKr7"m&:,]%m-?hF'\J(1+*L"l!&Gi!2_;@oND7"G`Q8<3kU@Gle?D8a.%HZV-k#Ns5,@s:lN6+dPThZ+5Z0^qDTk'4U7a-l=K[N?Fg\m<di4h.FJ'p.-m9hlM#;n1-OPc@#$CR=H4nhdC<\]6D+EjF%GQ8#NgAr.-[3+T)PCId9>>a<"1V7&[WmXg"4@/M(m9hNV`<O?f=VKFYuNWt9G[s!B;OrT^lO?F5R]IYgKjss8K&lg6!B\6NP;-%CgAZrMgg';hGXl]0H3rXV+lasU5>ISb(!-L;(pY4/9A+rWSaN<Gtk`LmE;b/uaL`:ZD>=7]J`Ma#e2&i9;:/Kl/N3[71<H6UJq1kueD/U(5Oo80\Ba?BTR#8/a.r;a$RN(l!18XNWN#uN9QU\Vi)]2nFOVf+O+dZ/p%0=Mi0G^(NZ&E-*U\,k.a<qjo11$EuXSOqKVi&od=B6;66>D\k23RMqmhXU0JU*mf*sBXCnJ;k/RmNfdUSZ[L.%G!4oeT=/"RZh_D8/ub=f,P-s1>D%1G%b+R,iVX%<n<qV`0aE#nT=IWSF![37k2$0Ys9OIG[;C7WE+A<X9ud`f0obI*kb7k:$^nLAOo/1b$O`,<;C'd^T"hrVg<K36<))Srj:)WuXemY$9(pjUr.pb]!M]nZ`1e^B!-67K*~>endstream
|
||||
endobj
|
||||
29 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 285
|
||||
>>
|
||||
stream
|
||||
GapWf9hWDY&A@g>]]89#G1&9+-UC]C]ne]:-+:/6V+n74K<W,Il/FHP%.=ja:s.-rG8'K0E;)[A%<hg&WePl@ZR\cSr@<k.`bJ.[RmrMt<d[67o%rT=JMNM@A>$:]KuNsq8ESGR\Q$C>;Bco_9(Z/hHQ0Yj1%C-mEQUBS]KG+0i/)_IKq*J(Ekj>HJhBeI"qDSmNl'_eiN`qRFK9Y)i/VccfQeS$a@V&3X]m'cT\ig.M/coC)(CU+Jip.0bfPA1Kb;d'/DUi_PI`*_(HuA+quMG%;mQ~>endstream
|
||||
endobj
|
||||
30 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1320
|
||||
>>
|
||||
stream
|
||||
Gau0CD0+]+%0"PUd.$.e]@a=lN8^4#kH6JiBdQOnVI)q[/@GOcCp.cj%V.?mpM(MgMZ\t-84/.)b=[(+Xn2l'D>GsX*@(V,7aV""!HV[+"kIh-0Y3"27ZB&1[b9oUN]1n^%/RZO_ZntJjQO#3H>^LP"/k1g3s-:h5tCs+S2EhbgG:WXaFjr(0ql@c_>4`uL<^>oMBiiaV@$6MZB3O]!MdspHE0@06(_XP=D&]]CXW`Fl<4A.#&>LF/2PTF%$I(]4sQ/#%Rm2OY/pBkk6Uf+;4!@MeBgO8?k4^LkmTA>.p*&p@d:aI,)["DM;8eYLb`&=d>3P@]^1qCnB@/@lhH4kDF8ieh(f#T1N**0m5r9CTJ478Fo/t\XHi;n3\"LRfXaHGJ9%!HnO3oZ*OZ4@!'s[2=GM5>rmUB$FAO0U*7=nMU2=]c#E5=po>`]?4=mmC:rNiOZq7=>k+'I!&ld2"/U4(k\qVkbg[Y$OFo6eC!iW8OrmGb3Y\5uuYMJrb:gGMM.G2B6n+o2f-S]Re5"L>;DiN_n9Qo!LAEud0^jdep&HtNOG_-g5>7nn9XC*MH!mMfjEAVCopb^kIGKmDKm(\S/qouhhQ\r5KpIDZ+NP?r:[OSaDP./SXHX]GYQUWgM.5*(s-C6D<dQg5FKhio/><7OLCO?.Y4+lk3PtN5t._X($Es3nE>6hQH`T3_s6rh<m%f%R@LWao--&`lfLj>TLn-#q`$[Z'q0dM-\05Pi(=%f#!8jI!8c*bLap%0?62J;p,'W&V5OHHM5Ps#_!#g&lOa8/b'@5L?8PPd[KCX13qA5:'Jiq08($7&NADLRMP8ffKH:>u=lYMFrDTMcgH\qe_]6fTdm@M.Cf'AULe*Sa%b/CkCp,;LhkRe$Vd3FI-P"100;mcun2A.$=JGXaQ"ko6Y-X,Zu0p$gLlD4AI,5$f*8:)'j)or`47d!@Pk`u!coeN(aI1jg%*qJuIMa]d5&QnE`&Z?Oo2J##_QhQHs:IEVQ94Z[b7N$D'F>:bN"1R%oG'*5n%bIe#ip\i@Ulgo)I43>CC9Bn>I[nA(9lNdI7`GZ*P.Ke`)RmVf(3nA_2h_RWc4"=<m)<OqrNG):V;edO]T"^I6b>6Te0#ll7f8!!5%V\+"-7Id''DPI5Y$hha=#*B\28t7=2'6_+rqi=OEiWjGF_^-mNZ2P;`n$>f8?a!R#4(A"6j^im^P"p:MO<h?60q,NMZE):eZkAUaX,33C;2:J1O,f>3Y0r_-+*!FQiCjdRHP_S&u<mu*7Cp0(-@efNr*YD.7]pKPGfIF?CM4kniWL4(NXdBeZMh:j'V9>gdM~>endstream
|
||||
endobj
|
||||
31 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 729
|
||||
>>
|
||||
stream
|
||||
Gb!#[?&tF>'Rf.GgmBusP5tkn"C&=V-JcCPRVY@fjF\ul8f&=*%(_2_hg=mg&XtWF/q*r`;/t`gq_?,A"W]8-IeFG*3u>8N$If&7"?KM;i'+qX=8AuFm5Ia,2/U7.0HAaq[7qUliGI,N/U_$E+o_86W&Lq[<85nmedr<gb`ift<Bl5hNG@E-(f1kKK=ekgLc_@WqH'M%)n;H.!7bjrgAM"@o`lY=<(Ah<*u$L2[gud.Jc"a]pq2/#>(@]AH2cVmR+'/5cY$cWN6^SZm2B<AFVDoVa0EcC)=]Ob'/,hs-f*&%8Iq=C&!ZNqC4_Lg&i*gG"-Q;1rlHJ0i>2'oR@<UKG2]EY25@TMNtM,kW]H))s4"Ie_.4]eUd&^HgWk)#dV!f:/#V/l)[4c+M4618/9K%6<k"Fh@FJd9@9U(i\aM[T@E`%#Ot=_3cVhm'3@-Okk%2I2^CWCA,id9`e]di@M(qN(M<'OrH@'8QIK9b/V\tm/%o#ncZ$!_=W:M2B=9*F?7B)Ig`dCA?;%Tu(o#X!@[@#F@\7!7fSt$ko-jbek"t@2AO(s.h?6"0l;en!e0ltJMQ;JdfA!iu2qQfrWL$Gb*r'/O\hNlnce?BUi715,[l2IZDlp[("\X&\<4I%1#5u],67/OSSCY;E'FkS=8Hcl;tX.&Z5?=0fen-+tumT/68eMH0@#Ud;$k%3n92]:UZo6L8F7X,l3p^7%b52lag+-(qO1&~>endstream
|
||||
endobj
|
||||
32 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1335
|
||||
>>
|
||||
stream
|
||||
Gau0CgN):C&:N^l3dt5:#suMa*E">ij4%+Hm5eB"0:![aWPN)?OYS_u9i:h8H?A+Hgq4s;`<auY5,Y<jkMUqZ0/re#,Co)'e8JW3)_`7agU*G(quV?V/,rZ*_Qr"%gV$)&KhgC1h-R]`cd?UaFm+_kgT-iDaJZWY6]NAud/^YHL$4s*ep#@O\?mp*CG\*1a&*HW'O'&eM)F/01:"<6"jd#ZEr$Y;Pm1R&$H"5.IP_oAU=V#fNHLa1@,.>>j0fANN4*LUmAC$:%G*+T&2L+kJg6]S.7sb9@hbW@i>SWlBaTnU63]+gS2n'MM:#TKL7VCq?Nmmr-'j)d`l&!kN!YA(+TY(MVo%%*9>8t%No5aY!>f^-(fFfjW;K/BcR=6'Ss;do=l6o1YNoHe@!hkLc\gP1Q\sU74.U7&[TD0g!O](U2nLZR997Ih%j]$ba"6^L^74LjQ>ecYpa($CjnhEF&H$@r5@gPuX,K9@9op:U5Sd<_)IWYV)+SWhOnnk5C2(C;/T\Z`rOj9C;*A<UmBlnZBHE'hCHY<eXdS>66DGMV+/,de3uKCQjsuL<'pM@]\Q/UFs8Bi=m)>i?I*J;e3+cm'M]s97AL,Tj6fALjrCm8uF[$#$*mejJ`[p%Wnd?kq?h3Lf(bAVN=^r3soVtt_r0YD,R2:Ju39"GOT1:5[&<.'<^sl'QeFP]6cTrX@)N@Q+X[2s5Du9?I/h;+:V.Ft/cn8EMomKf^@!Z6<!*1[V@QW6d*ttEdhkC!/_C!Is)n@NVSuZA5^Gra$):trF:1l%RVc(=6q6u#\T.0Gu76%g(po8*CM(!+Ua13Tji("E)_o*7\OS1DpAi4'[+.6.A\=Te6\+V3-&H@??B:Xd^#T`EtFk/%9_,?cQ)Xeh301LU8Z%UDnU28F#ku<`l&/_6IdtF1LCf&'XH#R6_S\E$o["(@]bfr/Zij"pp,teU5<R2^Mi/3L\$jQ<4KUt?D=q/-o`[Mp3UIf;:VJ)tOZ=\?,j;Q>bGB6>j%?PQZ!XqWE4JV80-p!C[s+W.)glJE<\=V5SmqV\4qSP3o4i9aT6R;,RG@:-E-^S]gPK(Y*J/e)BpO63n3mP9YIP[=u/4o+5SYPk)*^%pc2F/SZO!A[,XWKgXbRp+L4'2C3GEc(WX+(hOett5-:eWT30_doR1#;YN.BiTg0m7jI@^gK/II0)?IJUP@]MVugQ0nd_;)Hn2cbX>T\4jliG/p5`SXNa#qUQ(>AJd^-<u:4k:RGk5D0<OgJ9+`#eA2@]*>Qm!o4ngBP:Xl;EI$@F'$(Yd\C!BZi$:(CQ8Hlq;4]1OrHDLC)](oD'T.1CX0$,fb($1\poO~>endstream
|
||||
endobj
|
||||
33 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 630
|
||||
>>
|
||||
stream
|
||||
GatU0d;GF-'Rf-p:A[F/@5%fkh6KY@QDmb>XXi*=02?IQ<j4$?,up4[T:N>dP"&ZR#fO9>n%Io:k*X$7%paZ4'ei>?N[UieF:-_LIAF@IP$3n^IE@Fq&g`"$""tcRM%X*lVb*Ds?BF(VIseXpLkS9\aLdE.35fE@#ro28qf,/9>m?bmBK1__et)61-./he)T>5t:hk*_UB%P28uSYQco9V$JFin$H:WO&@3S.@:s6/_!,TL6$8\j!lgaK/-I;%I2(cQT.^S;`f#r@]en(`+O_4261Af9PbBeEiAfbLMK90gn4/&WsRi`oXrl3Z2eMTZL^Q7mE#4hS.9M3mEhcRi&k6kqVkrkutdTJP0Nb[g_:.`r1FM94!oY1#haU5W&V>*qKrj'IA$K[4XWThF#na+0"3<Jd(nQ*o2=IgSi/a2H"s!\[)aejZkNLk<tdJ#D"_>Q$E=(V4.s&$9"6Z%!48(tb&CG3@UE>WU<A)cMTTsmbC0)+AH^C3E&+Rs.Ki[;`[`l1"te[GbmN(r,j^UEELIA,H5:A+-^@E'E,CJZEZ?b(&'-`ekpSd@O*,;;l/;6l^MCYUFH<ErqJRg4(qcNTq'i4c8FR'lj7I<Noi@OtZGT,fI#efVZo/sQ~>endstream
|
||||
endobj
|
||||
34 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1425
|
||||
>>
|
||||
stream
|
||||
Gau0CD,91]&H88.0pb\p"A@<h*%+`:!QPq$*%BgGC7D6W,_NF[A,Fhm\-hc`46sAgn<S\W6#dUbmQCBj4HCj0g@XD#qfi-\kemBi%bq-c)S![)nB^%FDgZ9g1=ERtgTu2G\t(J64h!rIkVfbPX6XkXfj<G$=ho?lq#_?gBMZ@*`a;OL$`lIEGs?r4#K.1D54"=F$B:.'5XkfEEH[8f%eqjLh]!CKoQgoQ[o]6(jl8LfOEXBer++TYA\:b-r4uA:coTK\MAjo26kMm%KF*4q"(G6G\eRO`&7L<T@l).Sp2*52#r3cG(oB"5+q6k,$Sa;1YscrJn,_L&ic$(DK\oP*A%#8eKSHHo'iTFti"nD+F?EQDG"qk]$A(USY-LHS7#Gr0IW^&&6Pp&K/D/-f\NMnOAE\>%TX,'"dQU7R3n782>41P/j5m,NdNS^IE>Vk[(G=%:$orA+0Ba6k@LT]EYKL#;]Wo2#k,cEfC)DZpI#b/tP06us-\F]O4Du"F%\/>s3f8W[^e\ol5pE!3A$oHNTIoAlW\/09FoUP*4'm-=!++!-$9#)S5;u[LDB#\?[_&+5Ro_(9"FHa9GJ"FWBGkd$$OYk^I@b\S8oEfsnq'LR]U,SPgT,Y(XQ`G!X.oF]1Zg&K\i`1GO5\^,g$-m+co_TOp_K$/6jl7LWF8#OMFGeOWkis0U5srM1<K*a56);7dIN4Q:]1qd3]TD#"N-O+)%Lk>W:/j\O$em?/`Z&a_3W9qiKdib&b,C/iS(>L@2B]kH!T#J=a;Gi#C&<HB'HiO!1AG)ZO)A,2D52*NYLQW(Ld^r9Mgjq!Ekl=bCY-3+Oedk4N=Ymmqj4KJZp]cQOK-)N'uP;A,81?Go;n'o3R!j.8X$=0$K&tKP45(>lg*cm35a_gp5c99B"_#P6uNhDcHN25&^_(7HYUU'&RbV&-X1(TM]8d8UK=EA*SOQGN=`eo^hQX5c%"bp[BD`><tE:Q5hJX'cpRbfX6SQ_cF)tK[nm;iX.[U>BcqZ;PUoh1dB/$)6OSrBYs^(Mc1%(9T,MNO\l[a$/)Nqil$@W_uT$Lb"*lOFI)M1N<SblKN^6]1bpJ*nmLi!R\"stGtSG/'NJ+3Fu.pQ&,k*YYjZUKs2[dH!kCsL^1uY>5hdD$1j;OP)Ugl-`;T,)pGmV9T>.k@1995[NKnMH;(ntq)=C=rQ%Gel9&fstc![C).s7]8!:`)lpPKE!6IHalWpFS'(HT?ob2h?:#Nij"5L(X!27N'Cm^3r,SfYMR;r@UMQ>%/$.?^KsXS6F^7AeP;>G,i:TR#SAoi[+HK2Ln_<3,$m:!X53`JGl-jE923A4hP5!n8E_4BT9P6_D`ZlW>aEOM3N^*QO(k->?bP11t>kU\7Cteml-[)42,-H2YR7_1R,ISto,-pG0:Nb<"0,QAYr(rWA1fG7X~>endstream
|
||||
endobj
|
||||
35 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1337
|
||||
>>
|
||||
stream
|
||||
Gau0C=``:f&:WeDFS([Q'F9@H"qn@fPLuj6AaS.>AmD;9[:$YY1,Au0'`WSc#=<qAJRbi#8^l;C-O*Q7D+)-+#N/Mk.b=kA2<\1NeFblp^;EsSn>fqB-Q=qVdAjS_\8:D!X3nR&3dRkd>KuGY$T?W6Y6Fk+V?OZ`W*VCJYdoWg_1cncr7%2PHBZG.dV+.rq"2:>8"<-s,LqrF'>'h<7Q&\sEd\Fai=-0:UIseg>H8T,nQd7LL,MP']fUl''0u#7oIY+(pOn,Yd#"o7$=Nt$n/TdXZD#]1UrV)IhKsf?Oe-]8VCF3fn.AUSF.]:lJ^4NoXp"Z.Z2(&u]UbaQk\q<bR:rk@<aZ+!0OtWb8M>c^4PTkO7bBBfcX=JM#17V)$p@ZAGk`#H$u&?W;;EN7O3gI8mM@a_J+hh$)p]&ZAAmRfhQJ_\d'OF!g>cUB[`;)0NZqN]j8D"hMqJ^Ro0FN^&TP>gG=UC5@Q/I2/e%j;nAKC$bVWf8Lc4fi-[tpD/pZd+$:.!QfC]j3%J4hd%t'RWbc$V!/pC$[[D<<B!>98`Ad?rmW<>4h(Pdrh]-H]'*F50^7ZrKD.j&srAUR_/5=BgQhMjA;8Y603`G87C/91_Dd.&Gci7B)7!@r%"P6;cZ7X(ZJn1fCAJJp6WVukqL?unMhojt+Y`U,W&MEabLZY"3%e*0,.FoO"bL_iBAB!,iX2]+MZ&`cXbG)*UQT#1@g/EHZ8-_.4D21Rn.kG\7Z6_7ZE.c&uplB\3._UgFj&aZQ@>D,kUgT5;u#qHbSUbCrfI_!^.kEAUk]#1f2:DSmLeP-^N]Bj:iDRrpD4g;U3+0mhNq;msDQk)Y*^:=lU/c*us-jW*H2c9as#&#))1qa9:Pg+b/.VhPE9+WtHp``%oRW`S-p15,G.AJ:t2LR`Y"NZe3'm]Cb^PE>M3faj<([&#m"(:X[OsJa@N06Gm'\G;bOUoKe6EL]ha#Nu-4=fG<QQu0o+H-bT@Pn!mbGFr7WKp0'*L&=L]3YNRQS$mBP"\Z%DUL[S`s:dA3[S\G*/mfpkN7Wj?Up(\C`Hk=QUhDW8cfZXrB?A<^SJ3ZQiM'o7"HiBPk:ZX5Ijnu73aoh7%Q`V?\QIU17lh\7!m)G1`^9O3\lM3qk`.E#$]mojI!keN[QKIVQf_cGoYAk%aFSAB7MslF8,QBF>EZFrpMQjDjZ.tD-FBbU>W7YH!5AbE+WYs-kH5r6]27k%dqXM)]Mp_@3ChN1E.mk<TSdEPISHPjK(!n*.o\,p_WE'8ls$PVFF'2RR^p%hSrW8F1WiUErHiI!mPb\=q.1,Y<eSTYuis1cQ46`Y'Pd`H:-Y@$q=4`~>endstream
|
||||
endobj
|
||||
36 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1211
|
||||
>>
|
||||
stream
|
||||
Gb"/(;01/N&:WeDXGl192'GO?Kdo,^C\>LUWu8q_*k[R\>e/Xdab@/Yrc^"%["Kp;@h*_p(qq8^h!OOsI_3.s_,=W%ruZsqa"B2ED6P%"7prgM(:YIEX]rE9g%.;[NnNh]?$/rDCYITf=$<IMbtb`Xm<;tR5JO7e#B3g%]5?l<dt1SYK,OuiPPn[U"1+aDK6F:)0uEJ0g6q5/M.GL7fle@cSK!/tAWeoHpYdg<0ET_3PVi(SMus(S.5YECh",m/@..`WO?N<Q7pd#c&oe2/In@>8b2-r.\BhB=]C#Fqh3MKj8<S?G+nk1m7##A[)m+G6o]k=\T<$o!Bk:TLFoXuoA?_kfa2Dou'!J*nKN/OdL6:EB#goPa#bbn`-0mG&`e4I@=dut+HL4"DPY.%hOYT@;KXtJ'9F4@s2nMU8O]:fWgi=D@r^I&WTEZAmE3KR19t":3$-KTb[Rpg(OuP^@k&sjeGV*DY\bW'V8f<9&E53-lO"nQsjZ`O0-Tkjq.`R(>&UX1(;T7KQ_DH=VdkiqC*TKR\A+ZHtft8s^o/Af)TDnfk/+i"hl)u1#MFlLD3r*\@U+@W)1F1A@0k_9!c[i*h\6@l!(c:lRj`]otK%I\=/q@PCp`iLl(g]Kn17G^/72qD%4,IYlb`c)d+WHu?1@.=g>6em''8c[daE>$85Mm4/b-9her.*]]lmtZqMUaUg.]e9a11Kr?cP>rZTZUp@cgP).57L'$rS])[1$!m*_^f]a8^[/uHfA36Et\4F.0Z?MG]C#X-RsaX;auP+N(eGW937Z8'[nhDDO%TOYXDoF+fV3P33]Ji&[)UQA]XZ17a=BEK'6r2Q-MGc[e89i(@es>]4cEU2/dK"WLuP6Xc_lX<>+3XDk[SFAJ@p?Bh!HUPYr&]<qsUlEa67%Dh][35uHZ5JQ%+#E_X8IFc^BF+"=aLP-8\'meT+ALr[m2c'TV;j[&"BIWnr?$T@)*\J&>1WPj05E*h2_*O?$IKo1Ys<F!c*Obh)?b%k"7k_e&ILVR](+6*m#YA(ice3=6sWJ'c&9T[jVE1k@jFjX'p=7i/'m[l9?HS99+$Jj7[>ISdADlhdNd;oe`GP(V#&$04[/8rY`NdB/o6YN("niaN\^3B>Q)XgNiJ.09]TCfs0@\V_3@`=ukJP`a3S#Y,=$!\)LkO]`\Te95,<DeS-KG0"U':IZ2'OeokjeEP"T_8bJc]hr~>endstream
|
||||
endobj
|
||||
37 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1621
|
||||
>>
|
||||
stream
|
||||
GauHKgMYb8&:O:S9`3tI0[9L6"e%?0S>9/+YuIA]*!@d3/5[V%oPuD$q>/Ah.>`(6;b[:^Ybh$Zbac"\fqAQr4dQ(/blD(0iU"tobD,Nr=K^W"GR/rldI!(Hm.>/4O6jr>^^CQ$nfuR-Z!mNQi-JcjU$4s'(m1SB5g580VU]]CcH(\K[W\AD%cQJ+@LCsPN3SV75DSb1`\3S6:\=#FmC<"^o"B7"+)NqJ36NSC(-MMB#gQb/Z[C"^eDMtA3*iCQ.Jn,\Ie3_[h:aG$];=>0g?k!n!b2(f0NA*F?oJ;fQDRd$*K$\@$*RJA'?jm9YY5oJcOKs=q1`TFIeU[hen2he*gegp/_Fs$[)q3:<!W,(7,]`DY[B6i+q[HrGaapp,n`[I_'Z6O\3A"JP`R$q8Fk4<1G8+!T-(l#$D3j6+C1]g!L!%Z!\\(N6-G'LJRXMI<*UeEPl:BjaEqt*J#(2L5h?]FJ"[jH/4kC:PiPNeTH_XH3A67WC=N^Y-`8XBJ/M@A/el8jQOp"=2Pjk`c6o-=R(c-oECh<'A[7[D;!+>g4ZT@FWB_eM*JQV_DRdcf1ngpG@9EoVB(/`_E!Oaor?nN5;'creH,c-a+,\8L76-nd$XG/7Dd'sXi(`CV_-_:sd5b$YWpZ=mY@G@hPu:!c:a?9FMAr!Rka?=$F*?C,LAuV$N<QL4FIC?5QUsC,6l/:HD;"3)_RAq$lTQ[RLB\#3nnWqXgBE.Io7CeYVqGR8@;?AWZJK(ZJPGe@%mSZLT"Rp8f.ms:n!:*&m'UZ?mZ1I.pG1R0*:0NPA(]JXF(88^F#HEIl?4u*[8J4P3snr-S9u$@EWNLI(:<d<!F;Ec(i6X1-rOB;]34`M2QBr,$qK5h_oEQEcT1[+,`a,/EL#O48>JS\Q--:A;i>;S0;ja!\;s2@0/#(1B<"h/ftE,$]fYmY%.Y.7kU)'7O-*7Kgul4FHp@CQr:T)WYD2Ku^-Wu6pDXQ`\:P=s[DY6Z[\p7OWHh)_,g_NY+CVfR(>fe:+D*8gOdl$S*FB7GW`^XsHWVRVAZB*[S6JP'&S\@=Z@I/f7t[j^+2Z%B8?r;%_h&cGe-TL!kgL)dRc-Ht[CbfP:#k.?<uaZaais>A6dZo6km[qJGYJr-PlrLG+0*>3;.>D]H$s`3ge_"4UA@J`12;WO^)U8P<At$)m^6uCX\desPI'Qg\YL/db%d*eGYD6bW.B0.-69/4[<Ohlo\jP4TKrmpU,hm(hQSK[6k>)Vj)**435q#7fL[Hj:Z)T?7*ndhK:3_LHb;1m<JaeiOu2s8kR`err$Ka1[Rt.mV=DPr=Qa;f<`*W?D=72Pc<J6tAoHN'oJk0M@.u?b9MJqq+7)Jk%8K;[e+I@k0U`=,$^>beX=n5A3qZODdi2,L<K^4sL8pp*'t_(Wc#\V;NErB@UHhrg)GE>El)W`G\Xn()"-4qh6(CIucMJecfDf5<\/<*k\@h\-BDlT>F%]BT)8FYhilDBM2+k[%c`8upL'MplYp.q/H"rba8;k^#^teapg"P*4dU>\+,qY6_DFE?AHaVXbB]NibBXnnX\Y:BJbDh=tM7/5+)j.Z56S6oa?jB-)"l\fUE7PT%^oScTE,6;*cCa_28,iSS4]Z\~>endstream
|
||||
endobj
|
||||
38 0 obj
|
||||
<<
|
||||
/Filter [ /ASCII85Decode /FlateDecode ] /Length 1634
|
||||
>>
|
||||
stream
|
||||
Gatm;gN)%,&:O:SD#G""j3RpR&Xg,jini*Y'5O*Sc#d>*Q6Ck\9gVmE:B/!8?:7\W9M)3D&d;e>loE!:YU&/d7EY(%$Li3?QWF:qKuk>Hhsk.G&O&l`*`#=D),_i@BhVnSN#`Od1&Bk96UNp.")tooojS8'm+FVEk9l'W3aj?aL7gfT&GGuGN.,)j@`@qo1RK_$Ec*+N_J<@TcS'e$W7qbP]J`#Y`'o[h2Xd-Br.Yt1V=L:TFi3fEMV5[g1JB@l_G8l-GZ^\AR,udKA*g&s,N:s+Z"5c'SE67Y%N1`D`IQd@m")4kWkfYUP6EKs.)??T8B,[PZ(eV2oLJO6n-tR*@7G2iRQkLMkN^:rD!>+`DSNl>S"-`DV"cB+9?u_i9e96_qIT]aKb>hE&nhU@=s=L():C#.KpZPUi(bq"b%2dH*,`^s[$o_]JdI\oboZ1A?&(h[o.+p8B)[/+lbhU,B.t>hBq7Vb\<Is?ZV7ka>YWQ<8@fq:/X]p5n,LJ>pKV`4\\"],)5.clMW)E7bIK'u@n8*(#Gnct_.Qro$[C\,8h:UH_bq>]?=rPi(&Z$u]Ja+CY28k#Qm*%X$<WT[WjP+M'[pp9KNnhK[(tN6i(kHREQRf!V4N5W?5Q4$c=[?fA^)!lj+g#>SaWg-T'Nm3)"5\@J-9Y?a":HB//d8Ra_nK(C;n4:H*LMYUR(q@964Gh'M@XN\m.MGkFsXjcg?65\E+TlG[KDnY[YUQndiWQrGgnO@I3A\l[,bMroHJujV!m@&s_SL:9,8Y$tr>7Dg#4=aY/Yp8na$@@5n&N,>-X^4p<SLSLAH*G`;r,NgYBWR.b92W4U<oM8qIBA(\HG?6kO8Oi]RF#!)1.OhIm.L60MXV*3mQX/l?[E3%8*Y.mud!%r\Foub:/6<rXdXh1#sdY.r<fsGPCXHQm01P35gR9GUC(T`mKgjp*_GIUI6FCH>K2D-quh;<68PreUl=,*jBQ^GBn$!bs`n(d"cSW9R[6Q0^SCYZL6L>uU_E<e2aQHR#*jd!;:I]KZ,X2CR`';.>@A20a27",;;Pbe"Ld<PSDq`6iQWRI*4bFD56DB99%nr1KNq*itpBN7_rkL6bi7>8)MjH'0DWi`IX1q4lWT!#;Y9DD@^\rfcWEd@c&U#^X2IN!G\9>6I;g&p*m'uPIR<Zj&]dP,9n'%,Xj5&&<eT9r`!^]'B9-A,:Jk6P)WI':I49tb!hRu<!&%=R"]CrZIp2BmiL./<PPjbUh!qUg:+C>[@m/9:t0)4j*r=3%8>dJdOXo9g)%):s"sB<sbRf@HQOcf"cV\gta#OJuaBpL9aYBuBtN9)R&q%]TkG`E+q/A1K!]NfMiP93E08h7]ud5S["4)]%$%^Z-<0^oPWDeIm5JR2#GmnS1<UmI@>9L3G]'[)-1j.&`iBFIj6aJ/#-q^?-KT5AD!BrN7mu+K>sd*.,frj'NtCB845C2m`DDeYRl&4mB0F=e%HKCth_;]RTqF`!KhZDF)a[NNkhWfB&7OST&rUFutF!P8uosL$_X_(<lKOSLHX*:LSV(S\j?3$@C.f'Fr_n?;HV&Y,=gOL)i0N;3+/qOpHCS_Nof2A)R5)Z$ibI7.Yk8.5\foB1.0W>$=#$*]3J\apUuD"4e'?F8~>endstream
|
||||
endobj
|
||||
xref
|
||||
0 39
|
||||
0000000000 65535 f
|
||||
0000000061 00000 n
|
||||
0000000143 00000 n
|
||||
0000000250 00000 n
|
||||
0000000362 00000 n
|
||||
0000000567 00000 n
|
||||
0000000672 00000 n
|
||||
0000000787 00000 n
|
||||
0000000992 00000 n
|
||||
0000001197 00000 n
|
||||
0000001307 00000 n
|
||||
0000001513 00000 n
|
||||
0000001719 00000 n
|
||||
0000001925 00000 n
|
||||
0000002131 00000 n
|
||||
0000002337 00000 n
|
||||
0000002543 00000 n
|
||||
0000002749 00000 n
|
||||
0000002955 00000 n
|
||||
0000003161 00000 n
|
||||
0000003245 00000 n
|
||||
0000003451 00000 n
|
||||
0000003657 00000 n
|
||||
0000003727 00000 n
|
||||
0000004008 00000 n
|
||||
0000004161 00000 n
|
||||
0000005204 00000 n
|
||||
0000006525 00000 n
|
||||
0000007362 00000 n
|
||||
0000008854 00000 n
|
||||
0000009230 00000 n
|
||||
0000010642 00000 n
|
||||
0000011462 00000 n
|
||||
0000012889 00000 n
|
||||
0000013610 00000 n
|
||||
0000015127 00000 n
|
||||
0000016556 00000 n
|
||||
0000017859 00000 n
|
||||
0000019572 00000 n
|
||||
trailer
|
||||
<<
|
||||
/ID
|
||||
[<ab4fa5324f02268490d94a51d4d35c59><ab4fa5324f02268490d94a51d4d35c59>]
|
||||
% ReportLab generated PDF document -- digest (opensource)
|
||||
|
||||
/Info 23 0 R
|
||||
/Root 22 0 R
|
||||
/Size 39
|
||||
>>
|
||||
startxref
|
||||
21298
|
||||
%%EOF
|
||||
145
Les08-Van-InMemory-naar-Supabase/Les08-Slide-Overzicht.md
Normal file
145
Les08-Van-InMemory-naar-Supabase/Les08-Slide-Overzicht.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Les 8 — Slide-overzicht
|
||||
## Van In-Memory naar Supabase (10 slides)
|
||||
|
||||
---
|
||||
|
||||
## Slide-indeling
|
||||
|
||||
### Slide 1: Titelslide
|
||||
**Titel:** Les 8 — Van In-Memory naar Supabase
|
||||
**Ondertitel:** Koppelen van Supabase aan Next.js
|
||||
|
||||
---
|
||||
|
||||
### Slide 2: Terugblik vorige les
|
||||
**Titel:** Terugblik — Waar waren we?
|
||||
|
||||
**Bullets:**
|
||||
- Stemmen werkt lokaal (in-memory data)
|
||||
- QuickPoll app: / en /poll/[id] pagina's
|
||||
- VoteForm component → stemmen onmiddellijk
|
||||
- Nu: alles naar een echte database!
|
||||
|
||||
---
|
||||
|
||||
### Slide 3: Planning vandaag
|
||||
**Titel:** Planning — Les 8 (3 uur)
|
||||
|
||||
**Timeline:**
|
||||
- 09:00-09:15 | Welkom & Intro (15 min)
|
||||
- 09:15-09:45 | **KLASSIKAAL: Setup** — PDF Deel 1 (30 min)
|
||||
- 09:45-10:00 | **KLASSIKAAL: Queries** — PDF Deel 2 (15 min)
|
||||
- 10:00-10:15 | **KLASSIKAAL: Componenten** — PDF Deel 3 (15 min)
|
||||
- 10:15-10:30 | Pauze (15 min)
|
||||
- 10:30-10:45 | Uitleg INSERT + start Deel 4 (15 min)
|
||||
- 10:45-11:30 | **ZELFSTANDIG: /create pagina** — PDF Deel 4 (45 min)
|
||||
- 11:30-12:00 | Vragen + Huiswerk (30 min)
|
||||
|
||||
**Aanpak:** Deel 1-3 klassikaal met de PDF. Deel 4 zelfstandig.
|
||||
|
||||
---
|
||||
|
||||
### Slide 4: Van Array naar Database
|
||||
**Titel:** Van In-Memory Array naar Supabase
|
||||
|
||||
**Links:** In-memory (OUD)
|
||||
```javascript
|
||||
const polls = [
|
||||
{ question: "Favoriete taal?",
|
||||
options: ["JS", "Python"],
|
||||
votes: [10, 5]
|
||||
}
|
||||
];
|
||||
```
|
||||
|
||||
**Rechts:** Supabase Database (NIEUW)
|
||||
```
|
||||
polls tabel
|
||||
├─ id (1)
|
||||
├─ question ("Favoriete taal?")
|
||||
└─ options[] (relatie)
|
||||
|
||||
options tabel
|
||||
├─ poll_id (1)
|
||||
├─ text ("JS")
|
||||
└─ votes (10)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Slide 5: Supabase Queries
|
||||
**Titel:** Supabase Queries
|
||||
**Ondertitel:** Vier operaties die je nodig hebt
|
||||
|
||||
**Queries:**
|
||||
- SELECT alles: `.from("polls").select("*, options(*)")`
|
||||
- SELECT een: `.eq("id", 5).single()`
|
||||
- INSERT: `.insert({ question }).select().single()`
|
||||
- RPC: `.rpc("vote_option", { option_id })`
|
||||
|
||||
**Tekst:** Dit zijn de TODO blokken in de PDF!
|
||||
|
||||
---
|
||||
|
||||
### Slide 6: Server vs Client: Wie doet wat?
|
||||
**Titel:** Server vs Client
|
||||
**Ondertitel:** Wie doet wat?
|
||||
|
||||
**Twee kolommen:**
|
||||
|
||||
**SERVER Component:**
|
||||
- async function
|
||||
- await getPolls()
|
||||
- Data fetching
|
||||
- Direct naar DB
|
||||
|
||||
**CLIENT Component:**
|
||||
- 'use client'
|
||||
- useState, onClick
|
||||
- Interactief: klik, type
|
||||
- useEffect
|
||||
|
||||
**Zeg:** "Server haalt data, Client maakt het interactief."
|
||||
|
||||
---
|
||||
|
||||
### Slide 7: Pauze
|
||||
**Titel:** Pauze
|
||||
|
||||
**Tekst:** Deel 1-3 klaar! Na de pauze: zelfstandig /create pagina bouwen.
|
||||
|
||||
---
|
||||
|
||||
### Slide 8: Zelf Doen — /create pagina
|
||||
**Titel:** Zelf Doen — PDF Deel 4
|
||||
|
||||
**Ondertitel:** Het formulier staat in de PDF — jij schrijft de INSERT!
|
||||
|
||||
**Stappen:**
|
||||
1. RLS INSERT policy toevoegen (Stap 4.1)
|
||||
2. Copy-paste app/create/page.tsx (Stap 4.3)
|
||||
3. handleSubmit TODO invullen (de INSERT logica)
|
||||
4. Testen: poll aanmaken → verschijnt op homepage
|
||||
|
||||
---
|
||||
|
||||
### Slide 9: Huiswerk
|
||||
**Titel:** Huiswerk
|
||||
|
||||
**Verplicht:**
|
||||
- /create pagina afmaken
|
||||
- Validatie toevoegen (vraag niet leeg, min 2 opties)
|
||||
|
||||
**Extra:**
|
||||
- Delete functionaliteit
|
||||
- SQL queries in Supabase testen
|
||||
- Styling verbeteren
|
||||
|
||||
---
|
||||
|
||||
### Slide 10: Afsluiting
|
||||
**Titel:** Tot volgende week!
|
||||
|
||||
**Tekst:**
|
||||
- Volgende les: Supabase Auth
|
||||
- Inloggen, registreren & bepalen wie wat mag
|
||||
BIN
Les08-Van-InMemory-naar-Supabase/Les08-Slides.pptx
Normal file
BIN
Les08-Van-InMemory-naar-Supabase/Les08-Slides.pptx
Normal file
Binary file not shown.
Reference in New Issue
Block a user