Reflectie - NathanNeelis/meesterproef-2021 GitHub Wiki
Hieronder reflecteer ik per vak in de minor op mijn project. Ik beschrijf welke technieken ik toegepast heb in het Hipper project die ik geleerd per vak.
Tijdens WAFS heb ik geleerd hoe ik data uit een API kan fetchen door een promise te returnen.
Ik heb in project Hipper een util geschreven die de data ophaalt uit de API en deze als promise terug stuurt. De functie ziet er als volgt uit:
Code voorbeeld
const fetch = require('node-fetch');
async function getData(url) {
try {
const response = await fetch(url);
const data = await response.json();
return data;
} catch (error) {
console.log(`an error occurred: ${error}`)
throw error
}
}
module.exports = getData;
Ook heb ik geleerd hoe ik HTML elementen kan renderen op basis van acties van de gebruiker. Tijdens het vak WAFS deed ik dit om zo elke aparte pagina te renderen in mijn singe page application, maar in Project Hipper gebruik ik deze techniek om een formulier te renderen die vervolgens zijn data naar de database verzend.
Code voorbeeld
addActivityImg.forEach((result, index) => {
addActivityImg[index].addEventListener('click', () => {
let targetDate = dateOfDay[index].getAttribute('data-date');
renderForm(checkboxWrapper[index], targetDate);
})
})
function renderForm(form, date) {
// todays date
let dateDay = document.createElement('input')
dateDay.setAttribute('type', 'hidden');
dateDay.setAttribute('id', 'date_plan_activity');
dateDay.setAttribute('name', 'date_plan_activity');
dateDay.value = date;
// wandelen
let wandelen = document.createElement('input');
wandelen.setAttribute('type', 'checkbox');
wandelen.setAttribute('id', 'plan_wandelen');
wandelen.setAttribute('name', 'plan_wandelen')
let wandelenLabel = document.createElement('label');
wandelenLabel.setAttribute('for', 'plan_wandelen')
wandelenLabel.innerHTML = 'Wandelen'
let wandelenIMG = document.createElement('img');
wandelenIMG.src = 'images/walking.svg'
wandelenIMG.setAttribute('alt', 'icon walking');
// boodschappen
let boodschappen = document.createElement('input');
boodschappen.setAttribute('type', 'checkbox');
boodschappen.setAttribute('id', 'plan_boodschappen');
boodschappen.setAttribute('name', 'plan_boodschappen')
let boodschappenLabel = document.createElement('label');
boodschappenLabel.setAttribute('for', 'plan_boodschappen')
boodschappenLabel.innerHTML = 'Boodschappen'
let boodschappenIMG = document.createElement('img');
boodschappenIMG.src = 'images/walking.svg'
boodschappenIMG.setAttribute('alt', 'icon boodschappen');
// stofzuigen
let stofzuigen = document.createElement('input');
stofzuigen.setAttribute('type', 'checkbox');
stofzuigen.setAttribute('id', 'plan_stofzuigen');
stofzuigen.setAttribute('name', 'plan_stofzuigen')
let stofzuigenLabel = document.createElement('label');
stofzuigenLabel.setAttribute('for', 'plan_stofzuigen')
stofzuigenLabel.innerHTML = 'Stofzuigen'
let stofzuigenIMG = document.createElement('img');
stofzuigenIMG.src = 'images/walking.svg'
stofzuigenIMG.setAttribute('alt', 'icon stofzuigen');
// tuinieren
let tuinieren = document.createElement('input');
tuinieren.setAttribute('type', 'checkbox');
tuinieren.setAttribute('id', 'plan_tuinieren');
tuinieren.setAttribute('name', 'plan_tuinieren')
let tuinierenLabel = document.createElement('label');
tuinierenLabel.setAttribute('for', 'plan_tuinieren')
tuinierenLabel.innerHTML = 'Tuinieren'
let tuinierenIMG = document.createElement('img');
tuinierenIMG.src = 'images/walking.svg'
tuinierenIMG.setAttribute('alt', 'icon tuinieren');
// fietsen
let fietsen = document.createElement('input');
fietsen.setAttribute('type', 'checkbox');
fietsen.setAttribute('id', 'plan_fietsen');
fietsen.setAttribute('name', 'plan_fietsen')
let fietsenLabel = document.createElement('label');
fietsenLabel.setAttribute('for', 'plan_fietsen')
fietsenLabel.innerHTML = 'Fietsen'
let fietsenIMG = document.createElement('img');
fietsenIMG.src = 'images/walking.svg'
fietsenIMG.setAttribute('alt', 'icon fietsen');
// oefeningen
let oefeningen = document.createElement('input');
oefeningen.setAttribute('type', 'checkbox');
oefeningen.setAttribute('id', 'plan_oefeningen');
oefeningen.setAttribute('name', 'plan_oefeningen')
let oefeningenLabel = document.createElement('label');
oefeningenLabel.setAttribute('for', 'plan_oefeningen')
oefeningenLabel.innerHTML = 'Oefeningen'
let oefeningenIMG = document.createElement('img');
oefeningenIMG.src = 'images/walking.svg'
oefeningenIMG.setAttribute('alt', 'icon oefeningen');
// overige
let overige = document.createElement('input');
overige.setAttribute('type', 'checkbox');
overige.setAttribute('id', 'plan_overige');
overige.setAttribute('name', 'plan_overige')
let overigeLabel = document.createElement('label');
overigeLabel.setAttribute('for', 'plan_overige')
overigeLabel.innerHTML = 'Overige'
let overigeIMG = document.createElement('img');
overigeIMG.src = 'images/walking.svg'
overigeIMG.setAttribute('alt', 'icon overige');
form.appendChild(dateDay);
form.appendChild(wandelen);
form.appendChild(wandelenLabel).appendChild(wandelenIMG);
form.appendChild(boodschappen);
form.appendChild(boodschappenLabel).appendChild(boodschappenIMG);
form.appendChild(stofzuigen);
form.appendChild(stofzuigenLabel).appendChild(stofzuigenIMG);
form.appendChild(tuinieren);
form.appendChild(tuinierenLabel).appendChild(tuinierenIMG);
form.appendChild(fietsen);
form.appendChild(fietsenLabel).appendChild(fietsenIMG);
form.appendChild(oefeningen);
form.appendChild(oefeningenLabel).appendChild(oefeningenIMG);
form.appendChild(overige);
form.appendChild(overigeLabel).appendChild(overigeIMG);
}
Om mijn code inzichtelijk te maken voor andere heb ik een Actor diagram en Interaction diagram gemaakt. Het maken van deze diagrammen heb ik opgepikt tijdens dit vak.
Actor diagram
Interaction diagram
Tijdens mijn meesterproef heb ik toch veel van de technieken toegepast die ik tijdens WAFS geleerd heb.
In de meesterproef heb ik gebruik gemaakt van meerdere technieken waar ik tijdens dit vak mee in aanraking mee ben gekomen.
Zo gebruik ik width: min(xrem, xvw)
om bepaalde elementen repsonsive te maken zonder media queries. Ook maak ik tegenwoordig gulzig gebruik van custom properties.
Tijdens de meesterproef ben ik me ook gaan verdiepen in de conic gradients, deze gebruik ik om de data te visualiseren en is een vrij nieuwe techniek in de CSS. Na enkele documentatie gelezen te hebben kreeg ik mijn datavisualisatie voor elkaar en gebruik ik costum properties voor de percentage.
Om deze visualisatie te animeren moest ik gebruik maken van CSS.registerProperty(). Deze techniek is nog expirimenteel en werkt zeker niet in alle browsers op alle devices. Het belangrijkste van deze techniek is dat je een start value kan aangeven.
CSS.registerProperty({
name: '--pos',
syntax: '<length-percentage>',
initialValue: '0%',
inherits: true
});
In de CSS property hierboven zie je bijvoorbeeld dat de initial value 0% is. Deze value verander ik later in een animatie naar 100%. Zie hieronder.
@keyframes posDaily {
to {
--pos: var(--daily_percent);
}
}
Omdat deze techniek nog zo expirimenteel is en dus niet over goed werkt, moest ik gebruik maken van een @supports. Het heeft me echt wat tijd gekost om hier een goede @supports voor te vinden, maar in een bron vond ik dat ik er één die werkt, al weet ik nog steeds niet helemaal waar ik nu op check.
.dailygoal {
background: conic-gradient(var(--orange) var(--daily_percent), var(--lightGrey) 0);
}
.weeklygoal {
background: conic-gradient(var(--orange) var(--weekly_percent), var(--lightGrey) 0);
}
/* RESOURCE @Supports https://web.dev/at-property/ */
/* Check for Houdini support & register property */
@supports (background: paint(houdini)) {
.dailygoal,
.weeklygoal {
width: 10rem;
height: 10rem;
margin-bottom: 2rem;
background: conic-gradient(var(--c0) var(--pos, 0%), var(--c1) 0);
border-radius: 50%;
position: relative;
animation: 0s 1;
animation-duration: 2s, 1s;
animation-timing-function: steps(1), ease-in-out;
animation-fill-mode: forwards;
}
.dailygoal {
animation-name: c0, posDaily;
}
.weeklygoal {
animation-name: c0, posWeekly;
}
}
Een belangrijk aspect van mijn project is dat het gebruikersvriendelijk moet zijn, en mijn doelgroep zijn revalidanten met een gemiddelde leeftijd van 70 jaar. Ook weet ik dat er het meest gebruik wordt gemaakt van een tablet device. Om toegang te krijgen tot mijn project moeten ze elke keer de browser op starten, en ik heb geleerd dat hier nu ook een andere mogelijk voor is; namelijk een Progressive Web App. Hiervoor heb ik een service worker geinstalleerd en een manifest aangemaakt. Nu kunnen de gebruikers de applicatie op de meeste devices installeren zodat ze niet helemaal de browser hoeven op te starten.
Verder maak ik handig gebruik van de service worker en sla ik de bezochte pagina's op in een cache. Zo kan de gebruiker als hij zijn tablet meeneemt op zijn afspraak met de therapeut nog steeds toegang hebben tot zijn data. Dit is wel het laatst gesynchroniseert toen hij nog internet had.

