Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
0caa9d5
build(config): sett opp React, TypeScript og Vite
tordtst Sep 29, 2026
55a868f
docs(docs): dokumenter krav og oppstart
tordtst Sep 29, 2026
3ff2565
Merge pull request #9 from IT2810-H26/1-config-sett-opp-react-typescr…
andretg Sep 29, 2026
5dc3f80
build(config): sett opp Prettier
tordtst Sep 29, 2026
669dc17
build(config): sett opp ESLint for React og TypeScript
tordtst Sep 29, 2026
5629dea
docs(docs): dokumenter lint- og formateringskommandoer
tordtst Sep 29, 2026
633e393
Merge pull request #10 from IT2810-H26/2-config-sett-opp-linting-og-f…
andretg Sep 29, 2026
27ecf6b
feat(src): definer felles annonsetype og prisformat
tordtst Sep 30, 2026
697a182
feat(src): legg til eksempelannonser med illustrasjoner
tordtst Sep 30, 2026
58cb0a6
docs(docs): dokumenter datamodell og mockdata
tordtst Sep 30, 2026
8d5682a
Merge pull request #11 from IT2810-H26/4-feat-definer-annonsetype-og-…
andretg Sep 30, 2026
e373b91
style(css): legg til felles designvariabler og grunnstiler
tordtst Sep 30, 2026
84ca237
feat(src): lag prismerke og referanse for annonsekort
tordtst Sep 30, 2026
39899c0
feat(src): legg til designreferanse for utvikling
tordtst Sep 30, 2026
e9b556a
docs(docs): dokumenter designgrunnlag og mappestruktur
tordtst Sep 30, 2026
cd15f50
Merge pull request #12 from IT2810-H26/5-style-lag-felles-designgrunn…
andretg Sep 30, 2026
660d867
feat(app): legg til ruting, sidemal og plassholdersider
tordtst Sep 30, 2026
eebe6cf
feat(src): lag Button og TextField med tilgjengelige tilstander
tordtst Sep 30, 2026
373ad83
docs(docs): dokumenter sider, ruter og UI-komponenter
tordtst Sep 30, 2026
d1ddc4f
Merge pull request #13 from IT2810-H26/6-feat-lag-responsiv-sidemal-o…
andretg Sep 30, 2026
41bd5bd
feat(src): gjør annonsekortet til en lenke til detaljvisningen
andretg Sep 30, 2026
3a864bd
feat(src): lag rutenett for annonsekort
andretg Sep 30, 2026
4941918
feat(pages): vis annonsekort i katalogen
andretg Sep 30, 2026
3bae149
docs(docs): dokumenter katalog og annonsekort
andretg Sep 30, 2026
fb3a532
Merge pull request #17 from IT2810-H26/14-feat-lag-katalogvisning-med…
tordtst Sep 30, 2026
e939db0
feat(src): trekk ut annonsebilde med plassholder til egen komponent
Sep 30, 2026
fbe1626
feat(src): legg til hjelpefunksjoner for leieperiode og beløp
Sep 30, 2026
72a2873
feat(src): lag skjema for leieforespørsel med datovalg og demomelding
Sep 30, 2026
a36f235
feat(pages): vis alle annonseopplysninger og leieforespørsel i detalj…
Sep 30, 2026
13c7b57
docs(docs): dokumenter detaljvisning, annonsebilde og leieforespørsel
Sep 30, 2026
e0f2f10
Merge pull request #22 from IT2810-H26/18-feat-lag-detaljvisning-for-…
sebasti Sep 30, 2026
48d88f9
feat(src): lag nedtrekksliste og tekstområde med samme stil som tekst…
Sep 30, 2026
7e42f33
feat(src): legg til validering av annonseskjema
Sep 30, 2026
786f6a0
feat(src): lag skjema for ny annonse med prisforhåndsvisning og demom…
Sep 30, 2026
6ad695b
feat(pages): vis utleieskjemaet på siden for å leie ut verktøy
Sep 30, 2026
2354d33
docs(docs): dokumenter utleieskjema og nye skjemafelt
Sep 30, 2026
c4b34d0
feat(src): legg til filtrering av annonser med tilstand i URL-en
andretg Sep 30, 2026
92dd46d
Merge pull request #23 from IT2810-H26/19-feat-lag-skjema-for-å-legge…
tordtst Sep 30, 2026
a4f5dd5
feat(pages): legg til søk og filtre i katalogen
andretg Sep 30, 2026
a389dce
docs(docs): dokumenter søk og filtre
andretg Sep 30, 2026
07ee97d
Merge pull request #24 from IT2810-H26/15-feat-legg-til-søk-og-filtre…
sebasti Sep 30, 2026
4ea97de
docs(docs): beskriv idéen og visningene i prototypen
Sep 30, 2026
933cfc4
docs(docs): forklar hva som er mockup og demo i prototypen
Sep 30, 2026
78cce02
docs(docs): beskriv hva som er planlagt videre
Sep 30, 2026
f801440
feat(src): legg til sortering av annonser med tilstand i URL-en
andretg Sep 30, 2026
39a4bfa
Merge pull request #25 from IT2810-H26/20-docs-beskriv-idé-data-og-av…
tordtst Sep 30, 2026
816af25
feat(pages): legg til sortering i katalogen
andretg Sep 30, 2026
046a569
docs(docs): dokumenter sortering
andretg Sep 30, 2026
72f51a6
Merge pull request #26 from IT2810-H26/16-feat-legg-til-sortering-i-k…
sebasti Sep 30, 2026
18a7157
build(config): sett opp Vitest og React Testing Library
Oct 1, 2026
ac84366
test(src): test pris og gratismerking i prismerket
Oct 1, 2026
3a1a677
test(src): test søk, filtre og sortering av annonser
Oct 1, 2026
cd3895c
test(src): test leieperiode og validering av annonseskjema
Oct 1, 2026
ae69d64
test(src): test tilgjengelige navn på skjemafelt og knapper
Oct 1, 2026
4ea70a7
test(app): test navigasjon mellom sidene og søk i katalogen
Oct 1, 2026
2d26300
test(src): test leieforespørsel og utleieskjema
Oct 1, 2026
8db3b7d
docs(docs): dokumenter tester og kontroller av brukeropplevelsen
Oct 1, 2026
d7a60e4
docs(docs): lag prosjektstandard for branches, commits og pull requests
Oct 1, 2026
893a922
docs(github): legg til mal for issues
Oct 1, 2026
14ea10f
docs(github): legg til mal for pull requests
Oct 1, 2026
2afa597
docs(docs): opprett dokument for KI-bruk
Oct 1, 2026
6067406
docs(docs): legg til gjenstående kontroller i testdokumentasjonen
Oct 1, 2026
0d9ac11
docs(docs): fjern gjentakelser i README og samle lenker til dokumenta…
Oct 1, 2026
190022c
docs(docs): skrivefeil
Oct 1, 2026
93e8688
Merge pull request #27 from IT2810-H26/7-test-sett-opp-tester-og-kont…
sebasti Oct 1, 2026
0c6c615
Merge pull request #28 from IT2810-H26/3-docs-opprett-prosjektdokumen…
sebasti Oct 1, 2026
b9a6aac
build(config): krev Node-versjon som alle avhengighetene støtter
Oct 1, 2026
46327c3
fix(app): legg til favicon
Oct 1, 2026
14b45eb
docs(docs): dokumenter sluttkontrollen før første innlevering
Oct 1, 2026
f6f0420
docs(docs): beskriv planlagte data og sortering i katalogen
Oct 1, 2026
cae007b
docs(docs): utvid planen videre og be om tilbakemeldinger
Oct 1, 2026
ad9d507
Merge pull request #29 from IT2810-H26/21-config-klargjør-første-innl…
tordtst Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions .github/ISSUE_TEMPLATE/oppgave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
name: Oppgave
about: Ny funksjonalitet, feilretting, dokumentasjon, test eller oppsett
title: '[FEAT] '
labels: ''
assignees: ''
---

