Mörkt tema
Inlämningsuppgift 1
Information
Se detaljerna kring inlämningsuppgiften här: betyggskala, deadlines, examinerade moment, osv.
Introduktion
Den här veckan ska vi fokusera på själva beställningsformuläret och specialreglerna.
Tips! Fortsätt att skriva pseudokod för de olika uppgifterna. Det tränar även dig i att tänka logik och flöde.
Veckans uppgift(er)
Formulär för kunduppgifter
Har du inte fått nog av formulär?! Inte jag heller 😉 Nu ska vi dessutom validera att fälten fyllts i korrekt, och visa felmeddelanden om man inte har gjort det.
För det ska vi dels använda RegEx, men också "conditional classes" (CSS).
Skapa först formuläret i HTML (vi kan inte direkt automatisera någonting här, så finns ingen anledning att göra det med JS).
Glöm inte tillgänglighet.
Fält för:
- Förnamn
- Efternamn
- Adress (gata)
- Postnummer
- Postort
- Ev. portkod
- Telefon (mobil)
- E-postadress
- Val för betalsätt: kort eller faktura
- Om faktura valts som betalsätt ska ett formulärfält för svenskt personnummer visas. Även detta fält ska valideras innan formuläret går att skicka iväg, dvs. att man fyllt i korrekt personnummer.
- Om kort väljs som betalsätt, visas fält för kortnummer, datum/år och CVC. Dessa behöver inte valideras!
- Checkbox för godkännande av behandling av personuppgifter
- Checkbox för beställning av nyhetsbrev (ska vara iklickad som default)
- Samtliga formulärfält ska valideras och formuläret/beställningen ska inte gå att skicka om det finns några fel
- Felen ska markeras och kommuniceras tydligt (t.ex. ej enbart med röd färg, tag i beaktande a11y)
- När formuläret är korrekt ifyllt ska Skicka-/Beställ-knappen aktiveras, innan det är den utgråad
- Det ska finnas en "Rensa beställning"-knapp som återställer samtliga formulärfält liksom eventuella beställda munkar/produkter (alltså antalet återställs till 0)
- Det ska finnas ett fält för att mata in en rabattkod.
Specialregler
Nu ska vi jobba med lite if-satser, datum och matte (frukta ej!), och en timer.
Här är kravlistan på specialregler:
- På måndagar innan kl. 10 ges 10 % rabatt på hela beställningssumman. Detta visas i varukorgssammanställningen som en rad med texten "Måndagsrabatt: 10 % på hela beställningen".
- På fredagar efter kl. 15 och fram till natten mellan söndag och måndag kl. 03.00 tillkommer ett helgpåslag på 15 % på alla munkar. Detta ska inte framgå för kunden att munkarna är dyrare, utan priset ska bara vara högre i "utskriften" av munkarna.
- Om kunden har beställt för totalt mer än 800 kr ska det inte gå att välja faktura som betalsätt.
- Om kunden har beställt minst 10 munkar av samma sort, ska munkpriset för just denna munksort rabatteras med 10 %
- Om kunden beställer totalt mer än 15 munkar så blir frakten gratis. I annat fall är fraktsumman 25 kr plus 10% av totalbeloppet i varukorgen.
- Om kunden inte har lagt beställningen inom 15 minuter så ska beställningsformuläret tömmas/rensas och kunden ska meddelas att denne är för långsam.
Gå igenom "Vanliga misstag"
Kolla igenom din kod för vanliga misstag för HTML, CSS (från tidigare kurs) och för JS.
Tips och koncept
Specialregler
Specialreglerna är, i princip, if-satser i mer eller mindre avancerad tappning. Exempel:
På måndagar innan kl. 10 ges 10 % rabatt på hela beställningssumman. Detta visas i varukorgssammanställningen som en rad med texten "Måndagsrabatt: 10 % på hela beställningen".
Om munkarna/produkterna är sparade i en objekt-array såhär:
js
const products = [
{
name: 'Product 1',
price: 10,
amount: 0,
},
{
name: 'Product 2',
price: 15,
amount: 4,
},
{
name: 'Product 3',
price: 20,
amount: 3,
},
];
console.table(products);1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Pseudokod:
- Summera alla munkar från objekt-arrayen som man har beställt av
- Om det är måndag och klockan är mindre än 10, gångra med 0,9 för att applicera 10 % rabatt.
- Skriv ut texten i varukorgen
Praktiskt exempel som är krångligt att läsa (se nästa block):
js
// Loopa igenom produkt-arrayen, och för varje produkt
const totalOrderSum = products.reduce((currentValue, product) => {
// Kolla om vi beställt minst 1 ex av den produkten
if (product.amount > 0) {
// Gångra produktens pris med antal beställda, och addera till föregående summa
return (product.price * product.amount) + currentValue;
}
// Om vi inte beställt några ex av denna produkt, returnera föregående summa
return currentValue;
}, 0); // 0 = initial beställningssumma
console.log(totalOrderSum); // 1201
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Vi kan också göra samma som ovan med en vanlig for-loop, som är mer läsbar & lättförstådd:
js
let totalOrderSum = 0;
for (let i = 0; i < products.length; i++) {
if (products[i].amount > 0) {
totalOrderSum += products[i].amount * products[i].price;
}
}
console.log(totalOrderSum);1
2
3
4
5
6
7
2
3
4
5
6
7
Och sedan applicerar vi måndagsrabatten:
js
const today = new Date();
if (today.getDay() === 1 && today.getHours() < 10) { // söndag = 0, måndag = 1
console.log('Det är måndag morgon, så du får 10 % rabatt på din beställning:', totalOrderSum * 0.1, 'kr. Totalsumman blir:', totalOrderSum * 0.9, 'kr.');
}1
2
3
4
2
3
4
Kodupprepning & refaktorering
Det är helt okej att upprepa samma kod (i denna kurs, men inte sen i fortsättningskursen), men ibland kan det bli tröttsamt att skriva och/eller copy-paste:a samma kod.
Det är inte alltid lätt att se hur man ska strukturera om koden för att förenkla den, men jämför följande block:
js
function validateAdress() {
let adress = document.getElementById("adress").value;
if (adress.length === 0) {
adressError.innerHTML = "*";
return false;
}
adressError.innerHTML = '<i class="fa-solid fa-check"></i>';
return true;
}
function validateZip() {
let zipCode = document.getElementById("zip").value;
if (zipCode.length === 0) {
zipError.innerHTML = "*";
return false;
}
zipError.innerHTML = '<i class="fa-solid fa-check"></i>';
return true;
}
function validateCity() {
let city = document.getElementById("city").value;
if (city.length === 0) {
cityError.innerHTML = "*";
return false;
}
cityError.innerHTML = '<i class="fa-solid fa-check"></i>';
return true;
}
function validatePhone() {
let phone = document.getElementById("phone").value;
if (phone.length === 0) {
phoneError.innerHTML = "*";
return false;
}
if (!phone.match(/^[0-9]{10}$/)) {
phoneError.innerHTML = "Endast siffror";
return false;
}
phoneError.innerHTML = '<i class="fa-solid fa-check"></i>';
return true;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
Vi gör i princip samma sak om och om igen, bortsett från med telefonnumret som kräver en extra check.
Ett sätt att "dra ihop" koden på, skulle kunna vara detta:
JavaScript
js
function validateInput(inputElementId, checkSpecial) {
// Generalisera _vilket_ input-id som hämtas från HTML-dokumentet
const inputField = document.getElementById(inputElementId);
// Använd nextSibling eller previousSibling för att identifiera HTML-elementet
// som ligger före/efter input:en och används för felmeddelanden
// Detta stället krav på HTML-strukturen, se HTML-exempel nedan
const feedbackField = inputField.previousElementSibling;
// Om vi har special-fall, som t.ex. telefonnummer
let hasSpecialError = false;
let customErrorMessage = '';
// Om vi behöver kontrollera specialfall
if (checkSpecial !== '') {
// Kolla vilket specialfall
switch(checkSpecial) {
case 'phoneNumber':
hasSpecialError = !inputField.match(/^[0-9]{10}$/);
customErrorMessage = 'Endast siffror.';
break;
case 'socialSecurityNumber':
// Do something else
break;
}
}
// Skriv ut ev. felmeddelande eller check-mark
if (inputField.value.length === 0 || hasSpecialError) {
feedbackField.innerHTML = `* Fel: ${customErrorMessage}`;
return false;
} else {
feedbackField.innerHTML = '✔';
return true;
}
}
validateInput('address'); // Skicka in vilket ID som ska kollas
validateInput('zip');
validateInput('city');
validateInput('phone', 'phoneNumber'); // Id + specialfall1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
HTML:
html
<label>
<span>Adress</span>
<div class="error-message"></div> <!-- previousSibling till id="address" -->
<input type="text" id="address">
<div class="just-an-example"></div> <!-- nextSibling till id="address" -->
</label>1
2
3
4
5
6
2
3
4
5
6