Zoals ook bij CSS To The Rescue aangegeven, ik heb gebruik gemaakt van @Supports in de css om er voor te zorgen dat de datavisualisatie voor iedereen toegankelijk is. Voor de één is dit alleen met een animatie en voor de ander is dit zonder.
Hierbij kwam ook het testen op verschillende devices en browser bij kijken. Zo heb ik mijn Browserstack weer opgestart en ben ik deze feature gaan testen op IOS, Andriod, Chrome, Safari, Brave, Mobile, Tablet en Desktop. Hierdoor kwam ik er al snel achter dat de animatie niet overal werkte en hierdoor de conic gradient helemaal niet toonde. Door het toevoegen van de @supports werkt de visualisatie nu overal.
Het vak realtime web is niet heel erg aanbod gekomen in mijn meesterproef. Wel heb ik een betere en meer overwogen beslissing kunnen maken voor het gaan gebruiken van Mongoose/MongoDB in plaats van Firebase. Tijdens realtime web heb ik mij verdiept in Firebase authentication en database en op basis van deze kennis heb ik er voor gekozen om zelf gebruikers te gaan laten registreren en MongoDB te gaan gebruiken omdat ik hier zelf meer ervaring mee heb en ik niet opzoek was naar een oAuth login.
Wel heb ik nog wat extra aandacht besteed om mijn dataflow inzichtelijk te krijgen. Hiervoor heb ik een dataflow diagram gemaakt.
Dataflow diagram
In mijn project heb ik een doelgroep waar ik wel echt rekening mee kan en moet houden in de vormgeving. Zo heb ik mijn net zoals in HCD verdiept in mijn doelgroep en ben ik opzoek gegaan naar een oplossing die specifiek voor hun geschikt is. Een aantal design keuzes zoals grote knoppen en consistentie door mijn applicatie zijn een voorbeeld hiervan.
Daarbij kregen we ook de mogelijkheid om te spreken met eind gebruikers. Ik presenteerde mijn concept aan een revalidant die Hipper op dit moment gebruikt om te revalideren en een therapeut die ook met Hipper werkt. Hieruit kwam goede feedback waar ik weer een goede volgende stap mee kan maken. Het plan was eigenlijk om dit een echte usertest te laten zijn, helaas ging dit niet helemaal zoals bedacht omdat het online was.
Om tot een conclusie te komen denk ik dat ik heel veel heb gehad aan mijn ervaring in exclusive design voor Darice om nu overwogen beslissingen te maken voor mijn doelgroep. De volgende stap is testen met de doelgroep!