<!--
Bytt FEAT i tittelen med riktig type: FEAT, FIX, DOCS, TEST, CONFIG eller STYLE.
Skriv tittelen i imperativ, for eksempel «Lag detaljvisning for annonser».
Husk label, milestone og hvem som har ansvaret.
-->

## Beskrivelse

<!-- Hva skal gjøres, og hvorfor? Én til tre setninger. -->

## Akseptansekriterier

- [ ] <!-- Konkret og etterprøvbart, for eksempel «Et tomt søk viser alle annonser.» -->
- [ ]

## Avgrensning

<!-- Hva hører ikke med i dette issuet? -->

## Avhengigheter

<!-- Issues eller deler som må være på plass først. Skriv «Ingen» hvis det ikke finnes noen. -->
31 changes: 31 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
## Issue

Closes #

<!--
GitHub lukker bare issuet automatisk ved merge til main. Ved merge til dev må
issuet lukkes for hånd. Skriv det her hvis branchen bygger på en annen branch
som ikke er merget ennå.
-->

## Endringer

<!-- Hva er endret, og hvorfor? Nevn valg som den som gjennomgår, bør se på. -->

-

## Testing

<!-- Hvilke tester er lagt til, og hva er kontrollert i nettleser? -->

- [ ] `npm run typecheck`
- [ ] `npm run lint`
- [ ] `npm run format:check`
- [ ] `npm test`
- [ ] `npm run build`
- [ ] Kontrollert i nettleser, også på smal skjerm og med tastatur

