Introductie
Deze opdrachten vormen samen één doorlopend project: een Student Planner. In plaats van telkens een nieuwe oefening te starten, breid je stap voor stap dezelfde app uit.
Zo gebruik je deze pagina: elk niveau hieronder is inklapbaar. Klik op de balk van een niveau om hem open of dicht te klappen — zo hoef je niet ver te scrollen. Onder elke opdracht staat een blok Bestanden met de exacte bestanden waar je in werkt, en onderaan staan theorie-links als je vastloopt.
Hoofdidee: je bouwt per niveau verder aan dezelfde app. Zo blijft de context hetzelfde en zie je beter hoe losse React-onderdelen samen één echte applicatie vormen.
Wat bouw je precies?
Je maakt een Student Planner: een app waarin een student schooltaken kan bijhouden. Denk aan een dashboard met taken, filters en een detailpagina per taak.
Dit moet er minimaal in komen:
- Een dashboard met een takenlijst
- Taken kunnen toevoegen via een formulier
- Taken filteren (bijvoorbeeld Alles, Frontend, Backend)
- Taken markeren als afgerond of nog te doen
- Zoeken in taken
- Taken bewaren in localStorage
- Meerdere pagina's met React Router (dashboard, login, taakdetail)
Nog niet nodig bij de start:
- Geen backend of database
- Geen echte login met server
- Geen perfecte styling
Hoe werk je deze opdrachten uit?
- Gebruik één React oefenproject voor alle niveaus van deze Student Planner
- Breid per niveau je bestaande code uit in plaats van opnieuw te beginnen
- Maak binnen hetzelfde project aparte componenten, pagina's en folders zodat je structuur netjes blijft
- Begin klein: eerst layout, daarna state, daarna interactie
- Gebruik de theorie-links als je vastloopt
- Werk per opdracht in losse componenten, niet alles in App.jsx
- Test steeds tussendoor in de browser en in de console
Styling door de hele app
Je werkt gedurende alle niveaus aan de styling van je app. Per niveau staan er kleine styling-doelen die je meeneemt — de styling groeit dus mee met de functionaliteit. Aan het eind maak je in niveau 7 de puntjes op de i.
Kies je eigen aanpak: je mag zelf kiezen of je werkt met gewone CSS
(CSS-bestanden per component, bijvoorbeeld TaskCard.css) of met
Tailwind CSS (utility classes in de JSX). Beide zijn prima, kies wat jou
het meeste aanspreekt. Wissel niet halverwege.
Voorstel projectstructuur
react-opdrachten/
├── src/
│ ├── components/
│ │ ├── Header.jsx
│ │ ├── Sidebar.jsx
│ │ ├── FilterBar.jsx
│ │ ├── TaskList.jsx
│ │ ├── TaskCard.jsx
│ │ ├── TaskForm.jsx
│ │ ├── QuotesSection.jsx
│ │ └── Panel.jsx
│ ├── pages/
│ │ ├── Dashboard.jsx
│ │ ├── Login.jsx
│ │ ├── TaskDetail.jsx
│ │ └── DocentView.jsx
│ ├── context/
│ │ └── AuthContext.jsx
│ ├── data/
│ ├── App.jsx
│ └── main.jsx
Niveau 1: Basisopzet van de Student Planner
1.1 Maak je project aan
Maak een nieuw React-project met Vite. Verwijder daarna alle demo-inhoud die Vite automatisch aanmaakt, zodat je met een schone lei begint.
Wat moet je zien: een lege pagina met alleen de tekst Student Planner.
- Nieuw project:
npm create vite@latest student-planner -- --template react - Aanpassen:
src/App.jsx(alle demo-JSX weghalen, alleen Student Planner tonen) - Aanpassen:
src/App.cssensrc/index.css(Vite-stijlen leeghalen)
Klaar als npm run dev werkt en de
browser toont alleen
de titel, zonder Vite-voorbeeldcontent.
Theorie Project Setup
1.2 Maak je eerste component: TaskCard
Maak een apart bestand voor een TaskCard component. Dit component toont de informatie
van één taak: de naam, het vak, de deadline en de status.
Wat moet je zien: een kaart op de pagina met bijvoorbeeld:
- Naam: React presentatie
- Vak: Frontend
- Deadline: 15 juni
- Status: Nog niet klaar
- Nieuw:
src/components/TaskCard.jsx(component met hardcoded inhoud) - Aanpassen:
src/App.jsx(importeerTaskCarden plaats hem in de JSX)
Klaar als de kaart zichtbaar is op de pagina en de informatie klopt met wat je in het component hebt gezet.
Theorie JSX · Component maken
1.3 Zet de basisstructuur van je app op
Maak nu ook een Header en een Sidebar als aparte componentbestanden. Zorg
dat alle drie de componenten samen zichtbaar zijn op de pagina.
Wat moet je zien: een pagina met bovenaan een header met de naam van de app, een
sidebar met navigatie-items zoals Dashboard en Login, en de TaskCard
uit de vorige opdracht.
Stijl geef je layout een eerste vorm — header bovenaan, sidebar links of rechts, TaskCard met een duidelijke kaart-uitstraling. Netjes is genoeg, mooi hoeft nog niet.
- Nieuw:
src/components/Header.jsx - Nieuw:
src/components/Sidebar.jsx - Aanpassen:
src/App.jsx(importeer en plaatsHeader,SidebarenTaskCardsamen) - Bij gewone CSS:
src/App.css(basislayout voor header + sidebar) - Bij Tailwind: utility classes direct in de JSX (geen apart CSS-bestand nodig)
Klaar als je hebt minstens drie aparte componentbestanden en de pagina toont alle drie de onderdelen tegelijk met een herkenbare layout.
Theorie Denken in componenten · Component gebruiken · Styling in React
Niveau 2: Components & Props
2.1 Breid je componentenstructuur uit
Voeg twee nieuwe componenten toe aan je project: een FilterBar en een
TaskList. Gebruik ze allebei op je dashboardpagina.
Wat moet er in de componenten komen:
FilterBar: een rij met drie knoppen — Alles, Frontend en Backend. De knoppen hoeven nog niets te doen, ze moeten alleen zichtbaar zijn.TaskList: een container die één of meerdereTaskCard-componenten in zich heeft. Zet er voorlopig twee of drieTaskCard's in met vaste inhoud.
Wat moet je zien: onder je Header verschijnt de FilterBar
met drie knoppen, en daaronder de TaskList met meerdere TaskCard's erin.
- Nieuw:
src/components/FilterBar.jsx(drie knoppen, nog geen actie) - Nieuw:
src/components/TaskList.jsx(container met meerdereTaskCard's) - Aanpassen:
src/App.jsx(importeer en gebruik beide componenten)
Klaar als FilterBar en
TaskList staan elk
in een eigen bestand en worden geïmporteerd in je dashboard.
Theorie Component maken · Component gebruiken
2.2 Werk met props
Pas TaskCard aan zodat hij de taakgegevens ontvangt via props in plaats van dat de
gegevens hardcoded in het component staan. Gebruik meteen destructuring in de
parameters van de functie, zodat je velden zoals titel en status direct kunt
gebruiken zonder props.titel of props.status. Render daarna minstens drie
verschillende taken met hetzelfde component.
Wat moet je zien: drie taakkaarten met elk andere inhoud, allemaal gemaakt met
hetzelfde TaskCard component. Bijvoorbeeld:
- Kaart 1: React presentatie — Frontend — 15 juni — Nog niet klaar
- Kaart 2: Database ontwerp — Backend — 20 juni — Afgerond
- Kaart 3: UI prototype — Design — 22 juni — Nog niet klaar
Stijl geef TaskCard een
duidelijke opmaak
met padding, een rand of schaduw, en zorg dat de velden leesbaar gestructureerd zijn — bijvoorbeeld
de titel dikker en groter dan de rest.
- Aanpassen:
src/components/TaskCard.jsx(props ontvangen met destructuring, hardcoded waardes weghalen) - Aanpassen:
src/components/TaskList.jsx(drie keerTaskCardmet verschillende props)
Klaar als de gegevens van elke taak worden
doorgegeven via props,
het woord props. komt nergens voor in je TaskCard, en er staat niets meer
hardcoded in het component.
Theorie Props gebruiken · Meerdere props · Props destructuren
2.3 Gebruik children
Maak een herbruikbare Panel component met een titel en een ruimte voor willekeurige
inhoud via children. Gebruik dit component op minstens drie plekken met steeds andere
inhoud.
Wat moet je zien: drie panelen op de pagina, elk met een andere titel en andere
binneninhoud. Bijvoorbeeld een profielblok, een melding over deadlines en een tip van de dag —
allemaal gebouwd met hetzelfde Panel component.
- Nieuw:
src/components/Panel.jsx(titel-prop +children) - Aanpassen:
src/App.jsx(drie keerPanelmet andere inhoud erin)
Klaar als je hebt één Panel
component dat je minstens
drie keer gebruikt met verschillende inhoud erin.
Theorie Children
2.4 Bouw een eerste takenoverzicht
Maak een array met taakobjecten en render voor elk object een TaskCard. De gegevens geef
je door via props. Je hoeft in deze stap nog geen unieke key toe te voegen — een
console-waarschuwing over keys mag er nog zijn. In niveau 4 lossen we dat op.
Wat moet je zien: een lijst van minstens drie taakkaarten die automatisch gegenereerd worden vanuit de array. Je hebt de kaarten dus niet drie keer handmatig in JSX geschreven.
- Aanpassen:
src/components/TaskList.jsx(array met taakobjecten +.map()naarTaskCard) - Optioneel:
src/data/tasks.js(array eruit halen als losse datafile)
Klaar als als je een extra object aan je array toevoegt, verschijnt er automatisch een extra kaart op de pagina.
Niveau 3: Interactie in de Student Planner
3.1 Maak een status-toggle
Voeg bij elke taakkaart een knop toe waarmee je de status van de taak wisselt tussen afgerond en niet afgerond.
Wat moet je zien: als je op de knop klikt, verandert de tekst of stijl van de taak direct. Bijvoorbeeld van Nog niet klaar naar Afgerond en weer terug. Je hoeft de pagina niet te refreshen.
Tip voor nu mag elke TaskCard z'n
eigen lokale
status-state hebben. In niveau 4 tillen we dit omhoog naar de lijst, zodat je ook kunt filteren op
status.
- Aanpassen:
src/components/TaskCard.jsx(useStatevoor status + knop metonClick)
Klaar als elke taakkaart heeft een eigen knop die de status van die kaart wisselt zonder andere kaarten te beïnvloeden.
3.2 Toggle een detailpaneel
Voeg aan elke taakkaart een knop Toon details toe. Als je erop klikt, verschijnt extra informatie over die taak in de kaart zelf. Klik je nog een keer, dan verdwijnt de informatie weer.
Wat moet je zien: bij een klik klapt er binnen de kaart een klein stukje extra informatie open, zoals een korte omschrijving of een tip. Een tweede klik sluit het weer.
Let op dit is een simpele inline-toggle binnen de kaart — geen aparte detailpagina. In niveau 6 bouw je pas een echte detailpagina met een eigen URL en alle gegevens van de taak.
- Aanpassen:
src/components/TaskCard.jsx(extrauseStatevoortoonDetails+ conditional rendering van extra info)
Klaar als de extra informatie is standaard verborgen en wordt zichtbaar na een klik, zonder dat de pagina ververst.
Theorie Toggle met state · Conditional rendering
3.3 Kies een actieve filterknop
Maak drie knoppen: Alles, Te doen en Afgerond. De knop die je aanklikt moet er visueel anders uitzien dan de andere twee.
Wat moet je zien: de actieve knop heeft een andere kleur of stijl. Als je op een andere knop klikt, wisselt de actieve stijl mee.
Let op de takenlijst hoeft in deze stap nog niet echt gefilterd te worden. We oefenen hier alleen met state en conditionele styling — het échte filteren komt in niveau 4.
Stijl zorg dat het verschil tussen actieve en inactieve knoppen duidelijk zichtbaar is — een andere kleur, rand of dikkere tekst.
- Aanpassen:
src/components/FilterBar.jsx(useStatevooractieveFilter+ conditionele class op de knoppen) - Bij gewone CSS:
src/components/FilterBar.css(styling voor actieve vs. inactieve knop) - Bij Tailwind: ternary in
classNamedirect in de JSX
Klaar als er is altijd precies één knop actief en de styling wisselt correct mee bij elke klik.
Theorie Events · State updaten · Ternary
3.4 Live input preview
Maak een invoerveld waarin een gebruiker de naam van een nieuwe taak kan typen. Onder het veld verschijnt meteen een preview van wat er getypt wordt.
Wat moet je zien: terwijl je typt verschijnt er onder het veld bijvoorbeeld: Nieuwe taak: React opdracht afmaken. De preview past zich aan bij elke toetsaanslag.
- Nieuw:
src/components/TaskForm.jsx(input +useState+ live preview eronder) - Aanpassen:
src/App.jsx(importeer en plaatsTaskFormop het dashboard)
Klaar als de preview onder het invoerveld verandert live mee terwijl je typt, zonder dat je op een knop hoeft te klikken.
Theorie onChange · Input met state
3.5 Bouw een uitklapbaar zijpaneel
Maak een zijpaneel met extra informatie, zoals profielinfo, statistieken of een tip. Het paneel moet open en dicht kunnen via een knop.
Wat moet je zien: een knop waarmee het zijpaneel zichtbaar en onzichtbaar wordt. Het paneel is standaard gesloten.
- Aanpassen:
src/components/Sidebar.jsx(useStatevoor open/dicht + conditional rendering van de inhoud) - Of nieuw:
src/components/InfoPanel.jsx(eigen uitklappaneel naast de bestaande sidebar)
Klaar als het zijpaneel opent en sluit via één knop, zonder dat de pagina ververst.
Theorie Wat is state? · Klik-events · Conditional rendering
Niveau 4: Taken beheren
4.1 Render een lijst met keys
Maak een array met taakobjecten en render ze als een lijst of grid op de pagina. Elk item in de lijst
heeft een unieke id die je gebruikt als key.
Wat moet je zien: minstens vier taakkaarten die automatisch uit de array worden gegenereerd.
- Aanpassen:
src/components/TaskList.jsx(in.map()elk item een uniekekey={task.id}geven) - Aanpassen:
src/data/tasks.jsof waar je array staat (zorg dat elk object een uniekeidheeft)
Klaar als er staan geen waarschuwingen over ontbrekende keys in de console.
Theorie Lijsten renderen · Keys
4.2 Filter op categorie
Voeg filterknoppen toe boven je takenlijst, bijvoorbeeld Alles, Frontend en Backend. Als je op een knop klikt, zie je alleen de taken uit die categorie.
Wat moet je zien: klik je op Frontend, dan verdwijnen de backend-taken uit de lijst. Klik je op Alles, dan zijn alle taken weer zichtbaar.
- Aanpassen:
src/App.jsx(state vooractieveFilteroptillen naar hier, daarnafilter()op de takenarray) - Aanpassen:
src/components/FilterBar.jsx(ontvangtactieveFilter+setActieveFilterals props) - Aanpassen:
src/components/TaskList.jsx(ontvangt de gefilterde lijst als prop)
Klaar als elke filterknop toont alleen de bijbehorende taken en de actieve knop heeft een andere stijl.
Theorie Voorbeelden conditionals · State aanpassen · Arrays met objecten
4.3 Maak een controlled form
Bouw een formulier waarmee een student een nieuwe taak kan toevoegen. Na het invullen en versturen verschijnt de nieuwe taak meteen in de lijst.
Wat moet je zien: een formulier met minimaal een invoerveld voor de taaknaam en een knop Toevoegen. Na het klikken op de knop verschijnt de nieuwe taak onderaan de lijst en is het invoerveld weer leeg.
Let op de pagina mag niet refreshen bij het versturen van het formulier.
- Aanpassen:
src/components/TaskForm.jsx(controlled input +onSubmitmetpreventDefault) - Aanpassen:
src/App.jsx(functieaddTaskdie aanTaskFormwordt doorgegeven en de taak aan de state-array toevoegt)
Klaar als nieuwe taken verschijnen direct in de lijst na het versturen, zonder paginarefresh.
Theorie Basis form · Event syntax
4.4 Werk met meerdere formvelden in één object
Breid je taakformulier uit met extra velden: titel, vak, deadline en prioriteit. Sla alle velden op in één state-object in plaats van losse state-variabelen.
Wat moet je zien: een formulier met vier invulvelden. Na het versturen bevat de nieuwe taakkaart al deze gegevens.
- Aanpassen:
src/components/TaskForm.jsx(één state-object mettitel/vak/deadline/prioriteit,onChangemetname-attribuut) - Aanpassen:
src/components/TaskCard.jsx(de extra velden tonen)
Klaar als alle formuliervelden worden bijgehouden in één state-object en de nieuwe taakkaart toont alle ingevulde gegevens.
Theorie Form met object state
4.5 Voeg validatie toe
Zorg dat het formulier een foutmelding toont in drie situaties:
- Een verplicht veld (zoals de taaknaam) is leeg.
- De deadline is geen geldige datum.
- De deadline ligt in het verleden.
De taak mag pas worden toegevoegd als alle invoer correct is.
Wat moet je zien:
- Laat je het titelveld leeg en klik je op Toevoegen, dan verschijnt er een duidelijke foutmelding zoals Vul een taaknaam in.
- Vul je een datum in die in het verleden ligt, dan verschijnt er een melding zoals Deadline mag niet in het verleden liggen.
- Laat je het deadlineveld leeg of vul je iets ongeldigs in, dan verschijnt er een melding zoals Vul een geldige deadline in.
In alle drie de gevallen wordt de taak niet toegevoegd.
- Aanpassen:
src/components/TaskForm.jsx(state voorerrors, validatie inonSubmit, foutmeldingen onder de velden met{error && ...})
Klaar als elke ongeldige situatie geeft een eigen zichtbare foutmelding en blokkeert het toevoegen van de taak.
Theorie Validatie · Voorwaardelijk tonen met &&
4.6 Combineer alles in één takenmodule
Breng je takenlijst, filterknoppen, formulier en statustoggle samen op één scherm. Voeg ook een melding toe die verschijnt als er nog geen taken zijn.
TaskCard z'n eigen lokale status-state. Dat was prima om te oefenen, maar nu wil je ook
kunnen filteren op status — en dat kan alleen als alle taken in dezelfde array zitten in
App.jsx. Je tilt de status-state dus omhoog: weg uit TaskCard, naar
App.jsx. Dit heet lifting state up. TaskCard krijgt straks alleen
nog een functie via props die hij aanroept bij een klik. Dit is geen fout in 3.1 — het is een normale
stap als je app groeit.
Wat moet je zien: één werkend scherm waarop een student taken kan toevoegen, de lijst kan zien, kan filteren op categorie, en taken kan afvinken. Als de lijst leeg is staat er een melding zoals Nog geen taken toegevoegd.
Stijl zorg dat afgeronde taken visueel anders ogen dan open taken. Bijvoorbeeld een doorgestreepte titel, een groene rand, of een lichtere achtergrondkleur. Zo zie je in één oogopslag wat klaar is.
- Aanpassen:
src/App.jsx(alle state samenbrengen: takenarray,actieveFilter, statustoggle-handler) - Aanpassen:
src/components/TaskList.jsx(empty-state melding tonen alstasks.length === 0) - Aanpassen:
src/components/TaskCard.jsx(status komt nu van bovenaf, niet meer lokaal — knop roept een prop-functie aan)
Klaar als de drie interactieve functies (filteren, toevoegen, statustoggle) werken samen met de takenlijst op één scherm, zonder dat ze elkaar verstoren.
Theorie Lijsten met componenten · Form input · Conditional rendering
Niveau 5: Data & Bewaren
5.1 Bewaar taken in localStorage
Zorg dat de takenlijst bewaard blijft als de gebruiker de pagina refresht of de browser sluit.
Wat moet je zien: voeg een taak toe, refresh de browser, en de taak staat er nog steeds.
- Aanpassen:
src/App.jsx(inituseStatevanuitlocalStorage.getItem, enuseEffectdatlocalStorage.setItemdoet zodratasksverandert)
Klaar als taken verdwijnen niet meer na een paginarefresh.
Theorie localStorage in React · Dependencies
5.2 Fetch quotes van een API
Voeg een nieuw component QuotesSection toe aan je dashboard. In dit blok toon je
motiverende quotes voor studenten, opgehaald van de DummyJSON API. Het blok staat naast of onder je
eigen takenlijst.
API
https://dummyjson.com/quotes?limit=10
— het antwoord is een object met een quotes-array. Elke quote heeft een
id, quote (de tekst) en author.
Let op dit blok staat volledig los van je eigen takenlijst. De quotes worden puur opgehaald en getoond — je kunt ze niet bewerken, afvinken of koppelen aan taken. Het doel is dat je leert hoe je data ophaalt uit een API en toont.
Wat moet je zien: op het dashboard verschijnt een apart blok met minstens tien quotes, elk met de tekst en de auteur eronder. De data wordt opgehaald bij het laden van het dashboard.
Stijl geef het quotes-blok een eigen uitstraling zodat het duidelijk losstaat van je takenlijst — andere achtergrondkleur of rand, quote zelf prominent met de auteur kleiner eronder.
- Nieuw:
src/components/QuotesSection.jsx(useEffectmetfetchnaar DummyJSON,.map()over de quotes) - Aanpassen:
src/App.jsx(importeer en plaatsQuotesSectionop het dashboard)
Klaar als het quotes-blok staat op het dashboard, haalt bij het laden minstens tien quotes op, en toont ze met tekst en auteur.
Theorie Data fetchen · useEffect voorbeelden
5.3 Voeg loading en error states toe
Breid opdracht 5.2 uit met drie extra situaties in het quotes-blok: een laadmelding terwijl de data wordt opgehaald, een foutmelding als het ophalen mislukt, en een melding als er geen quotes zijn.
Wat moet je zien:
- Tijdens het laden: Laden...
- Bij een fout: een foutmelding
- Als er geen quotes zijn: Geen quotes gevonden
Tip voor het testen om een foutmelding te zien,
kun je tijdelijk
de URL in je fetch-aanroep kapot maken (bijvoorbeeld dummyjson.com/quotez). Vergeet niet
om hem daarna weer terug te zetten.
- Aanpassen:
src/components/QuotesSection.jsx(extra state voorloadingenerror, in JSX drie conditional branches: laden / fout / leeg / lijst)
Klaar als alle drie de situaties een eigen zichtbare melding tonen in het quotes-blok.
Theorie Basis loading/error · UX patterns
5.4 Bewaar voorkeuren van de gebruiker
Maak een voorkeur die bewaard blijft na het refreshen van de pagina. Kies er één: een dark mode toggle of een sorteervolgorde voor de takenlijst.
Wat moet je zien: zet dark mode aan, refresh de pagina, en de app staat nog steeds in dark mode. Of: kies een sortering, refresh, en de sortering is bewaard.
- Aanpassen:
src/App.jsx(state voor de voorkeur +useEffectdie naarlocalStorageschrijft, init vanuitlocalStorage.getItem) - Bij gewone CSS:
src/App.cssofsrc/index.css(alleen bij dark mode: voeg klassedarkop<body>of een wrapper en stijl daarop) - Bij Tailwind: voeg de class
darkconditioneel toe op een wrapper-element en gebruikdark:bg-…/dark:text-…classes in je JSX
5.5 Bouw een zoekcomponent
Maak een zoekveld waarmee een student door de takenlijst kan zoeken. De lijst past zich aan terwijl de gebruiker typt. Als er geen resultaten zijn, verschijnt er een melding.
Wat moet je zien: typ je react in het zoekveld, dan zie je alleen taken met dat woord in de naam. Typ je iets wat nergens in voorkomt, dan staat er Geen taken gevonden.
- Nieuw:
src/components/SearchBar.jsx(input metonChange) - Aanpassen:
src/App.jsx(state voorzoekterm, gecombineerde filter+search-logica op de takenarray) - Aanpassen:
src/components/TaskList.jsx(toon Geen taken gevonden als de gefilterde lijst leeg is)
Niveau 6: Routing & Login
6.1 Maak meerdere pagina's
Bouw je app uit naar meerdere pagina's: een dashboardpagina, een taakdetailpagina en een loginpagina. Voeg een navigatiebalk toe zodat je tussen de pagina's kunt wisselen.
Aanpak in 4 stappen — doe ze in deze volgorde:
- Installeer
react-router-domen wikkel<App />inmain.jsxin een<BrowserRouter>. - Maak drie nieuwe pages aan in
src/pages/:Dashboard.jsx,Login.jsx,TaskDetail.jsx. Verhuis de huidige inhoud vanApp.jsxnaarDashboard.jsx. - Zet in
App.jsxnu alleen nog een<Routes>blok met drie<Route>'s — elk gekoppeld aan een page. - Maak de navigatiebalk met
<NavLink>in plaats van gewone links, zodat de actieve link een extra styling krijgt.
Wat moet je zien: je kunt via klikken in de navigatiebalk wisselen tussen minstens drie pagina's, zonder dat de browser ververst.
Optionele uitbreiding: je kunt ook je QuotesSection uit niveau 5
verhuizen naar een eigen /quotes-pagina in plaats van dat het blok op het dashboard
staat. Dan heb je meteen een vierde pagina waartussen je kunt navigeren.
Stijl geef je navigatiebalk een herkenbare styling en laat duidelijk zien op welke pagina de gebruiker zich bevindt (bijvoorbeeld door de actieve link anders te stylen).
- Installeren:
npm install react-router-dom - Aanpassen:
src/main.jsx(omhul<App />met<BrowserRouter>) - Nieuw:
src/pages/Dashboard.jsx(inhoud van je huidige App.jsx hierheen) - Nieuw:
src/pages/Login.jsx - Nieuw:
src/pages/TaskDetail.jsx - Aanpassen:
src/App.jsx(alleen nog<Routes>+<Route>'s en de navigatiebalk) - Aanpassen:
src/components/Header.jsxofSidebar.jsx(gebruik<NavLink>voor actieve link styling)
6.2 Werk met URL parameters
Maak de takenlijst klikbaar. Als je op een taak klikt, ga je naar een detailpagina met de ID van die taak in de URL. Op de detailpagina zie je de volledige informatie van die taak.
Wat moet je zien: klik je op taak 3, dan ga je naar een URL zoals
/tasks/3.
Op die pagina staan de naam, het vak, de deadline en de omschrijving van die specifieke taak.
- Aanpassen:
src/App.jsx(route toevoegen:/tasks/:id→TaskDetail) - Aanpassen:
src/pages/TaskDetail.jsx(useParamsomidte lezen, taak opzoeken in de array) - Aanpassen:
src/components/TaskCard.jsx(<Link to={`/tasks/${id}`}>rond de kaart of titel)
6.3 Navigeer programmatisch
Maak een loginformulier met minimaal een veld voor gebruikersnaam en een veld voor wachtwoord. Na het versturen navigeert de app automatisch naar het dashboard, zonder dat de gebruiker op een link hoeft te klikken.
Wat moet je zien: vul het loginformulier in en klik op Inloggen. De app stuurt je automatisch naar de dashboardpagina.
Houd het simpel: je hoeft de ingevulde gebruikersnaam en het wachtwoord nog niet te
controleren — elke invoer mag meteen doorsturen naar het dashboard. Het doel van deze stap is dat je
een formulier via onSubmit kunt verbinden met useNavigate. In de volgende
opdracht maken we hier echte login-logica van met een auth context.
- Aanpassen:
src/pages/Login.jsx(controlled form met velden +useNavigate, inonSubmit→navigate('/dashboard'))
useNavigate.
6.4 Maak een simpele auth context
Bouw een context die bijhoudt of een gebruiker ingelogd is én wat de gebruikersnaam is. De
navigatiebalk
toont andere opties afhankelijk van de inlogstatus. Bewaar de inlogstatus en de gebruikersnaam ook in
localStorage, zodat de gebruiker na een refresh ingelogd blijft.
Pas opdracht 6.3 aan: bij het versturen van het loginformulier zet je de gebruikersnaam in de context (en dus ook in localStorage) voordat je doornavigeert.
Wat moet je zien:
- Niet ingelogd: de navigatiebalk toont alleen Login (eventueel plus een publieke pagina zoals Quotes, als je die hebt)
- Wel ingelogd: de navigatiebalk toont Dashboard en Uitloggen
- Refresh na login: je blijft ingelogd, de navigatiebalk wijzigt niet
Welke pagina's waar: het dashboard is alleen voor ingelogde gebruikers (dat maken we af in 6.5). Andere pagina's zoals een quotes-pagina mag je zelf beslissen: altijd zichtbaar of alleen na login.
- Nieuw:
src/context/AuthContext.jsx(createContext+AuthProvidermetuserstate,login/logoutfuncties, sync metlocalStorage) - Aanpassen:
src/main.jsx(omhul<App />met<AuthProvider>) - Aanpassen:
src/pages/Login.jsx(roeplogin(gebruikersnaam)aan vóórnavigate('/dashboard')) - Aanpassen:
src/components/Header.jsxofSidebar.jsx(useContextvooruser, conditional navigatie-items + uitlogknop)
6.5 Bescherm een route
Zorg dat de dashboardpagina alleen zichtbaar is voor ingelogde gebruikers. Niet-ingelogde gebruikers worden automatisch doorgestuurd naar de loginpagina.
Wat moet je zien: log uit, typ /dashboard handmatig in de adresbalk, en
je komt automatisch op de loginpagina terecht in plaats van het dashboard.
- Nieuw:
src/components/ProtectedRoute.jsx(checkuseruitAuthContext, anders<Navigate to="/login" />) - Aanpassen:
src/App.jsx(wikkel de dashboardroute in<ProtectedRoute>)
Niveau 7: Einduitbreidingen
7.1 Voeg statistieken toe
Toon boven of naast je takenlijst een aantal statistieken over de taken in de app.
Wat moet je zien: minstens drie statistiekblokken, bijvoorbeeld:
- 5 taken open
- 3 taken afgerond
- Frontend heeft de meeste deadlines
- Nieuw:
src/components/Stats.jsx(ontvangttasksals prop, rekent de waardes uit met.filter()en.length) - Aanpassen:
src/pages/Dashboard.jsx(importeer en plaatsStatsboven of naast je takenlijst)
7.2 Voeg sortering en extra filters toe
Geef de gebruiker de mogelijkheid om de takenlijst te sorteren en extra te filteren. Kies minimaal twee uitbreidingen.
Voorbeelden:
- Sorteren op deadline (vroegste eerst)
- Sorteren op prioriteit (hoog naar laag)
- Filteren op taken van deze week
- Filteren op vak
- Aanpassen:
src/components/FilterBar.jsx(extra dropdown of knoppen voor sortering/filter) - Aanpassen:
src/pages/Dashboard.jsx(extra state +.sort()/.filter()op de takenarray voor je deze aanTaskListgeeft)
7.3 Maak een docentweergave
Voeg een extra pagina of modus toe waarop een docent een overzicht ziet van alle taken en hun status. In deze weergave kan de docent niet bewerken — het is puur een leesoverzicht.
Wat moet je zien: een aparte pagina of knop Docentmodus die een overzicht toont van alle taken met per taak minimaal: de titel, het vak, de deadline, en de status (Afgerond of Te doen). Bovenaan staan ook samenvattende cijfers, bijvoorbeeld 8 taken totaal — 3 afgerond, 5 open.
Houd het simpel: een knop in de navigatiebalk of een extra route
(zoals /docent) is genoeg. Je hoeft geen aparte docent-login of gebruikersdatabase te
bouwen — deze weergave is beschikbaar voor elke ingelogde gebruiker.
- Nieuw:
src/pages/DocentView.jsx(lees alle taken, toon ze als lees-only lijst + samenvattende cijfers bovenaan) - Aanpassen:
src/App.jsx(extra route/docent) - Aanpassen:
src/components/Header.jsxofSidebar.jsx(extra navigatie-link Docentmodus)
7.4 Maak de styling af
Je hebt tijdens de vorige niveaus al stap voor stap aan styling gewerkt. In deze opdracht poets je de app op tot een geheel dat er samenhangend uitziet. Loop je app door vanaf de loginpagina tot en met de docentweergave en zorg dat alles er consistent uitziet.
Wat moet je zien:
- Eén herkenbaar kleurenpalet door de hele app (bijvoorbeeld twee à drie hoofdkleuren).
- Consistente afstanden, lettergroottes en knopstijlen tussen pagina's.
- De app werkt ook goed op een kleiner scherm (responsive).
- Foutmeldingen, status-indicatoren en actieve knoppen vallen duidelijk op.
Je werkt met wat je aan het begin hebt gekozen: gewone CSS of Tailwind. Voeg in deze stap geen nieuwe stylingmethode toe — polish wat je hebt.
- Aanpassen:
src/index.css(globale stijlen: kleurenpalet als CSS-variabelen, basis lettertype, knopstijl) - Aanpassen: alle bestaande
src/components/*.cssbestanden (consistente spacing en kleuren toepassen) - Of bij Tailwind: aanpassen
tailwind.config.js(eigen kleuren intheme.extend) - Aanpassen: globale CSS of Tailwind-classes voor responsive breakpoints (mobiel scherm)
7.5 Eindchallenge
Voeg zelf minstens drie extra features toe aan je Student Planner. Kies features die voor jou nuttig of interessant zijn.
Voorbeelden van extra features:
- Kleurcodes per vak
- Favorieten markeren
- Notificatie als een deadline nadert
- Kalenderweergave van deadlines
- Taken kunnen bewerken na aanmaken
Wat moet je kunnen laten zien: welke drie features je hebt toegevoegd, waarom je ze hebt gekozen en wat ze doen in de app.
- Afhankelijk van je keuze — per feature meestal: een nieuw component in
src/components/en aanpassingen insrc/pages/Dashboard.jsxof de relevante pagina - Voorbeelden:
- Kleurcodes per vak →
src/components/TaskCard.jsx(kleur op basis vanvak) - Favorieten →
src/components/TaskCard.jsx(ster-knop) +src/App.jsx(favoriet-state in localStorage) - Taken bewerken →
src/components/EditTaskForm.jsx(nieuw) +src/pages/TaskDetail.jsx
- Kleurcodes per vak →