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.

Bestanden
  • 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.css en src/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
Bestanden
  • Nieuw: src/components/TaskCard.jsx (component met hardcoded inhoud)
  • Aanpassen: src/App.jsx (importeer TaskCard en 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.

Bestanden
  • Nieuw: src/components/Header.jsx
  • Nieuw: src/components/Sidebar.jsx
  • Aanpassen: src/App.jsx (importeer en plaats Header, Sidebar en TaskCard samen)
  • 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 meerdere TaskCard-componenten in zich heeft. Zet er voorlopig twee of drie TaskCard'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.

Bestanden
  • Nieuw: src/components/FilterBar.jsx (drie knoppen, nog geen actie)
  • Nieuw: src/components/TaskList.jsx (container met meerdere TaskCard'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.

Bestanden
  • Aanpassen: src/components/TaskCard.jsx (props ontvangen met destructuring, hardcoded waardes weghalen)
  • Aanpassen: src/components/TaskList.jsx (drie keer TaskCard met 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.

Bestanden
  • Nieuw: src/components/Panel.jsx (titel-prop + children)
  • Aanpassen: src/App.jsx (drie keer Panel met 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.

Bestanden
  • Aanpassen: src/components/TaskList.jsx (array met taakobjecten + .map() naar TaskCard)
  • 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.

Theorie map() · Props

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.

Bestanden
  • Aanpassen: src/components/TaskCard.jsx (useState voor status + knop met onClick)

Klaar als elke taakkaart heeft een eigen knop die de status van die kaart wisselt zonder andere kaarten te beïnvloeden.

Theorie useState · onClick

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.

Bestanden
  • Aanpassen: src/components/TaskCard.jsx (extra useState voor toonDetails + 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.

Bestanden
  • Aanpassen: src/components/FilterBar.jsx (useState voor actieveFilter + conditionele class op de knoppen)
  • Bij gewone CSS: src/components/FilterBar.css (styling voor actieve vs. inactieve knop)
  • Bij Tailwind: ternary in className direct 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.

Bestanden
  • Nieuw: src/components/TaskForm.jsx (input + useState + live preview eronder)
  • Aanpassen: src/App.jsx (importeer en plaats TaskForm op 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.

Bestanden
  • Aanpassen: src/components/Sidebar.jsx (useState voor 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.

Bestanden
  • Aanpassen: src/components/TaskList.jsx (in .map() elk item een unieke key={task.id} geven)
  • Aanpassen: src/data/tasks.js of waar je array staat (zorg dat elk object een unieke id heeft)

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.

Bestanden
  • Aanpassen: src/App.jsx (state voor actieveFilter optillen naar hier, daarna filter() op de takenarray)
  • Aanpassen: src/components/FilterBar.jsx (ontvangt actieveFilter + setActieveFilter als 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.

Bestanden
  • Aanpassen: src/components/TaskForm.jsx (controlled input + onSubmit met preventDefault)
  • Aanpassen: src/App.jsx (functie addTask die aan TaskForm wordt 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.

Bestanden
  • Aanpassen: src/components/TaskForm.jsx (één state-object met titel/vak/deadline/prioriteit, onChange met name-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.

Bestanden
  • Aanpassen: src/components/TaskForm.jsx (state voor errors, validatie in onSubmit, 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.

Let op in 3.1 had elke 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.

Bestanden
  • Aanpassen: src/App.jsx (alle state samenbrengen: takenarray, actieveFilter, statustoggle-handler)
  • Aanpassen: src/components/TaskList.jsx (empty-state melding tonen als tasks.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.

Bestanden
  • Aanpassen: src/App.jsx (init useState vanuit localStorage.getItem, en useEffect dat localStorage.setItem doet zodra tasks verandert)

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.

Bestanden
  • Nieuw: src/components/QuotesSection.jsx (useEffect met fetch naar DummyJSON, .map() over de quotes)
  • Aanpassen: src/App.jsx (importeer en plaats QuotesSection op 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.

Bestanden
  • Aanpassen: src/components/QuotesSection.jsx (extra state voor loading en error, 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.

Bestanden
  • Aanpassen: src/App.jsx (state voor de voorkeur + useEffect die naar localStorage schrijft, init vanuit localStorage.getItem)
  • Bij gewone CSS: src/App.css of src/index.css (alleen bij dark mode: voeg klasse dark op <body> of een wrapper en stijl daarop)
  • Bij Tailwind: voeg de class dark conditioneel toe op een wrapper-element en gebruik dark:bg-… / dark:text-… classes in je JSX
Klaar als de gekozen voorkeur blijft bewaard na een paginarefresh.

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.

Bestanden
  • Nieuw: src/components/SearchBar.jsx (input met onChange)
  • Aanpassen: src/App.jsx (state voor zoekterm, gecombineerde filter+search-logica op de takenarray)
  • Aanpassen: src/components/TaskList.jsx (toon Geen taken gevonden als de gefilterde lijst leeg is)
Klaar als de takenlijst filtert live mee tijdens het typen en toont een melding als er geen resultaten zijn.

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:

  1. Installeer react-router-dom en wikkel <App /> in main.jsx in een <BrowserRouter>.
  2. Maak drie nieuwe pages aan in src/pages/: Dashboard.jsx, Login.jsx, TaskDetail.jsx. Verhuis de huidige inhoud van App.jsx naar Dashboard.jsx.
  3. Zet in App.jsx nu alleen nog een <Routes> blok met drie <Route>'s — elk gekoppeld aan een page.
  4. 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).

Bestanden
  • 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.jsx of Sidebar.jsx (gebruik <NavLink> voor actieve link styling)
Klaar als alle drie de pagina's bereikbaar zijn via de navigatiebalk en de URL verandert mee bij elke pagina.

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.

Bestanden
  • Aanpassen: src/App.jsx (route toevoegen: /tasks/:idTaskDetail)
  • Aanpassen: src/pages/TaskDetail.jsx (useParams om id te lezen, taak opzoeken in de array)
  • Aanpassen: src/components/TaskCard.jsx (<Link to={`/tasks/${id}`}> rond de kaart of titel)
Klaar als elke taak heeft een eigen detailpagina met de juiste gegevens en een werkende URL.

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.

Bestanden
  • Aanpassen: src/pages/Login.jsx (controlled form met velden + useNavigate, in onSubmitnavigate('/dashboard'))
Klaar als na het versturen van het loginformulier navigeert de app automatisch naar het dashboard via 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.

Bestanden
  • Nieuw: src/context/AuthContext.jsx (createContext + AuthProvider met user state, login/logout functies, sync met localStorage)
  • Aanpassen: src/main.jsx (omhul <App /> met <AuthProvider>)
  • Aanpassen: src/pages/Login.jsx (roep login(gebruikersnaam) aan vóór navigate('/dashboard'))
  • Aanpassen: src/components/Header.jsx of Sidebar.jsx (useContext voor user, conditional navigatie-items + uitlogknop)
Klaar als de navigatiebalk past automatisch aan als de inlogstatus verandert, en een refresh gooit je niet uit.

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.

Bestanden
  • Nieuw: src/components/ProtectedRoute.jsx (check user uit AuthContext, anders <Navigate to="/login" />)
  • Aanpassen: src/App.jsx (wikkel de dashboardroute in <ProtectedRoute>)
Klaar als het dashboard is onbereikbaar voor niet-ingelogde gebruikers, ook als ze de URL direct intypen.

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
Bestanden
  • Nieuw: src/components/Stats.jsx (ontvangt tasks als prop, rekent de waardes uit met .filter() en .length)
  • Aanpassen: src/pages/Dashboard.jsx (importeer en plaats Stats boven of naast je takenlijst)
Klaar als de statistieken automatisch updaten als je een taak toevoegt of afvinkt.

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
Bestanden
  • 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 aan TaskList geeft)
Klaar als minstens twee van de bovenstaande opties werken en de lijst past zich direct aan bij een wijziging.

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.

Bestanden
  • 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.jsx of Sidebar.jsx (extra navigatie-link Docentmodus)
Klaar als de docentweergave is bereikbaar, toont alle taken met hun status, en laat samenvattende cijfers zien die automatisch meeveranderen.

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.

Bestanden
  • Aanpassen: src/index.css (globale stijlen: kleurenpalet als CSS-variabelen, basis lettertype, knopstijl)
  • Aanpassen: alle bestaande src/components/*.css bestanden (consistente spacing en kleuren toepassen)
  • Of bij Tailwind: aanpassen tailwind.config.js (eigen kleuren in theme.extend)
  • Aanpassen: globale CSS of Tailwind-classes voor responsive breakpoints (mobiel scherm)
Klaar als de app oogt als één geheel: zelfde kleuren, lettertypes en stijl van knoppen op alle pagina's, en de layout schaalt netjes mee op een smaller 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.

Bestanden
  • Afhankelijk van je keuze — per feature meestal: een nieuw component in src/components/ en aanpassingen in src/pages/Dashboard.jsx of de relevante pagina
  • Voorbeelden:
    • Kleurcodes per vak → src/components/TaskCard.jsx (kleur op basis van vak)
    • 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
Klaar als minstens drie zelfgekozen features werken aantoonbaar in de app.