## Sjekkliste

- [ ] README eller `docs/` er oppdatert hvis det trengs
- [ ] Eventuell KI-bruk er ført i `docs/ki-bruk.md`
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Avhengigheter
node_modules

# Byggresultat
dist
*.tsbuildinfo

# Logger
npm-debug.log*
*.log

# Lokale miljøvariabler
.env
.env.*.local
.env.local

# Editor og OS
.DS_Store
.idea
.vscode/*
!.vscode/extensions.json
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24
6 changes: 6 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Genererte filer og avhengigheter. Prettier leser også .gitignore,
# men listen gjør det tydelig hva som holdes utenfor formateringen.
node_modules
dist
coverage
package-lock.json
6 changes: 6 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"semi": true,
"tabWidth": 2,
"trailingComma": "all"
}
272 changes: 258 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,267 @@

Repository for team IT2810-H26-T36 in IT2810-H26.

## Working in this repository
Webapplikasjon for leie og gratis utlån av verktøy mellom studenter og
privatpersoner i Trondheim. Bygget med React, TypeScript og Vite.

`main` is protected — you cannot push to it directly. Work on a branch and
open a pull request:
## Om prototypen

Dette er første innlevering: en klikkbar prototype som viser idéen og hvordan
løsningen er tenkt brukt. Den har ingen backend, database eller innlogging.

### Idé

Mange har verktøy som står ubrukt det meste av året, mens andre trenger det
samme verktøyet én helg. Her kan studenter og privatpersoner i Trondheim leie
ut eller låne bort verktøy til hverandre. Eieren setter en døgnpris, og
**0 kroner betyr gratis utlån**. Målet er at det skal være enkelt å finne og
låne verktøy i nærheten i stedet for å kjøpe nytt.

### Visninger og navigasjon

| Visning | Slik kommer du dit | Hva du kan gjøre |
| -------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Katalog | Startsiden, «Katalog» i menyen eller navnet øverst | Se alle annonsene, søke, filtrere på kategori og gratis utlån og sortere på pris |
| Detaljvisning | Klikk på et annonsekort i katalogen | Se bilde, beskrivelse, tilstand, tilbehør og pris, velge datoer og se samlet pris |
| Lei ut verktøy | «Lei ut verktøy» i menyen | Fylle ut skjemaet for en ny annonse med tittel, kategori, beskrivelse, område og pris |

Menyen ligger øverst på alle sider. Detaljvisningen har en lenke tilbake til
katalogen, og en ukjent adresse gir en side med lenke til katalogen. Alt kan
brukes med tastatur.

Betalt leie og gratis utlån skilles med tekst, ikke bare med farge. Betalte
annonser viser for eksempel «150 kr/døgn», mens gratis annonser viser
«Gratis utlån» med grønn bakgrunn.

### Hva som er mockup

- **Annonsene er oppdiktede eksempler.** De 10 annonsene i
`src/data/mockListings.ts` er skrevet for prototypen. De er ikke ekte tilbud
og inneholder ingen personopplysninger. Illustrasjonene er laget for
prosjektet. Ekstern datakilde, for eksempel for produktdata, er ikke valgt.
- **Leieforespørselen er en demo.** Knappen heter «Send forespørsel (demo)».
Ingen forespørsel blir sendt, og verktøyet blir ikke reservert.
- **Utleieskjemaet er en demo.** Knappen heter «Legg ut verktøy (demo)».
Annonsen blir ikke lagret og vises ikke i katalogen.
- **Ingenting lagres.** Det finnes ingen backend, database eller innlogging.
Søk og filtre virker bare på eksempelannonsene i nettleseren, og det som
er fylt ut i skjemaene, forsvinner når siden lastes inn på nytt.

### Data

En annonse har i dag tittel, kategori, beskrivelse, område i Trondheim,
døgnpris, tilstand, tilbehør og bilde. Feltene er beskrevet under
[Datamodell og mockdata](#datamodell-og-mockdata).

I den ferdige løsningen ligger dataene i en database:

| Data | Innhold |
| ------------- | ---------------------------------------------------------------------- |
| Verktøymodell | Produktinformasjon som er lik for alle eksemplarer, for eksempel merke |
| Annonse | Ett fysisk eksemplar med eier, tilstand, pris, område og bilde |
| Bruker | Den som legger ut annonser eller sender leieforespørsler |
| Booking | Leieperiode og status: sendt, godkjent, avslått, utlevert eller levert |
| Vurdering | Leietakerens vurdering etter et gjennomført leieforhold |

Annonser, bookinger og vurderinger er de brukergenererte dataene som lagres.
For å teste søk og blaing i store resultatsett fyller vi databasen med
genererte eksempelannonser via et seed-skript. Om vi henter produktdata fra en
ekstern kilde, er ikke avklart.

### Planlagt videre

- **Backend og database:** En egen GraphQL-backend i Node og TypeScript med
PostgreSQL. Begge kjører direkte på gruppens VM, uten Docker. Appen blir
tilgjengelig via Apache under `/project2`, og backenden på port 3001.
- **Søk i hele databasen:** Søk, filtre og sortering skjer på serveren, før
resultatet deles opp i sider. Katalogen får blaing med «Forrige» og
«Neste», og endrede valg starter på første side. Søket venter til brukeren
har sluttet å skrive (debouncing), og svar på utdaterte søk forkastes.
- **State:** Apollo Client henter og bufrer data fra backenden. Søk, filtre og
sortering ligger fortsatt i URL-en.
- **Innlogging og egne annonser:** Brukere kan opprette, redigere og
deaktivere egne annonser. Serveren sjekker at bare eieren kan endre dem.
- **Booking:** Eieren godkjenner eller avslår leieforespørsler, og begge
parter ser sine leieforhold. Godkjente bookinger kan ikke overlappe for
samme verktøy. Utlevering og retur registreres, og leietakeren kan gi en
vurdering etterpå. Gratis utlån bruker samme flyt.
- **Tilgjengelighet:** Semantisk HTML, tastaturnavigasjon, synlig fokus og
kontrast etter WCAG 2.1 er på plass allerede. Senere kommer test med
skjermleser og en manuell brukertest.
- **Bærekraft:** Små bilder som lastes når de trengs, systemfont, buffring og
spørringer som bare henter feltene som vises. Vi måler datamengde og antall
forespørsler.
- **Testing:** Komponenttester med Vitest finnes allerede. Senere kommer
API-tester mot en testdatabase og en ende-til-ende-test med Playwright av en
hel leieflyt.

Betaling, depositum, frakt og chat er ikke en del av planen. Hvis kjernen blir
ferdig og testet, vurderer vi prosjektlister, for eksempel «Bygg en
bokhylle», med verktøyene som trengs.

### Dette ønsker vi tilbakemelding på

- Er idéen og forskjellen på leie og gratis utlån lett å forstå?
- Mangler katalogen filtre eller sorteringer du ville brukt, for eksempel
område eller ledige datoer?
- Er det tydelig hvordan en leieforespørsel fungerer?
- Er det noe i datamodellen over som virker unødvendig, eller som mangler?

## Krav

- Node.js 24.15 eller nyere (LTS). Versjonen står i `.nvmrc`, så med nvm holder
det å kjøre `nvm use`.
- npm 10 eller nyere (følger med Node).

`engines` i `package.json` angir minstekrav: Node 22.22.2 eller 24.15 og
npm 10. Lavere versjoner støttes ikke av `jsdom`, som testene bruker. npm
stopper ikke installasjonen hvis versjonen er feil. Sjekk selv med
`node -v` og `npm -v`.

TypeScript er låst til 6.0.x fordi `typescript-eslint` foreløpig ikke støtter
TypeScript 7.

## Oppstart

```bash
git checkout -b my-feature
git push -u origin my-feature
npm ci # installer avhengigheter nøyaktig etter package-lock.json
npm run dev # start utviklingsserver på http://localhost:5173
```

Before a pull request can be merged:
## Kommandoer

| Kommando | Hva den gjør |
| ---------------------- | ----------------------------------------- |
| `npm run dev` | Starter utviklingsserver |
| `npm run build` | Kjører typekontroll og bygger til `dist/` |
| `npm run preview` | Viser det bygde resultatet lokalt |
| `npm run typecheck` | Kjører TypeScript med streng typekontroll |
| `npm test` | Kjører alle testene én gang |
| `npm run test:watch` | Kjører testene ved hver endring |
| `npm run lint` | Kjører ESLint på hele prosjektet |
| `npm run format` | Formaterer alle filer med Prettier |
| `npm run format:check` | Sjekker formatering uten å endre filer |

ESLint finner feil i koden, mens Prettier bestemmer formateringen.
`eslint-config-prettier` ligger sist i `eslint.config.js` og slår av
ESLint-regler som ellers ville kollidert med Prettier. Byggfiler,
avhengigheter og `package-lock.json` formateres ikke.

Testene bruker Vitest og React Testing Library. Hva som testes, og hvilke
kontroller som er gjort i nettleser, står i [docs/testing.md](docs/testing.md).

## Mappestruktur

```
src/
types/ Felles datatyper, for eksempel Listing
data/ Mockdata. Byttes med GraphQL-backend senere
utils/ Formatering av pris og etiketter, filtrering og sortering
assets/ Illustrasjoner til eksempelannonsene
styles/ Designvariabler og grunnstiler
components/ Gjenbrukbare komponenter, én mappe per komponent
pages/ Én mappe per side
hooks/ Små felles hooks, for eksempel usePageTitle
design/ Designreferanse, bare under utvikling
test/ Felles oppsett for testene
```

Komponenter i `components/` får data gjennom props og importerer ikke
`data/` direkte. Bare sidene i `pages/` henter data. Da kan datakilden byttes
uten at visningene må skrives om.

## Sider og ruter

Rutene er definert i `src/App.tsx` med React Router.

| Rute | Side | Innhold nå |
| ---------------------- | ------------------- | ------------------------------------------- |
| `/` | `CatalogPage` | Annonsekort med søk, filtre og sortering |
| `/annonser/:listingId` | `ListingDetailPage` | Alle opplysninger og leieforespørsel (demo) |
| `/lei-ut` | `RentOutPage` | Skjema for å legge ut verktøy (demo) |
| Alle andre | `NotFoundPage` | «Fant ikke siden» |

Ny side: lag en mappe i `src/pages/`, legg til en `Route` i `App.tsx` og kall
`usePageTitle` i siden. Sidemalen (`Layout`) gir header, navigasjon og
hopp-lenke automatisk.

## Søk, filtre og sortering

Katalogen kan snevres inn med fritekstsøk, kategori og gratis utlån. Søket
leter i tittel og beskrivelse og skiller ikke mellom store og små bokstaver.
Filtrene kan kombineres, og et tomt søk viser alle annonser.

Treffene kan sorteres på pris, lavest eller høyest først. Standard er
rekkefølgen fra datakilden. Sorteringen gjøres etter filtreringen og er
stabil: annonser med samme pris beholder rekkefølgen seg imellom. «Fjern alle
filtre» nullstiller søk og filtre, men beholder sorteringen. Sortering på
nyeste krever et datofelt i `Listing` og er ikke laget ennå.

Valgene lagres i URL-en, slik at de overlever en sideoppdatering og kan deles
som lenke:

| Parameter | Eksempel | Betydning |
| ----------- | --------------------- | ----------------------------------- |
| `q` | `?q=drill` | Søkeord |
| `kategori` | `?kategori=garden` | Kategori, med nøklene fra `Listing` |
| `gratis` | `?gratis=1` | Bare annonser med pris 0 |
| `sortering` | `?sortering=priceAsc` | `priceAsc` eller `priceDesc` |

Ugyldige verdier ignoreres, og standardvalg vises ikke i URL-en. Filtrering og
sortering skjer foreløpig lokalt på mockdataene i `src/utils/listingFilters.ts`
og `src/utils/listingSort.ts`. Hookene `useListingFilters` og `useListingSort`
leser og skriver valgene i URL-en uten å fylle nettleserhistorikken med ett
innslag per endring.

## Design

Felles farger, typografi, avstander og komponenter er beskrevet i
[docs/design.md](docs/design.md). Under utvikling viser
<http://localhost:5173/design.html> en designreferanse med eksempler. Den er
ikke med i produksjonsbygget.

## Datamodell og mockdata

Alle annonser følger typen `Listing` i `src/types/listing.ts`:

| Felt | Innhold |
| ------------- | ---------------------------------------------------------- |
| `id` | Stabil ID, for eksempel `listing-001` |
| `title` | Kort tittel |
| `category` | Fast nøkkel, for eksempel `powerTools` |
| `description` | Fritekst |
| `area` | Område i Trondheim, for eksempel «Moholt» |
| `dailyPrice` | Pris i hele kroner per døgn. `0` betyr gratis utlån |
| `condition` | `likeNew`, `good` eller `worn` |
| `accessories` | Liste med tilbehør. Tom liste når ingenting følger med |
| `imageUrl` | Adresse til bilde, eller `null` når annonsen mangler bilde |

Kategori og tilstand lagres som engelske nøkler slik at de senere kan bli
GraphQL-enums. `src/utils/listingFormat.ts` gir de norske visningsnavnene og
`formatDailyPrice`, som viser `150 kr/døgn` eller `Gratis utlån`, og
`formatKroner` for vanlige beløp. Bruk disse i
stedet for å formatere på nytt i hver komponent. Når `imageUrl` er `null`, viser
`ListingImage` en nøytral plassholder.

`src/utils/rentalPeriod.ts` regner ut antall døgn og sjekker datoene i en
leieforespørsel. Henting og retur samme dag regnes som ett døgn.

`src/utils/listingForm.ts` validerer skjemaet for å legge ut verktøy. Alle
felt er påkrevd, og døgnprisen må være et helt tall fra 0 til 10 000 kroner.
Serveren skal senere gjøre den samme kontrollen.

`src/data/mockListings.ts` har 10 eksempelannonser som dekker gratis og betalt
utlån, korte og lange titler, tomt tilbehør og annonser uten bilde. Se
[Hva som er mockup](#hva-som-er-mockup) for hvor dataene kommer fra.

## Dokumentasjon

| Fil | Innhold |
| ---------------------------------------------------- | -------------------------------------------------------- |
| [docs/prosjektstandard.md](docs/prosjektstandard.md) | Branches, commit-format, pull requests og krav før merge |
| [docs/design.md](docs/design.md) | Farger, typografi, kontrast og felles komponenter |
| [docs/testing.md](docs/testing.md) | Tester, kontroller, resultater og det som gjenstår |
| [docs/ki-bruk.md](docs/ki-bruk.md) | Hvordan vi bruker og kontrollerer KI |

1. **A member of IT2810-H26-T36 must approve it.** You cannot approve your own pull
request, and approvals from staff do not count — you review each other's
code.
2. **Every review comment must be marked resolved.** Reply to each one, fix it
or explain why not, then click *Resolve conversation*.
3. **Pushing new commits dismisses the approval**, so if you change something
after being approved, ask for another review. This is deliberate: what was
approved is what gets merged.
`main` er beskyttet, så alt arbeid går via pull request mot `dev`. Maler for
issues og pull requests ligger i `.github/`.
Loading