1. Components
Tijdens deze oefeningenreeks oefen je op
- Het aanmaken van een React project
- Het schrijven van componenten
- Het opdelen van een interface in componenten
- Het toevoegen van CSS
Voorbereiding: Nieuw project & basisstructuur
Maak een nieuw project aan en zorg ervoor dat de titel van de HTML-pagina "Frontend Frameworks | Les 1: Componenten | Oplossing" wordt.
Bouw een component Exercise. Deze component bevat een div die, vanuit JavaScript, volgende opmaak krijgt.
{
box-shadow: 7px 2px 8px 1px rgba(18,89,46,0.67);
background: #EEEEEE;
min-height: 7em;
padding: .5em;
margin: 1.5em .5em;
}Verder heeft de component minimaal: een property title en een property background. Als de background property niet undefined is, wordt deze waarde gebruikt om de achtergrondkleur in te stellen, in de plaats van de #EEEEEE die hierboven gedefinieerd is. De component Exercise heeft een andere component ExerciseTitle als kind. Deze laatste component heeft eveneens een property title. Geneste JSX-code binnen de Exercise component moeten getoond worden.
De component ExerciseTitle toont de inhoud van de title property en krijgt volgende opmaak via een CSS-stylesheet.
{
font-family: "Lucida Sans", Monaco, monospace;
font-size: 3rem;
letter-spacing: 3px;
color: #3A5D9B;
font-weight: 300;
font-style: oblique;
line-height: 1.2;
}Gebruik deze component om onderstaand resultaat te bouwen, merk op dat de tweede en vierde oefening een andere achtergrondkleur hebben, gebruik hiervoor de kleur #77EEEE.

Oefening 1: Multiplication Table
Bouw een nieuwe component ExerciseOne en doe dit in een nieuwe file. De component wordt vanuit dit bestand geëxporteerd en gerenderd als kind van de eerder aangemaakte Exercise component (die 'Exercise 1: Multiplication Table' als titel heeft).

