Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ coverage/
.vite/
*.local
*.tsbuildinfo
playwright-report/
test-results/
.env
.env.*
!.env.example
210 changes: 190 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,217 @@
# Spillkveld

Spillkveld er en nettside som skal gjøre det enklere for venner og familier å finne brettspill som passer til antall personer og tiden de har. Dette er den første, kjørbare prototypen i IT2810. Den lar medstudenter prøve hovedideen før vi kobler på en backend og et større datasett.
Spillkveld hjelper venner og familier å finne brettspill som passer til antall personer og tiden de har. Applikasjonen er utviklet av gruppe T32 i IT2810.

## Kom i gang
**Prøv appen:** [Spillkveld på VM](http://it2810-32.idi.ntnu.no/project2/). Bruk NTNU-nettet eller NTNU VPN utenfor campus.

Du trenger Node.js 22 eller nyere og npm. Kjør følgende fra prosjektmappen:
**Repo:** [IT2810-H26/T32-Project-2](https://git.ntnu.no/IT2810-H26/T32-Project-2).

## Funksjoner

- Søk i navn og beskrivelse, og kombiner filtre for antall spillere, spilletid og kategori.
- Sorter etter navn eller spilletid, og bla gjennom seks spill per side.
- Åpne spilldetaljer og gå tilbake med søk og filtre bevart.
- Legg til og fjern spill i «Kveldens utvalg». Listen lagres i nettleseren og beholdes etter ny innlasting.
- Mobiltilpasset grensesnitt med tastaturbetjening, synlig fokus og meldinger ved lasting, feil og ingen treff.

Spillene hentes fra **PostgreSQL gjennom GraphQL**. Søk, filtrering, sortering og sidevisning skjer i backend.

**De 12 spillene er eksempeldata**, med forenklede beskrivelser, kategorier og spilletider. De kommer ikke fra et valgt eller offisielt brettspilldatasett. Symbolene er dekorative ikoner.

## Lokal oppstart

Du trenger Git, npm, Node.js 22.22 eller 24, og en kjørende PostgreSQL-installasjon. Løsningen er testet med PostgreSQL 17.11 og 18.6.

### 1. Installer avhengigheter

```bash
git clone https://git.ntnu.no/IT2810-H26/T32-Project-2.git
cd T32-Project-2
npm ci
npm --prefix server ci
```

### 2. Opprett databaser

Åpne `psql` som lokal PostgreSQL-administrator. På en ny installasjon:

```sql
CREATE ROLE spillkveld_app LOGIN;
\password spillkveld_app
CREATE DATABASE spillkveld OWNER spillkveld_app;
CREATE DATABASE spillkveld_test OWNER spillkveld_app;
```

`\password` ber om et passord til den lokale databasebrukeren. Testdatabasen brukes bare til automatiske tester.

### 3. Konfigurer og fyll databasen

Kopier `server/.env.example` til `server/.env`, og sett inn ditt lokale databasepassord:

```dotenv
DATABASE_URL=postgresql://spillkveld_app:DITT_LOKALE_PASSORD@127.0.0.1:5432/spillkveld
TEST_DATABASE_URL=postgresql://spillkveld_app:DITT_LOKALE_PASSORD@127.0.0.1:5432/spillkveld_test
PORT=3001
HOST=127.0.0.1
```

Spesialtegn i passordet må URL-kodes. Faktiske passord og `.env`-filer skal ikke legges i Git.

Kjør fra prosjektroten:

```bash
npm --prefix server run db:setup
npm --prefix server run db:seed
```

Seed kan kjøres flere ganger uten duplikater; eksisterende spill blir ikke oppdatert.

### 4. Start appen

Start backend:

```bash
npm --prefix server run dev
```

Start frontend i en annen terminal, også fra prosjektroten:

```bash
npm install
npm run dev
```

Åpne adressen som Vite viser, vanligvis `http://localhost:5173`.
Åpne [http://localhost:5173/project2/](http://localhost:5173/project2/). La `VITE_GRAPHQL_URL` være tom ved lokal utvikling; Vite videresender `/graphql` til backend på port 3001.

## Arkitektur

Frontend bruker React, TypeScript og Vite. Apollo Client sender GraphQL-spørringer til en Node.js-backend med GraphQL Yoga. Backend bruker `pg` til å hente spill fra PostgreSQL. Apache serverer frontend og videresender API-kall på VM-en.

| Mappe | Innhold |
| ----------------------- | ------------------------------------------------------------ |
| `src/` | Grensesnitt, Apollo-oppsett og frontend-tester |
| `server/src/` | GraphQL-skjema, validering og parameteriserte SQL-spørringer |
| `server/db/` | Tabellskjema og de 12 eksempelspillene |
| `server/tests/`, `e2e/` | Backend-tester og Playwright-test |
| `deploy/` | Apache, systemd og publiseringsskript |

API-et har fire spørringer: `games` for katalogen, `game` for detaljer, `gamesByIds` for utvalgte spill og `categories` for kategorier. Backend beregner totalt antall treff før sidevisning og sikrer stabil sortering. Databasen krever gyldige spillergrenser, positiv spilletid og at nødvendige felt er fylt ut. Feltene er definert i `server/db/schema.sql` og `server/src/schema.ts`.

## Tester og kodekvalitet

For å kontrollere prosjektet:
Kjør fra prosjektroten:

```bash
npm test
npm run test:backend
npm run lint
npm run format:check
npm run build
npm --prefix server run build
```

`npm run preview` viser produksjonsbygget lokalt etter `npm run build`.
Frontend-testene bruker mockede GraphQL-svar og trenger ingen database. Backend-testene bruker `TEST_DATABASE_URL` med `localhost` eller `127.0.0.1` og databasen `spillkveld_test`. **Testene tømmer spilltabellen i testdatabasen** og setter inn egne testdata.

## Dette fungerer nå
Lint kontrollerer både frontend og backend. Formateringskommandoen dekker frontend og Vite-konfigurasjonen; øvrige filer kan kontrolleres med:

- Søk etter ord i spillnavn eller beskrivelse.
- Filtre for antall spillere, maksimal spilletid og kategori. Filtrene kan kombineres.
- Sortering etter navn eller kortest spilletid, og sidevisning av søkeresultater.
- Detaljvisning med beskrivelse og praktisk informasjon. Søk og filtre beholdes når du går tilbake.
- «Kveldens utvalg»: legg til og fjern spill. Listen lagres i nettleserens lokale lagring på samme enhet.
- Mobiltilpasset grensesnitt med synlig tastaturfokus, tydelige feltnavn og melding ved null treff.
```bash
npx prettier --check "server/**/*.{ts,mjs,json}" "e2e/**/*.ts" playwright.config.ts README.md
```

### Ende-til-ende-test

Installer nettleseren én gang med `npx playwright install chromium`. Med lokal frontend og backend i gang kjører du `npm run test:e2e`. Mot VM fra PowerShell:

```powershell
$env:PLAYWRIGHT_BASE_URL = 'http://it2810-32.idi.ntnu.no/project2/'
npm run test:e2e
Remove-Item Env:PLAYWRIGHT_BASE_URL
```

Testen søker etter Azul, kontrollerer ekte GraphQL-svar, åpner detaljer og går tilbake med søket bevart.

### Verifisert 16. oktober 2026

- Alle 13 frontend-tester og 22 backend-tester passerer. Backend-testene er også kjørt på VM med det felles databaseskjemaet.
- Lint, frontend-formatering og begge produksjonsbygg passerer.
- Ende-til-ende-testen passerer mot den publiserte appen, både før og etter VM-omstart. Appens hovedfunksjoner er også prøvd manuelt.
- Apache, PostgreSQL og backend startet automatisk etter omstart. Prosjekt 1 fungerer fortsatt.
- Seed kan kjøres flere ganger uten duplikater. Databasen avviser ugyldige spillergrenser, spilletid og manglende navn.

## Bygg og drift på VM

Frontend bygges med Vite-base `/project2/` og `VITE_GRAPHQL_URL=/project2/graphql`. Fra PowerShell i prosjektroten:

```powershell
$env:VITE_GRAPHQL_URL = '/project2/graphql'
npm run build
Remove-Item Env:VITE_GRAPHQL_URL
npm --prefix server run build
```

| Del | Oppsett på `it2810-32.idi.ntnu.no` |
| ---------- | -------------------------------------------------------------------------------- |
| Frontend | `dist/` publiseres til `/var/www/html/project2` |
| Backend | `/opt/spillkveld/server`, port `127.0.0.1:3001` |
| API-proxy | Apache videresender `/project2/graphql` til backend `/graphql` |
| PostgreSQL | Installert direkte uten Docker, database `spillkveld` på `127.0.0.1:5432` |
| Miljøfil | `/etc/spillkveld/backend.env`, kun lesbar for root |
| Tjeneste | `spillkveld-backend.service`, kjører `npm start` som systembrukeren `spillkveld` |

VM-en bruker Node.js 22.22.1, npm 9.2.0, PostgreSQL 18.6 og Apache 2.4.66. Systemd leser `DATABASE_URL`, `HOST` og `PORT` fra miljøfilen. Databasebrukeren `spillkveld_app` eier databasen uten administratorrettigheter.

Oppsettet forutsetter at Node.js, npm, PostgreSQL og Apache er installert på VM-en, og at prosjekt 1 svarer under `/project1/`. Kjør de to første kommandoene fra mappen som inneholder `deploy/`.

Førstegangsoppsettet består av tre steg:

**Spillene er statiske eksempeldata.** Beskrivelser, kategorier og spilletider er forenklet for å demonstrere prototypen. De er ikke hentet fra et valgt eller offisielt brettspilldatasett. Illustrasjonene er dekorative symboler, ikke spillbilder.
1. Kjør `sudo bash deploy/setup-database.sh` for å opprette database, bruker og miljøfil.
2. Kjør `sudo bash deploy/install-runtime.sh` for å installere Apache- og tjenesteoppsett.
3. Klargjør en utgivelsesmappe med backend under `server/`, bygget frontend under `dist/` og en kopi av `deploy/publish-first-release.sh` direkte i mappen. Installer, bygg og kontroller backend der, og kjør `sudo bash publish-first-release.sh`. Skriptet er tilpasset gruppens VM og brukeren `bjoabe`.

## Videre arbeid
Førstegangspubliseringen er gjennomført. Skriptet skal ikke kjøres på nytt på den publiserte appen. Den midlertidige testtjenesten er deaktivert. Ved senere oppdateringer bygges og testes en ny kopi før driftsfilene erstattes og backend startes på nytt. Behold miljøfilen og eksisterende data.

Vi skal velge og vurdere et brettspilldatasett, og bygge en Node.js- og TypeScript-backend med GraphQL og egen database på gruppens virtuelle maskin. Da skal søk, filtre, sortering og sidevisning gjelde hele katalogen, og klienten hente én resultatside om gangen. Backend skal også lagre «Kveldens utvalg». Vi vil vurdere bilder og vanskelighetsgrad når datakilde og rettigheter er avklart. «Hjelp meg å velge» kan bli en senere utvidelse. Kart, vurderinger og kommentarer er ikke del av denne prototypen.
Etter SSH-innlogging på VM kan drift kontrolleres med:

```bash
systemctl status apache2 postgresql spillkveld-backend
curl --fail http://127.0.0.1:3001/health
sudo journalctl -u spillkveld-backend -n 50 --no-pager
sudo systemctl restart spillkveld-backend
```

`/health` gir HTTP 200 med `{"status":"ok","database":"ok"}` når databasen er tilgjengelig, ellers HTTP 503. Ved Apache-endringer kontrolleres konfigurasjonen med `sudo apache2ctl configtest` før reload.

## Begrensninger og videre arbeid

Katalogen har bare de 12 eksempelspillene, og detaljvisningen viser foreløpig omtrent samme informasjon som kortet. «Kveldens utvalg» synkroniseres ikke mellom nettlesere eller enheter. Én ende-til-ende-test dekker søk og detaljer; den dekker ikke alle funksjoner og skjermstørrelser. VM-en bruker HTTP og krever NTNU-nett/VPN.

Et større datasett, bilder og «Hjelp meg å velge» kan vurderes videre. Kart, vurderinger og kommentarer er ikke implementert.

## Arbeid i repoet

Tekstfiler skal bruke LF-linjeskift på alle operativsystemer. `.gitattributes` styrer dette i Git, og `.editorconfig` gir samme regel til editorer og Prettier. Bruk støtte for EditorConfig i editoren din.
Tekstfiler skal bruke LF-linjeskift, styrt av `.gitattributes` og `.editorconfig`. Arbeid knyttes til en issue og gjøres på egen branch, for eksempel `feature/7-vm-deployment`. Issue- og PR-tekster og commitmeldinger skrives på engelsk; commitmeldinger viser til relevant issue.

`main` er beskyttet. Endringer leveres som pull request og må godkjennes av et annet medlem av `IT2810-H26-T32`; godkjenning fra ansatte teller ikke. Svar på og løs alle review-kommentarer. Nye commits fjerner tidligere godkjenning, så be om ny gjennomgang etter endringer.

Prosjektet bygger på [prosjektbeskrivelsen](https://docs.google.com/document/d/18swVXIU3Pm7DdFzoIUmIShoD_kerodH1R3CQX6Zy5qw/edit).

## KI-erklæringer

### Kamilla – database

ChatGPT ble brukt til å forklare PostgreSQL-oppsett, bistå med utkast til SQL-skjema og seed-fil og gi testinstruksjoner. SQL-filene ble kjørt, og resultatene ble kontrollert lokalt.

### Marius – backend

ChatGPT ble brukt til stegvis veiledning og kodeforslag for backend-konfigurasjon, databasetilgang, GraphQL-operasjoner, API-tester og dokumentasjon.

Verifiseringen av implementasjonen er beskrevet under tester. Ved backendleveransen var de gjenstående integrasjonskontrollene ennå ikke gjennomført.

### Andreas – frontend

ChatGPT ble brukt som støtte under frontend-utviklingen, hovedsakelig til å diskutere løsningsforslag, feilsøke, gjennomgå kode og foreslå forbedringer.

KI ble også brukt til hjelp med React, TypeScript, Apollo Client, GraphQL-integrasjon, automatiske tester og dokumentasjon. Forslagene ble gjennomgått, tilpasset ved behov og testet for å kontrollere at de fungerte som tiltenkt. Alle endringer ble kontrollert med automatiske tester, ESLint og produksjonsbygg.

`main` er beskyttet. Arbeid på en egen branch og åpne en pull request når arbeidet skal gjennomgås. Før den kan merges, må et medlem av `IT2810-H26-T32` godkjenne den; du kan ikke godkjenne din egen pull request, og godkjenning fra ansatte teller ikke. Svar på og løs alle review-kommentarer. Nye commits etter en godkjenning fjerner godkjenningen, så be om ny gjennomgang hvis du gjør endringer.
### Bjørn – prototype, drift og integrasjon

Denne prototypen følger [prosjektbeskrivelsen](https://docs.google.com/document/d/18swVXIU3Pm7DdFzoIUmIShoD_kerodH1R3CQX6Zy5qw/edit) og [issue #1](https://git.ntnu.no/IT2810-H26/T32-Project-2/issues/1).
Codex ble brukt til hjelp med prototypen, kodegjennomgang, VM-oppsett, publisering, Playwright-test og samlet dokumentasjon. Resultatet ble kontrollert med tester, lint, produksjonsbygg, HTTP-/GraphQL-kall og manuell utprøving. Automatisk oppstart og ende-til-ende-test ble også kontrollert etter VM-omstart.
70 changes: 70 additions & 0 deletions deploy/install-runtime.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bash
set -euo pipefail

if [[ $EUID -ne 0 ]]; then
echo 'Run with sudo: sudo bash deploy/install-runtime.sh' >&2
exit 1
fi

script_dir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
[[ -s /etc/spillkveld/backend.env ]] || { echo 'Run setup-database.sh first.' >&2; exit 1; }
[[ $(curl -s -o /dev/null -w '%{http_code}' http://localhost/project1/) == 200 ]]

if systemctl is-active --quiet spillkveld-backend.service; then
echo 'The real backend is running; refusing to replace it with the test server.' >&2
exit 1
fi
if ss -H -ltn 'sport = :3001' | grep -q .; then
systemctl is-active --quiet spillkveld-setup-test.service || {
echo 'Port 3001 is occupied by another process.' >&2
exit 1
}
fi

if id spillkveld >/dev/null 2>&1; then
[[ $(getent passwd spillkveld | cut -d: -f7) == /usr/sbin/nologin ]] || {
echo 'An unexpected spillkveld system account already exists.' >&2
exit 1
}
else
useradd --system --user-group --home-dir /opt/spillkveld --no-create-home --shell /usr/sbin/nologin spillkveld
fi

install -d -m 755 /opt/spillkveld/setup-test /var/www/html/project2
install -m 644 "$script_dir/setup-test/server.mjs" /opt/spillkveld/setup-test/server.mjs
if [[ ! -e /var/www/html/project2/index.html ]]; then
install -m 644 "$script_dir/setup-test/index.html" /var/www/html/project2/index.html
fi
install -m 644 "$script_dir/spillkveld-backend.service" /etc/systemd/system/spillkveld-backend.service
install -m 644 "$script_dir/spillkveld-setup-test.service" /etc/systemd/system/spillkveld-setup-test.service
systemd-analyze verify /etc/systemd/system/spillkveld-backend.service /etc/systemd/system/spillkveld-setup-test.service

configuration=/etc/apache2/conf-available/spillkveld.conf
if [[ -e $configuration ]] && ! cmp -s "$configuration" "$script_dir/spillkveld.conf"; then
echo 'Existing Apache configuration differs; inspect it before replacing it.' >&2
exit 1
fi
was_enabled=false
[[ ! -e /etc/apache2/conf-enabled/spillkveld.conf ]] || was_enabled=true
install -m 644 "$script_dir/spillkveld.conf" "$configuration"
a2enmod proxy proxy_http
a2enconf spillkveld
if ! apache2ctl configtest; then
if [[ $was_enabled == false ]]; then a2disconf spillkveld; fi
echo 'Apache configuration failed validation; Apache has not been reloaded.' >&2
exit 1
fi

systemctl daemon-reload
systemctl enable postgresql
systemctl enable --now spillkveld-setup-test.service
curl --fail --silent --retry 5 --retry-connrefused --retry-delay 1 http://127.0.0.1:3001/health
systemctl reload apache2

[[ $(curl -s -o /dev/null -w '%{http_code}' http://localhost/project1/) == 200 ]]
[[ $(curl -s -o /dev/null -w '%{http_code}' http://localhost/project2/) == 200 ]]
[[ $(curl -s -o /dev/null -w '%{http_code}' -X POST http://localhost/project2/graphql) == 503 ]]
curl --silent -X POST http://localhost/project2/graphql |
node -e 'let body=""; process.stdin.on("data", c => body += c); process.stdin.on("end", () => { if (JSON.parse(body).setupOnly !== true) process.exit(1); });'
echo
echo 'Runtime setup verified. The temporary server is running; the real backend is not deployed.'
Loading