Meny:
Prosjektbeskrivelse: En venn av deg har kommet på en idè til en app, der folk kan registrere fjelltopper de går på gjennom året. Vennen har derimot ikke peiling på hva som kreves for å kunne lagre denne informasjonen, og ber deg om å hjelpe til med planlegging av “backend”. I første omgang skal du altså lage en datamodell, og forklare den.
Etter et møte med vennen din, sitter du igjen med en liste med krav:
Kommentarer:
Lag datamodellen, og forhold deg til normaliseringsreglene.
NB: Kommentarene er ikke grundige nok til å forklare alle deler av modellen, men er eksempel på hvordan du kan tenke når du skal gjøre dette.
NB2: Her kan man bare gå et fjell per tur, og det kan ikke gå flere personer på samme tur. Dette er for å gjøre det enklere å lage datamodellen, og senere databasen, men det er ikke nødvendigvis slik det må være i en virkelig applikasjon. Det er helt greit å utvide datamodellen, og gjøre den mer kompleks, hvis du ønsker det. Det viktigste er at du forstår hvordan de forskjellige delene henger sammen, og at du kan forklare det.
NB3: fjelltur.db inneholder også en bilde-tabell med noen testrader (bilder knyttet til en fjelltur), men de faktiske bildefilene disse radene peker på er ikke lagt ved i prosjektet. Dette er fordi vi ikke bruker denne tabellen i webapplikasjonen ennå - se “Videre arbeid” for et forslag om å bygge ut løsningen med dette.
Bruk SQLite3, eller andre verktøy du er komfortabel med, for å lage databasen basert på datamodellen du har laget.
Legg også inn testdata, slik at du har noe å jobbe med når du skal lage spørringer og senere en webapplikasjon.
Lettvint løsning:
Øv deg på å “spørre” databasen, og hente ut den informasjonen du er interessert i.
Her kan du finne oppgaver og løsningsforslag for SQL-spørringer mot denne databasen: SQL - oppgaver og løsningsforslag
Vi skal nå lage en enkel webapplikasjon som kan hente data fra SQLite-databasen, og vise det i en nettleser. Vi skal bruke Node.js og Express for å lage en enkel server, og better-sqlite3 for å håndtere SQLite-databasen.
Sluttproduktet kan se slik ut:

Her følger en steg-for-steg guide for hvordan du kan lage dette.
Lag deg først en ny mappe for prosjektet, og flytt database-filen inn i denne.
Deretter initialiser du et nytt Node-prosjekt i denne mappen. Åpne terminalen, naviger til mappen, og kjør følgende kommando:
npm init -y
Kontroller at package.json har blitt opprettet, og at det inneholder en “main” som peker på app.js (eller hva du har valgt å kalle hovedfilen din).
Merk deg at du skal lagre all koden for webapplikasjonen din i denne mappen, og det er her du skal installere nødvendige avhengigheter. Følg med på instruksjonene, da du etter hvert må opprette nye mapper og filer for å kunne lage en fungerende applikasjon.
Dersom du får problemer med å kjøre npm init, eller andre kommandoer, så kan det være lurt å sjekke at du har Node.js og npm installert på maskinen din. Du kan sjekke dette ved å kjøre node -v og npm -v i terminalen. Hvis du ikke har disse installert, kan du laste ned og installere Node.js fra nodejs.org.
Et annet problem som mange får er hvilke rettigheter du har til å kjøre script. Du kan tillate dette ved å skrive følgende kommando i terminalen (dersom du bruker PowerShell på Windows):
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Dette vil tillate deg å kjøre script som er laget på din egen maskin, men ikke script som er lastet ned fra internett, uten at du har godkjent det først.
Fortsatt fra terminalen; kjør følgende kommando for å installere Express, better-sqlite3 og CORS:
npm install express better-sqlite3 cors
Kontroller at package.json har blitt oppdatert med de nye avhengighetene, og at det har blitt opprettet en node_modules-mappe med disse pakkene.
Tenk etter hva du har gjort. Hva er Express? Hva er better-sqlite3? Hva er CORS?
Det er vanlig praksis å ikke laste opp node_modules-mappen til GitHub, da denne kan være veldig stor, og den uansett inneholder filer som kan gjenopprettes ved å kjøre npm install basert på package.json. For å unngå at node_modules blir lastet opp, kan du opprette en .gitignore-fil i rotmappen av prosjektet ditt, og legge til følgende linje i denne filen:
node_modules/
Dette vil fortelle Git at den skal ignorere node_modules-mappen, og ikke laste den opp til GitHub. Kontroller at .gitignore-filen er opprettet, og at den inneholder denne linjen.
Vi lager en enkel Express-server som kan håndtere forespørsler og hente data fra SQLite-databasen.
Startkode:
// Server-bit, setter opp en Express-app
const express = require('express');
const app = express();
const PORT = 3000;
// Databasen
const Database = require('better-sqlite3');
const db = new Database('fjelltur.db');
// CORS-middleware for å tillate forespørsler fra andre domener
const cors = require('cors');
app.use(cors());
// Eksempel på en rute som henter alle fjell, beskrivelse, høydene og bilde deres
app.get('/api/fjell', (req, res) => {
const rows = db.prepare('SELECT fjellnavn, hoyde, beskrivelse, foto FROM fjell').all();
res.json(rows);
});
// Åpner en viss port på serveren, og starter serveren
app.listen(PORT, () => {
console.log(`Server kjører på http://localhost:${PORT}`);
});
Du starter serveren ved å kjøre node app.js i terminalen.
Kontroller at serveren starter uten feil, at du kan nå http://localhost:3000/api/fjell i nettleseren, og se dataene fra databasen. Hvilket format får du dataene i? Hvordan kan du bruke dette i en frontend-applikasjon senere?
Vi skal nå bruke fetch for å hente data fra API-et ditt, og vise det i en enkel frontend-applikasjon.
Vi må utvide app.js for å servere statiske filer, slik at vi kan ha en HTML-fil og tilhørende JavaScript og CSS. Legg til den følgende linjen i app.js:
// Middleware for å servere statiske filer fra "public" mappen
app.use(express.static('public'));
Opprett en mappe som heter public, og lag tre filer her:
index.htmlindex.jsindex.cssKoble disse filene sammen.
I index.html kan du lage en enkel struktur for å vise dataene, og inkludere index.js og index.css. For eksempel:
<!DOCTYPE html>
<html lang="nb">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fjell</title>
<script src="index.js" defer></script>
<link rel="stylesheet" href="index.css">
</head>
<body>
<!-- Fylles ut av JS -->
</body>
</html>
I index.js kan du bruke fetch for å hente data fra API-et ditt, og vise det i nettleseren. NB: Koden nedenfor skriver bare ut dataene i konsollen, du må selv lage HTML-elementer og legge dataene inn i disse for å vise det på siden.
async function fetchData() {
const response = await fetch('/api/fjell');
const data = await response.json();
console.log(data);
// Her kan du gjøre noe med dataen (vise det frem)
}
fetchData();
Høyde: ${fjell.hoyde} meter
Beskrivelse: ${fjell.beskrivelse}
Du kan se all koden for dette i public-mappen, og du kan også se hvordan jeg har gjort det i CSS for å style det litt.
Nå skal vi lage en dropdown-meny som lar oss velge en person, og når vi har valgt en person, så skal vi hente ut alle fjellturene til den personen, og vise det i nettleseren.
Her deler vi problemet opp i flere deler:
Legg til følgende rute i app.js:
// Eksempel på en rute som henter alle brukernavnene til alle personene i databasen
app.get('/api/personer', (req, res) => {
const rows = db.prepare('SELECT brukernavn FROM person').all();
res.json(rows);
});
Merk at vi her bare henter ut brukernavn-kolonnen, og ikke andre kolonner som for eksempel fornavn eller etternavn. Dette er fordi vi i dette eksempelet bare trenger brukernavnene for å kunne hente ut fjellturene til en person senere. Dersom du ønsker å vise fornavn og etternavn i dropdown-menyen, så kan du endre SQL-spørringen til å hente ut disse kolonnene også, og returnere det som JSON.
Deretter lager vi klar HTML-koden i en fil vi kaller eks-fjellturer-for-person.html, som inneholder en dropdown-meny for å velge person, og en container for å vise fjellturene til den valgte personen. Denne filen legger du i public-mappen.:
<html lang="nb">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Fjellturer for person</title>
<script src="eks-fjellturer-for-person.js" defer></script>
<link rel="stylesheet" href="eks-fjellturer-for-person.css">
</head>
<body>
<!-- Venstre panel: personvalg -->
<div id="sidebar">
<h2>Velg person</h2>
<select id="personDropdown" title="Personvalg">
<option value="">Velg en person</option>
</select>
</div>
<!-- Høyre panel: fjellturer for valgt person, fylles ut av JS -->
<div id="fjellturerContainer"></div>
</body>
</html>
Det siste steget i denne delen er å fylle ut dropdown-menyen med brukernavnene til alle personene i databasen. Dette gjør vi i den tilkoblede filen eks-fjellturer-for-person.js:
// Fyller ut en dropdown (select) med brukernavnene på alle personene i databasen
async function hentPersoner() {
const response = await fetch('/api/personer');
const personer = await response.json();
const dropdown = document.getElementById('personDropdown');
for (const person of personer) {
const option = document.createElement('option');
option.value = person.brukernavn;
option.textContent = person.brukernavn;
dropdown.appendChild(option);
}
}
document.addEventListener('DOMContentLoaded', hentPersoner);
Kontroller at dropdown-menyen fylles ut med brukernavnene til alle personene i databasen når du åpner eks-fjellturer-for-person.html i nettleseren.
Nå når dropdown-menyen er fylt ut, så skal vi lage en rute i Express som kan hente ut alle fjellturene til en gitt person, basert på brukernavn. Dette gjør vi ved å bruke URL-parametere i Express.
Legg til følgende rute i app.js:
app.get('/api/fjellturer/:brukernavn', (req, res) => {
const brukernavn = req.params.brukernavn;
const rows = db.prepare(`
SELECT fjell.fjellnavn
FROM person
JOIN fjelltur ON person.brukernavn = fjelltur.brukernavn
JOIN fjell ON fjelltur.fjell_id = fjell.fjell_id
WHERE person.brukernavn = ?
`).all(brukernavn);
res.json(rows);
});
Ruten over tar inn et brukernavn som en URL-parameter, og bruker dette for å hente ut alle fjellene som denne personen har gått på. Merk at vi ikke trenger å sjekke om brukernavn mangler her: Express kaller aldri denne ruten uten at :brukernavn-delen av URL-en er fylt ut, så en slik sjekk ville aldri slått til.
Det du nettopp gjorde oppleves kanskje litt vanskelig, men tenk på alternativet, der du måtte lage en ny rute for hver person du vil hente ut fjellturene til, og hardkode navnet på personen i SQL-spørringen. Det ville vært en særs tungvint løsning, og det er derfor vi bruker URL-parametere (som :brukernavn i ruten) for å gjøre det mer fleksibelt.
// Eksempel om å hente alle fjellene som en gitt person har gått
// Et alternativ som er en veldig dårlig løsning, fordi vi hardkoder navnet på personen i SQL-spørringen,
// og da må vi lage en ny rute for hver person vi vil hente ut fjellene til
app.get('/api/fjellturer_hausnes', (req, res) => {
const rows = db.prepare(`
SELECT fjell.fjellnavn
FROM person
JOIN fjelltur ON person.brukernavn = fjelltur.brukernavn
JOIN fjell ON fjelltur.fjell_id = fjell.fjell_id
WHERE person.brukernavn = 'hausnes'`).all();
res.json(rows);
});
Når ruten er på plass i app.js, så kan du teste den ved å åpne http://localhost:3000/api/fjellturer/hausnes i nettleseren, og se at du får ut alle fjellene som personen med brukernavn “hausnes” har gått på. Sjekk deretter et annet brukernavn for å se at det fungerer for flere personer (for eksempel http://localhost:3000/api/fjellturer/harry).
For å faktisk bruke denne ruten i frontend-applikasjonen, så må du lage en event listener på dropdown-menyen, som henter ut den valgte personen, og deretter gjør et API-kall for å hente ut fjellturene til denne personen, og viser det i nettleseren.
HTML-siden har du allerede laget, og den inneholder en dropdown-meny med id personDropdown, og en container med id fjellturerContainer der vi skal vise fjellturene til den valgte personen.
I filen eks-fjellturer-for-person.js skal du nå legge til følgende:
// Når en person er valgt, henter og viser alle fjellturene til den personen
document.getElementById('personDropdown').addEventListener('change', async function() {
const brukernavn = this.value;
console.log(`Valgt person: ${brukernavn}`);
if (brukernavn) {
const response = await fetch(`/api/fjellturer/${encodeURIComponent(brukernavn)}`);
if (!response.ok) throw new Error(`HTTP ${response.status}`);
const fjellturer = await response.json();
// Sjekker at vi har fått data tilbake, og viser det i konsollen
console.log(fjellturer); // Her kan du erstatte dette med kode for å vise fjellturene i UI
// Skriver turene til HTML
// Først viser vi en overskrift med hvilken person vi viser turene for
const turerDiv = document.getElementById('fjellturerContainer');
turerDiv.innerHTML = `<h2>Fjellturer for ${brukernavn}</h2>`;
// Så viser vi en liste med alle fjellturene
const ul = document.createElement('ul');
for (const tur of fjellturer) {
const li = document.createElement('li');
li.textContent = tur.fjellnavn;
ul.appendChild(li);
}
turerDiv.appendChild(ul);
}
});
Som du kan se i koden over, så har vi laget en event listener på dropdown-menyen, som lytter etter endringer (når en person blir valgt). Når en person blir valgt, så henter vi ut brukernavnet til den valgte personen, og gjør et API-kall til ruten vi laget tidligere for å hente ut fjellturene til denne personen. Når vi får dataene tilbake, så viser vi det i konsollen, og deretter skriver vi det ut i HTML ved å lage en overskrift med navnet på personen, og en liste med alle fjellturene.
Du kan se CSS-filen eks-fjellturer-for-person.css her for et eksempel på hvordan du kan style dette, og gjøre det mer visuelt tiltalende.
Nå har du en fungerende frontend-applikasjon som kan hente ut og vise data fra databasen, men det er ikke så gøy hvis du ikke kan legge til nye data også. I denne delen skal vi lage en form i frontend-applikasjonen, der brukeren kan legge inn informasjon om en ny fjelltur, og deretter sende dette til serveren via et POST-kall. På serveren må du lage en rute som håndterer dette POST-kallet, og legger den nye fjellturen inn i databasen.
Se hvilke felt du trenger å fylle ut, enten basert på datammodellen eller ved å se på databasen. Lag deretter en form i HTML som inneholder input-felt for alle disse feltene. For eksempel kan du lage dropdown-menyer for å velge person og fjell, og vanlige input-felt for å legge inn tidspunkt, tid brukt, og beskrivelse.
Prøv selv!
Løsningsforslag (eks-registrere-ny-tur.html):
<form id="ny-tur-form">
<h1>Registrer ny fjelltur</h1>
<!-- Dropdown for å velge brukernavn: -->
<label for="brukernavn-dropdown">Brukernavn:</label>
<select id="brukernavn-dropdown" name="brukernavn-dropdown" required>
<!-- Fylles ut av JS -->
</select>
<!-- Dropdown for å velge fjell: -->
<label for="fjell-dropdown">Fjell:</label>
<select id="fjell-dropdown" name="fjell-dropdown" required>
<!-- Fylles ut av JS -->
</select>
<!-- Tidspunkt for turen: -->
<label for="tidspunkt">Tidspunkt for turen:</label>
<input type="date" id="tidspunkt" name="tidspunkt" required>
<!-- Varighet for turen (i minutter): -->
<label for="varighet">Varighet (minutter):</label>
<input type="number" id="varighet" name="varighet" required>
<!-- Beskrivelse av turen -->
<label for="beskrivelse">Beskrivelse:</label>
<textarea id="beskrivelse" name="beskrivelse" required></textarea>
<button type="submit">Registrer tur</button>
<!-- Lenke til oversikt over registrerte turer -->
<a href="eks-fjellturer-for-person.html" class="nav-lenke">Se hvilke fjell en person har gått</a>
</form>
For at brukeren skal kunne velge en person og et fjell når de skal registrere en ny fjelltur, så må vi fylle ut dropdown-menyer for disse feltene med data fra databasen. Dette gjør vi ved å lage to ruter i Express som henter ut alle personer og alle fjell, og deretter bruke disse rutene i frontend for å fylle ut. Dette gjorde du tidligere i oppgaven, så forsøk gjerne selv først.
NB: Vi forenkler selvsagt en hel del siden vi i denne løsningen kan legge inn fjellturer for andre enn oss selv (vi kan velge andre brukere enn oss selv). Se egen guide for hvordan du kan implementere autentisering og autorisasjon senere, for å gjøre det mer realistisk dersom du ønsker det.
I Express, bruk ruten du laget tidligere i app.js for å hente ut alle personer:
// Eksempel på en rute som henter alle brukernavnene til alle personene i databasen
app.get('/api/personer', (req, res) => {
const rows = db.prepare('SELECT brukernavn FROM person').all();
res.json(rows);
});
I filen eks-registrere-ny-tur.js legger du til følgende kode for å hente ut alle personer og fylle ut dropdown-menyen for brukernavn:
// Kode for å fylle ut en dropdown med alle brukernavn
async function hentPersoner() {
const response = await fetch('/api/personer');
const personer = await response.json();
console.log(personer); // Sjekker at vi har fått data tilbake
const dropdown = document.getElementById('brukernavn-dropdown');
dropdown.innerHTML = '';
for (const person of personer) {
const option = document.createElement('option');
option.value = person.brukernavn;
option.textContent = person.brukernavn;
dropdown.appendChild(option);
}
}
hentPersoner();
På samme måte som vi fylte ut dropdown-menyen for personer, så kan vi fylle ut dropdown-menyen for fjell ved å lage en rute i Express som henter ut alle fjell, og deretter bruke denne ruten i frontend for å fylle ut dropdown-menyen for fjell.
I Express, legg til følgende rute i app.js for å hente ut alle fjell:
// Eksempel på en rute som henter alle fjellnavnene som finnes i databasen
app.get('/api/fjell/navn', (req, res) => {
const rows = db.prepare('SELECT fjellnavn FROM fjell').all();
res.json(rows);
});
I filen eks-registrere-ny-tur.js legger du til følgende kode for å hente ut alle fjell og fylle ut dropdown-menyen for fjell:
// Kode for å hente alle fjellene som er registrert i databasen og fylle ut en dropdown med disse
async function hentFjellnavn() {
const response = await fetch('/api/fjell/navn');
const fjell = await response.json();
console.log(fjell); // Sjekker at vi har fått data tilbake
const dropdown = document.getElementById('fjell-dropdown');
dropdown.innerHTML = '';
for (const f of fjell) {
const option = document.createElement('option');
option.value = f.fjellnavn;
option.textContent = f.fjellnavn;
dropdown.appendChild(option);
}
}
hentFjellnavn();
Kontroller at begge dropdown-menyene fylles ut med data fra databasen når du åpner eks-registrere-ny-tur.html i nettleseren.
Nå som vi har en form for å registrere en ny fjelltur, og dropdown-menyer som er fylt ut med data fra databasen, så skal vi lage en event listener på formen som håndterer form-submission, henter ut dataene som brukeren har skrevet inn, og sender dette til serveren via et POST-kall.
I filen eks-registrere-ny-tur.js legger du til følgende kode for å håndtere form-submission:
// Kode for å sende data om en ny fjelltur til serveren
document.getElementById('ny-tur-form').addEventListener('submit', async function(event) {
event.preventDefault(); // Forhindrer at siden refresher når formen sendes inn
// Henter ut data fra form-feltene
const brukernavn = document.getElementById('brukernavn-dropdown').value;
const fjellnavn = document.getElementById('fjell-dropdown').value;
const tidspunkt = document.getElementById('tidspunkt').value;
const varighet = document.getElementById('varighet').value;
const beskrivelse = document.getElementById('beskrivelse').value;
// Kontroller at vi har fått data fra form-feltene
console.log({ brukernavn, fjellnavn, tidspunkt, varighet, beskrivelse }); // Sjekker at vi har riktig data før vi sender det til serveren
// Vi legger til mer kode her snart!
});
Kontroller at skjemaet fungerer som det skal, og at du får ut dataene i konsollen når du trykker på “Registrer tur”-knappen.
Merk at du snart skal legge til mer kode i denne event listeneren for å sende dataene til serveren, men før den tid må du lage en rute i Express som kan håndtere et POST-kall for å legge til en ny fjelltur i databasen. Se neste punkt for hvordan du kan gjøre dette.
Vi skal nå lage en rute i Express som kan håndtere et POST-kall for å legge til en ny fjelltur i databasen. Dette innebærer at vi må kunne lese data fra forespørselen, og deretter bruke disse dataene for å sette inn en ny rad i fjelltur-tabellen i databasen.
Løsningsforslag, legg til rute iapp.js:
// Rute som lar oss registrere en ny fjelltur for en person
app.post('/api/fjellturer', express.json(), (req, res) => {
// Henter ut data fra request body (det som klienten har sendt inn)
const { brukernavn, fjellnavn, tidspunkt, varighet, beskrivelse } = req.body;
// Sjekk om personen eksisterer
const person = db.prepare('SELECT * FROM person WHERE brukernavn = ?').get(brukernavn);
if (!person) return res.status(404).json({ error: 'Person ikke funnet' });
// Sjekk om fjellet eksisterer
const fjell = db.prepare('SELECT * FROM fjell WHERE fjellnavn = ?').get(fjellnavn);
if (!fjell) return res.status(404).json({ error: 'Fjell ikke funnet' });
// Registrer den nye fjellturen
db.prepare('INSERT INTO fjelltur (brukernavn, fjell_id, tidspunkt, varighet, beskrivelse) VALUES (?, ?, ?, ?, ?)').run(brukernavn, fjell.fjell_id, tidspunkt, Number(varighet), beskrivelse);
res.status(201).json({ message: 'Fjellturen er registrert!' });
});
Vi skal altså få data fra frontend (brukernavn, fjellnavn, tidspunkt, varighet og beskrivelse), sjekke at både personen og fjellet eksisterer i databasen, og deretter sette inn en ny rad i fjelltur-tabellen med denne informasjonen. Merk at vi bruker Number(varighet) for å konvertere varigheten fra tekst (slik den kommer fra form-feltet) til et tall, slik at den lagres riktig i databasen.
Nå må vi utvide koden i event listeneren for form-submission i eks-registrere-ny-tur.js for å sende dataene til denne ruten via et POST-kall. Dette gjør vi ved å bruke fetch med method: 'POST', og sende dataene i request body som JSON. Logikken bak dette er lik i alle tilfeller der du sender data, så det er bare å tilpasse i fremtidige situasjoner.
// Kode for å sende data om en ny fjelltur til serveren
document.getElementById('ny-tur-form').addEventListener('submit', async function(event) {
event.preventDefault(); // Forhindrer at siden refresher når formen sendes inn
// Henter ut data fra form-feltene
const brukernavn = document.getElementById('brukernavn-dropdown').value;
const fjellnavn = document.getElementById('fjell-dropdown').value;
const tidspunkt = document.getElementById('tidspunkt').value;
const varighet = document.getElementById('varighet').value;
const beskrivelse = document.getElementById('beskrivelse').value;
// Kontroller at vi har fått data fra form-feltene
console.log({ brukernavn, fjellnavn, tidspunkt, varighet, beskrivelse }); // Sjekker at vi har riktig data før vi sender det til serveren
// Sender dataen til serveren via et POST-kall
const response = await fetch('/api/fjellturer', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ brukernavn, fjellnavn, tidspunkt, varighet, beskrivelse })
});
// Sjekker om responsen fra serveren var vellykket, og gir tilbakemelding til brukeren
if (response.ok) {
alert('Fjellturen er registrert!');
} else {
alert('Det skjedde en feil ved registrering av fjellturen.');
}
});
Kontroller at du nå kan registrere en ny fjelltur ved å fylle ut skjemaet og trykke på “Registrer tur”-knappen, og at du får en bekreftelse på at turen er registrert. Du kan også sjekke i databasen at den nye fjellturen har blitt lagt til i fjelltur-tabellen.
Lag flere ruter som henter ut forskjellige typer data, der du kan få inspirasjon fra SQL-oppgavene du har løst tidligere.
Databasen har allerede en bilde-tabell for å knytte ett eller flere bilder til en registrert fjelltur (se NB3 tidligere i guiden), men denne brukes ikke i webapplikasjonen ennå. Bygg videre på løsningen slik at en bruker kan laste opp bilder til en fjelltur, og vise disse frem igjen.
Jobb videre med å få “ting” til å se bedre ut. Det er mange måter å gjøre dette på, og det er helt opp til deg hvordan du vil style det. Bruk gjerne bilder og ikoner for å gjøre det mer interessant.
Se løsningsforslag for hvordan jeg har gjort det her, men merk at det ikke er et gjennomgående tema i stilsettingen så langt. Det er mer ment som et eksempel på hvordan du kan style det, og ikke en ferdig løsning. Det viktigste er at du har det gøy med å lage dette, og at du lærer noe underveis.