De component ExerciseOne bestaat uit een component MultiplicationTable die één property heeft, table. MultiplicationTable is opgedeeld in twee andere componenten Header en Row. Header heeft ook de eigenschap table. Row heeft twee eigenschappen, factor1 en factor2.
De eigenschap table geeft aan welke maaltafel afgeprint moet worden, de eigenschappen factor1 en factor2 geven aan welke 2 getallen er vermenigvuldigt moeten worden. Om table om te zetten in een string kan je gebruik maken van onderstaand object.
const translate: Record<number, string> = {
1: 'One',
2: 'Two',
3: 'Three',
4: 'Four',
5: 'Five',
6: 'Six',
7: 'Seven',
8: 'Eight',
9: 'Nine',
}Gebruik een for loop om de rijen in de maaltafels af te printen. Voor de opmaak maak je gebruik maken van onderstaande CSS-code. Je plaatst deze in een .css bestand en zorgt dat dit in de volledige oefening gebruikt kan worden. Elke van onderstaande klassen is bedoeld om aan een div gekoppeld te worden.
/* Opmaak voor de component Header */
.header {
font-size: 50px;
color: #e65100;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
background-color: #ff9800;
}
/* Opmaak voor de component Row */
.row {
font-size: 20px;
color: #455a64;
}
/* Opmaak voor de component MultiplicationTable */
.table {
font-family: "Comic Sans MS", serif;
text-align: center;
width: 200px;
padding: 0;
border-radius: 20px;
background-color: #ffe0b2;
filter: drop-shadow(0px 0px 5px #666);
margin: 2em;
}
/* Opmaak voor de component ExerciseOne */
.exercise {
display: flex;
}Oefening 2: Rater
Voor deze oefening maken we gebruik van Lucide React, een grote icon library die beschikbaar is zowat alle JavaScript frameworks. Ga in de documentatie op zoek naar installatie-instructies.
Schrijf een nieuwe component ExerciseTwo en render deze op de gepaste plaatst.

De component ExerciseTwo toont 3 Rater componenten. Deze component bestaat op zijn beurt uit de componenten Star en Label.
De component Rater krijgt twee properties, rating en max, de verhouding van deze twee bepaald de score (rating/max) die als property wordt doorgegeven aan de component Label.
De component star heeft één property, full. Als deze booleaanse eigenschap waar is wordt een volle ster getoond anders een lege.
Zoek in het overzicht van de Lucide iconen naar een gepast icoon. Via de fill property kan je het icoon inkleuren.
De component Label bepaald het label van de rater aan de hand van een property score, je gebruikt hiervoor volgende tekst.
- Kleiner dan 0.1 ➝ Disaster
- Tot en met 0.3 ➝ Insufficient
- Tot en met 0.5 ➝ Sufficient
- Tot en met 0.6 ➝ Average
- Tot en met 0.8 ➝ Good
- Tot en met 0.9 ➝ Very good
- Hoger dan 0.9 ➝ Excellent
Voeg onderstaande CSS-code toe aan het .css bestand dat je in de vorige oefening gemaakt hebt. Gebruik daarnaast opnieuw de CSS-klasse exercise.
/* Opmaak voor Rater */
.rater {
text-align: center;
padding: 2em;
border-radius: 2px;
background-color: #E2E2E2;
filter: drop-shadow(0px 0px 5px #666);
margin: 2em;
width: fit-content;
}Oefening 3: Progressbar
Bekijk de HTML-code hieronder. Deze code bouwt een progressbar, de breedte van de bar wordt bepaald door de l180 op lijn 10. De waarde kan gaan van l0 = 0% tot l360 = 100%. Als de taak 25% voltooid is zal hier dus 0.25 * 360 = l90 staan.
<svg height="80" width="400">
<!--De volledig bar, 100%-->
<g fill="none" stroke="lightgrey" stroke-width="25">
<path stroke-linecap="round" d="M20 55 l360 0" />
</g>
<!--Het voltooide gedeelte, l180 breed, of 180/360 = 50%-->
<g fill="none" stroke="green" stroke-width="25">
<path stroke-linecap="round" d="M20 55 l180 0" />
</g>
<!--De tekstuele weergave van het voltooide percentage-->
<text x="180" y="25" fill="green">
45 %
</text>
</svg>Bouw een nieuwe component ExerciseThree, deze component maakt opnieuw gebruik van de CSS-klasse exercise. Daarbovenop wordt aan deze component volgende CSS gekoppeld, kies zelf hoe je dit doet.
{
flex-direction: column;
}De component ExerciseThree maakt drie keer gebruik van de ProgressBar component, die gebouwd wordt op basis van bovenstaande HTML-code. Deze component krijgt twee properties, percentage en color. De component is opgedeeld in twee andere componenten Label en Bar, die dezelfde properties krijgen.
Om onderstaand resultaat te bekomen, maak je gebruik van de kleuren #ce4b99, #ce1b29, en #125b69.

Oefening 4: Number grid
Bouw een component ExerciseFour, deze component roept 3 keer een component NumberGrid op, zodat onderstaand resultaat geproduceerd wordt.

Probeer zelf te bepalen welke properties NumberGrid nodig heeft.
Om dezelfde layout te krijgen als in het screenshot kan je het aangeboden CSS-bestand gebruiken. Dit bestand moet, in tegenstelling tot het vorige stylesheet, enkel beschikbaar zijn voor de code uit deze oefening.
Elke cell in bovenstaande kaders is een button die de klasse square krijgt. Elke rij is een div die de klasse grid-row krijgt. Tenslotte is ook het volledig kader omringd door een div en krijgt deze div de klasse grid.
Om het getal te bepalen kan je gebruik maken van de formule i * n + j + 1, waar i het rijnummer is, n het aantal rijen in totaal, en j het kolomnummer. Deze formule gaat ervan uit dat je begint te tellen bij 0.
Oefening 5: Comment Card
Tijdens deze oefening bouw je een component die gebruikt kan worden om één commentaar te plaatsen op een forum.

Maak een nieuwe component ExerciseFive en een nieuwe component CommentCard. Bekijk vervolgens onderstaande structuur (elke kader duid een component aan) en bouw deze na.

CSS
Bekijk onderstaande CSS-code en voeg deze toe aan je project, kies zelf hoe.
.card {
display: flex;
flex-direction: row;
background-color: #18191A;
color: white;
}
.card .avatar {
margin-right: 0.5em;
height: 5em;
margin-bottom: 0;
}
.card .author {
font-size: 110%;
color: #bdc4d0;
margin: 0;
}
.card .content {
margin: 0;
color: #6c757d;
}
.card .commentSection {
display: flex;
flex-direction: column;
}Dummy data
Voeg onderstaande variabelen toe aan het bestand waarin ExerciseFive gedefinieerd is, deze stellen 2 comments voor die gevisualiseerd worden met de CommentCard component. Roep binnen ExerciseFive 2 keer de CommentCard component op, geef telkens een commentaar mee als property en maak hiervoor gebruik van de spread operator. De twee CommentCard componenten zijn van elkaar gescheiden met een <hr/>. Zorg er natuurlijk ook voor dat je een gepaste interface IComment voorziet.
const comment1: IComment = {
id: 'ebba06aa-649c-40b8-ad38-d517f45fc843',
firstName: 'Evangeline',
lastName: 'Mcintyre',
avatar: 'https://avatar.iran.liara.run/public/girl',
content: 'Nisi ipsum anim reprehenderit ex id laboris sunt deserunt quis. Id velit aliqua commodo reprehenderit nostrud sit elit exercitation mollit proident amet et amet. Do reprehenderit tempor tempor excepteur fugiat irure anim deserunt elit incididunt ut cillum dolore.',
}
const comment2: IComment = {
id: 'e3c21e32-df68-4d77-b594-18a2d4ee18f9',
firstName: 'Dudley',
lastName: 'Gates',
avatar: 'https://avatar.iran.liara.run/public/boy',
content: 'Reprehenderit sunt enim dolore cillum. Proident Lorem commodo ea duis tempor ipsum dolore in magna aliquip reprehenderit esse. Consequat do fugiat veniam esse anim ullamco eu pariatur laboris ullamco velit excepteur ipsum. Ea consectetur quis anim fugiat fugiat veniam Lorem exercitation Lorem aliqua do.',
}