get-frontend/webshop_app/mvc-emne2/README-NO.md
2025-07-01 20:42:02 +02:00

481 lines
No EOL
15 KiB
Markdown

# MVC Nettbutikk Applikasjon
En ren JavaScript-implementering av en nettbutikk som bruker Model-View-Controller (MVC) arkitekturmønsteret. Dette utdanningsprosjektet demonstrerer kjerne webutviklingskonsepter uten eksterne rammeverk.
## 🏗️ Arkitekturoversikt
Denne applikasjonen følger MVC-mønsteret med et sentralisert view-renderingssystem:
- **Model**: Håndterer databehandling og forretningslogikk
- **View**: Administrerer HTML-generering og DOM-manipulering
- **Controller**: Koordinerer brukerinteraksjoner og dataflyt
## 📊 UML Diagrammer
### Klassediagram
```mermaid
classDiagram
class Model {
-products: Array~Product~
-cart: Array~CartItem~
+getAllProducts() Array~Product~
+getProductById(id) Product
+addToCart(productId, quantity) boolean
+removeFromCart(productId) void
+updateCartQuantity(productId, quantity) void
+getCart() Array~CartItem~
+getCartTotal() number
+getCartItemCount() number
+clearCart() void
+saveCartToStorage() void
+loadCartFromStorage() Array~CartItem~
+initializeCart() void
}
class View {
-currentPage: string
-cartCount: number
+updateView(viewType, data) void
+generateNavbar() string
+generateProductsPage(products) string
+generateProductDetailPage(product) string
+generateCartPage(cartItems, total, itemCount) string
+createProductCard(product) string
+createCartItem(item) string
+attachEventListeners() void
+updateCartCountInNav() void
+showNotification(message) void
}
class Controller {
+loadProducts() void
+showProductDetail(productId) void
+handleAddToCart(productId) void
+handleRemoveFromCart(productId) void
+changeQuantity(productId, change) void
+handleClearCart() void
+navigateToProducts() void
+navigateToCart() void
+updateCartDisplay() void
}
class Product {
+id: number
+name: string
+price: number
+description: string
+image: string
+category: string
}
class CartItem {
+productId: number
+quantity: number
+product: Product
}
class App {
+initialize() void
}
Controller --> Model : bruker
Controller --> View : oppdaterer
View --> Controller : sender hendelser
Model --> Product : inneholder
Model --> CartItem : administrerer
CartItem --> Product : refererer til
App --> Controller : initialiserer
App --> Model : setter opp
App --> View : starter
```
### Sekvensdiagram - Legg til i handlekurv
```mermaid
sequenceDiagram
participant U as Bruker
participant V as View
participant C as Controller
participant M as Model
U->>V: Klikker "Legg i handlekurv"
V->>C: handleAddToCart(productId)
C->>M: addToCart(productId)
M->>M: getProductById(productId)
M->>M: Finn eksisterende element eller lag nytt
M->>M: saveCartToStorage()
M-->>C: return true/false
alt Vellykket
C->>M: getProductById(productId)
M-->>C: return product
C->>V: updateView('notification', {message})
C->>C: updateCartDisplay()
C->>M: getCart()
M-->>C: return cart
C->>M: getCartTotal()
M-->>C: return total
C->>M: getCartItemCount()
M-->>C: return itemCount
C->>V: updateView('cart', {cartItems, total, itemCount})
C->>V: updateView('cart-count', {count})
V->>V: generateCartPage() eller updateCartCountInNav()
V-->>U: Oppdatert UI med notifikasjon
else Feilet
C->>V: updateView('notification', {message: 'Feil'})
V-->>U: Feilmelding
end
```
## 📁 Prosjektstruktur
```
mvc-emne2/
├── index.html # Hoved HTML-fil med enkelt app-container
├── styles.css # Applikasjonsstyling
├── js/
│ ├── app.js # Applikasjonsinitialisering
│ ├── model.js # Datalag og forretningslogikk
│ ├── view.js # UI-rendering og HTML-generering
│ └── controller.js # Brukerinteraksjonshåndtering
├── flow-diagram.md # Applikasjonsflytvisualisering
├── README.md # Engelsk dokumentasjon
├── README-NO.md # Norsk dokumentasjon (denne filen)
└── ACCESSIBILITY.md # Tilgjengelighetsdokumentasjon
```
## 🔧 Nøkkelkomponenter
### 1. Model (`model.js`)
**Formål**: Administrerer applikasjonsdata og persistering
**Nøkkelfunksjoner**:
- `getAllProducts()` - Returnerer produktkatalog
- `getProductById(id)` - Henter spesifikt produkt
- `addToCart(productId, quantity)` - Legger til varer i handlekurv
- `removeFromCart(productId)` - Fjerner varer fra handlekurv
- `updateCartQuantity(productId, quantity)` - Oppdaterer vareantall
- `getCart()` - Returnerer gjeldende handlekurvinnhold
- `getCartTotal()` - Beregner total handlekurvpris
- `getCartItemCount()` - Returnerer totalt antall varer
- `clearCart()` - Tømmer handlekurven
- `saveCartToStorage()` / `loadCartFromStorage()` - LocalStorage-persistering
**Datastruktur**:
```javascript
// Produkt
{
id: number,
name: string,
price: number,
description: string,
image: string (emoji),
category: string
}
// Handlekurvvare
{
productId: number,
quantity: number,
product: Product
}
```
### 2. View (`view.js`)
**Formål**: Håndterer all UI-rendering gjennom en sentralisert `updateView`-funksjon
**Kjernearkitektur**:
```javascript
function updateView(viewType, data = {}) {
switch (viewType) {
case 'products': // Rendrer produktliste
case 'product-detail': // Rendrer enkelt produkt
case 'cart': // Rendrer handlekurv
case 'cart-count': // Oppdater handlekurvmerke
case 'notification': // Vis brukermeldinger
}
}
```
**Nøkkelfunksjoner**:
- **Enkelt inngangspunkt**: All rendering går gjennom `updateView()`
- **Komplett sidegenerering**: Genererer hele side-HTML inkludert navigasjon
- **Event Listener-administrasjon**: Fester automatisk event listeners etter hver rendering
- **Mallfunksjoner**: Modulære HTML-genereringsfunksjoner
**HTML-genereringsfunksjoner**:
- `generateNavbar()` - Lager navigasjonsheader
- `generateProductsPage(products)` - Produktlisteside
- `generateProductDetailPage(product)` - Produktdetaljside
- `generateCartPage(cartItems, total, itemCount)` - Handlekurvside
- `createProductCard(product)` - Individuelt produktkort
- `createCartItem(item)` - Individuell handlekurvvare
### 3. Controller (`controller.js`)
**Formål**: Håndterer brukerinteraksjoner og koordinerer mellom Model og View
**Navigasjonsfunksjoner**:
- `navigateToProducts()` - Viser produktliste
- `navigateToCart()` - Viser handlekurv
- `showProductDetail(productId)` - Viser produktdetaljer
**Handlekurvadministrasjon**:
- `handleAddToCart(productId)` - Legger til produkt i handlekurv
- `handleRemoveFromCart(productId)` - Fjerner produkt fra handlekurv
- `changeQuantity(productId, change)` - Oppdaterer produktantall
- `handleClearCart()` - Tømmer hele handlekurven
- `updateCartDisplay()` - Oppdaterer handlekurvvisning og teller
**Nøkkeldesignmønstre**:
- Alle funksjoner kaller `updateView()` for UI-oppdateringer
- Brukernotifikasjoner håndteres konsistent
- Handlekurvtilstand persisteres automatisk etter endringer
### 4. Applikasjonsinitialisering (`app.js`)
**Formål**: Bootstrapper applikasjonen
**Initialiseringsflyt**:
1. Vent på at DOM skal laste
2. Initialiser handlekurv fra localStorage
3. Last produkter fra model
4. Renderer initial produktside
5. Oppdater handlekurvteller
```javascript
document.addEventListener('DOMContentLoaded', function() {
// Fjern lastingstilstand
const loadingElement = document.querySelector('.loading');
if (loadingElement) {
loadingElement.remove();
}
initializeCart();
const products = getAllProducts();
const itemCount = getCartItemCount();
updateView('products', { products });
updateView('cart-count', { count: itemCount });
console.log('Nettbutikk MVC Demo initialisert!');
});
```
## 🔄 Dataflyt
### 1. Applikasjonsoppstart
```
HTML-lasting → DOMContentLoaded → initializeCart() → loadCartFromStorage() →
getAllProducts() → updateView('products') → generateProductsPage() → attachEventListeners()
```
### 2. Brukerinteraksjoner
```
Brukerklikk → Controller-funksjon → Model-operasjon → updateView() →
HTML-generering → Event Listener-tilkobling → UI-oppdatering
```
### 3. Handlekurvoperasjoner
```
Legg til i handlekurv → addToCart() → saveCartToStorage() → updateCartDisplay() →
updateView('cart') + updateView('cart-count') → showNotification()
```
## 🎨 View-renderingssystem
### Sentralisert rendering
Alle UI-oppdateringer flyter gjennom den enkelte `updateView()`-funksjonen:
```javascript
updateView('products', { products: [...] });
updateView('product-detail', { product: {...} });
updateView('cart', { cartItems: [...], total: 0, itemCount: 0 });
updateView('cart-count', { count: 0 });
updateView('notification', { message: 'Vellykket!' });
```
### Komplett sidegenerering
I motsetning til tradisjonell DOM-manipulering genererer dette systemet komplett side-HTML:
```javascript
function generateProductsPage(products) {
return `
${generateNavbar()}
<main>
<section class="page active">
<h2>Våre Produkter</h2>
<div class="products-grid">
${products.map(product => createProductCard(product)).join('')}
</div>
</section>
</main>
`;
}
```
### Event Listener-administrasjon
Etter hver rendering festes event listeners på nytt:
```javascript
function attachEventListeners() {
const productsLink = document.querySelector('[data-page="products"]');
const cartLink = document.querySelector('[data-page="cart"]');
if (productsLink) {
productsLink.addEventListener('click', function(e) {
e.preventDefault();
navigateToProducts();
});
}
// ... flere listeners
}
```
## 💾 Datapersistering
### LocalStorage-integrasjon
Handlekurvdata persisteres automatisk:
```javascript
function saveCartToStorage() {
try {
localStorage.setItem('webstore_cart', JSON.stringify(cart));
} catch (error) {
console.error('Feil ved lagring av handlekurv til localStorage:', error);
}
}
function loadCartFromStorage() {
try {
const savedCart = localStorage.getItem('webstore_cart');
if (savedCart) {
const parsedCart = JSON.parse(savedCart);
return parsedCart.map(item => ({
...item,
product: products.find(p => p.id === item.productId) ||
{ id: item.productId, name: 'Ukjent Produkt', price: 0 }
}));
}
} catch (error) {
console.error('Feil ved lasting av handlekurv fra localStorage:', error);
}
return [];
}
```
## 🚀 Bruk
### Kjøring av applikasjonen
1. Åpne `index.html` i en nettleser
2. Applikasjonen initialiseres automatisk
3. Naviger mellom produkter, produktdetaljer og handlekurv
4. Handlekurvtilstand persisteres på tvers av nettlesersesjoner
### Nøkkelfunksjoner
- **Produktbrowsing**: Vis alle produkter i rutenettlayout
- **Produktdetaljer**: Klikk på hvilket som helst produkt for detaljert visning
- **Handlekurv**: Legg til, fjern og modifiser antall
- **Persistent handlekurv**: Handlekurvinnhold lagret i localStorage
- **Responsiv design**: Fungerer på desktop og mobil
- **Brukernotifikasjoner**: Tilbakemelding for alle brukerhandlinger
## ♿ Tilgjengelighet og semantisk HTML
Applikasjonen er bygget med tilgjengelighet i fokus:
### Semantiske HTML-elementer
- **`<main>`**, **`<header>`**, **`<footer>`**, **`<nav>`**, **`<section>`**, **`<article>`**
- Riktig heading-hierarki (`<h1>`, `<h2>`, `<h3>`)
- Beskrivende ARIA-attributter
### ARIA-funksjoner
- **`role`**-attributter for klargjøring av elementfunksjoner
- **`aria-label`** for beskrivende etiketter
- **`aria-live`** for dynamiske innholdsoppdateringer
- **`aria-describedby`** for tilleggsinformasjon
### Tastaturnavigasjon
- Alle interaktive elementer er tilgjengelige via tastatur
- Fokusindikatorer for alle interaktive elementer
- Logisk tab-rekkefølge
## 🎯 Utdanningsmessige fordeler
### MVC-mønsterdemonstrasjon
- Tydelig separasjon av ansvar
- Model håndterer data, View håndterer presentasjon, Controller håndterer logikk
- Demonstrerer hvordan komponenter samhandler i MVC-arkitektur
### Moderne JavaScript-funksjoner
- ES6+-syntaks (arrow-funksjoner, template literals, destructuring)
- LocalStorage API-bruk
- Event handling-mønstre
- Funksjonelle programmeringskonsepter
### Webutviklingsfundamentaler
- DOM-manipuleringsteknikker
- Event listener-administrasjon
- Klientsidehåndtering av tilstand
- HTML-generering og templating
- CSS-stylingintegrasjon
## 🔧 Tekniske beslutninger
### Hvorfor sentralisert rendering?
- **Konsistens**: Alle UI-oppdateringer følger samme mønster
- **Vedlikeholdbarhet**: Lett å spore og debugge UI-endringer
- **Skalerbarhet**: Enkelt å legge til nye visningstyper
- **Tilstandshåndtering**: Klar dataflyt fra model til view
### Hvorfor komplett sidegenerering?
- **Enkelhet**: Ingen kompleks DOM-diffing eller tilstandssporing
- **Pålitelighet**: Fresh render eliminerer foreldede tilstandsproblemer
- **Ytelse**: Moderne nettlesere håndterer innerHTML effektivt
- **Debugging**: Lett å se nøyaktig hvilken HTML som genereres
### Hvorfor LocalStorage?
- **Persistering**: Handlekurv overlever nettleseroppstart
- **Enkelhet**: Ingen serversidekompleksitet
- **Ytelse**: Øyeblikkelige lastetider
- **Utdanningsmessig**: Demonstrerer klientsidelagringskonsepter
## 🎨 Stylingarkitektur
Applikasjonen bruker et rent, moderne CSS-design:
- Responsive rutenettlayouter
- Kortbasert produktvisning
- Konsistent knapp- og formstiling
- Mobilvennlig navigasjon
- Glatte overganger og hover-effekter
## 🔮 Fremtidige forbedringer
Denne MVC-implementeringen fungerer som et grunnlag for progressiv forbedring:
1. **Fase 2**: Legg til TypeScript for typesikkerhet
2. **Fase 3**: Implementer Vue.js for reaktiv UI
3. **Fase 4**: Legg til brukerautentisering
4. **Fase 5**: Integrer betalingsbehandling
5. **Fase 6**: Legg til produktsøk og filtrering
6. **Fase 7**: Implementer ekte backend-API
## 📚 Læringsutbytte
Ved å studere denne kodebasen vil du forstå:
- MVC-arkitekturmønsterimplementering
- Klientsidehåndtering av tilstand
- Moderne JavaScript-utviklingspraksis
- HTML-generering og templating-tilnærminger
- Hendelsesdrevne programmeringsmønstre
- LocalStorage API-bruk
- Responsive webdesignprinsipper
- Tilgjengelighetsstandarder og semantisk HTML
---
*Dette prosjektet er en del av GET Frontend-utviklingslæreplanen og demonstrerer kjerne webutviklingskonsepter gjennom praktisk implementering.*