Compare commits
1 Commits
2e62261f49
...
chore/004-
| Author | SHA1 | Date | |
|---|---|---|---|
| 77be23de5d |
439
docs/features/003-task-points.md
Normal file
439
docs/features/003-task-points.md
Normal file
@ -0,0 +1,439 @@
|
|||||||
|
# Feature 3 – Uppgiftspoäng
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
Planerad.
|
||||||
|
|
||||||
|
## Bakgrund
|
||||||
|
|
||||||
|
HemHub ska på sikt kunna använda spelifiering för att uppmuntra
|
||||||
|
familjemedlemmar att utföra uppgifter. Exempel på framtida funktioner kan vara
|
||||||
|
mål, achievements och belöningar baserade på hur många poäng en användare
|
||||||
|
samlar under en viss period.
|
||||||
|
|
||||||
|
Feature 3 inför den grundläggande poänginformationen på uppgiften. Funktionen
|
||||||
|
registrerar endast uppgiftens poängvärde. Intjäning av poäng och övrig
|
||||||
|
spelifiering införs i senare features.
|
||||||
|
|
||||||
|
## Mål
|
||||||
|
|
||||||
|
Feature 3 ska:
|
||||||
|
|
||||||
|
- lägga till ett obligatoriskt poängvärde på varje uppgift;
|
||||||
|
- låta användaren ange poäng när en uppgift skapas;
|
||||||
|
- visa poängen på uppgiftskortet;
|
||||||
|
- validera poängen konsekvent i frontend och backend;
|
||||||
|
- dokumentera hur lokal utvecklingsdata hanteras.
|
||||||
|
|
||||||
|
## Betydelsen av poäng
|
||||||
|
|
||||||
|
Poängen uttrycker uppgiftens samlade värde utifrån hur:
|
||||||
|
|
||||||
|
- tidskrävande uppgiften är;
|
||||||
|
- besvärlig uppgiften är;
|
||||||
|
- viktig uppgiften är.
|
||||||
|
|
||||||
|
När poängintjäning införs i en senare feature ska samma värde motsvara hur många
|
||||||
|
poäng användaren får när uppgiften slutförs.
|
||||||
|
|
||||||
|
Poängen är inte en exakt tidsuppskattning. En snabb men viktig uppgift kan
|
||||||
|
därför ha ett högre poängvärde än en längre men mindre betydelsefull uppgift.
|
||||||
|
|
||||||
|
Feature 3 registrerar endast poängvärdet. Den ska inte registrera:
|
||||||
|
|
||||||
|
- vem som har tjänat poängen;
|
||||||
|
- om poängen har delats ut;
|
||||||
|
- när poängen har tjänats in;
|
||||||
|
- någon historik över poäng.
|
||||||
|
|
||||||
|
## Poängskala
|
||||||
|
|
||||||
|
Poäng ska vara ett heltal mellan 1 och 99, inklusive gränsvärdena.
|
||||||
|
|
||||||
|
Alla heltal i intervallet är tillåtna. Feature 3 inför inte någon fast skala med
|
||||||
|
fördefinierade steg.
|
||||||
|
|
||||||
|
Giltiga exempel:
|
||||||
|
|
||||||
|
- 1
|
||||||
|
- 7
|
||||||
|
- 25
|
||||||
|
- 99
|
||||||
|
|
||||||
|
Ogiltiga exempel:
|
||||||
|
|
||||||
|
- inget värde;
|
||||||
|
- `null`;
|
||||||
|
- 0;
|
||||||
|
- negativa tal;
|
||||||
|
- 100 eller högre;
|
||||||
|
- decimaltal;
|
||||||
|
- text som inte kan tolkas som ett heltal.
|
||||||
|
|
||||||
|
En fast poängskala kan införas senare om erfarenhet från användningen visar att
|
||||||
|
det är lämpligt.
|
||||||
|
|
||||||
|
## Avgränsning
|
||||||
|
|
||||||
|
Feature 3 omfattar endast:
|
||||||
|
|
||||||
|
- uppgiftens titel;
|
||||||
|
- uppgiftens valfria beskrivning;
|
||||||
|
- uppgiftens obligatoriska poängvärde;
|
||||||
|
- visning av poäng på uppgiftskortet.
|
||||||
|
|
||||||
|
Feature 3 ska inte införa:
|
||||||
|
|
||||||
|
- tilldelning av uppgifter;
|
||||||
|
- ändring av uppgiftsstatus;
|
||||||
|
- drag-and-drop;
|
||||||
|
- redigering av befintliga uppgifter;
|
||||||
|
- radering av uppgifter;
|
||||||
|
- deadlines;
|
||||||
|
- återkommande uppgifter;
|
||||||
|
- poänghistorik;
|
||||||
|
- användares poängsaldo;
|
||||||
|
- topplistor;
|
||||||
|
- statistik;
|
||||||
|
- mål;
|
||||||
|
- achievements;
|
||||||
|
- belöningar;
|
||||||
|
- automatisk utdelning av poäng när en uppgift slutförs.
|
||||||
|
|
||||||
|
Dessa funktioner hanteras i senare features enligt roadmapen.
|
||||||
|
|
||||||
|
## Användarflöde
|
||||||
|
|
||||||
|
När användaren öppnar dialogen för att skapa en uppgift ska formuläret
|
||||||
|
innehålla:
|
||||||
|
|
||||||
|
- titel;
|
||||||
|
- beskrivning;
|
||||||
|
- poäng.
|
||||||
|
|
||||||
|
Poängfältet ska initialt innehålla värdet `1`.
|
||||||
|
|
||||||
|
Användaren kan behålla standardvärdet eller ange ett annat heltal mellan 1 och
|
||||||
|
99.
|
||||||
|
|
||||||
|
När uppgiften skapas ska frontend alltid skicka poängvärdet uttryckligen till
|
||||||
|
backend. Backend ska inte själv fylla i ett saknat värde.
|
||||||
|
|
||||||
|
Efter att en uppgift har skapats framgångsrikt ska formuläret återställas.
|
||||||
|
Poängfältet ska då återgå till `1`.
|
||||||
|
|
||||||
|
Om dialogen stängs och senare öppnas igen ska poängfältet också börja på `1`.
|
||||||
|
|
||||||
|
## Skapandedialog
|
||||||
|
|
||||||
|
Poäng ska anges med ett vanligt numeriskt inmatningsfält.
|
||||||
|
|
||||||
|
Fältet ska ha:
|
||||||
|
|
||||||
|
- etiketten `Poäng`;
|
||||||
|
- initialt värde `1`;
|
||||||
|
- minsta värde `1`;
|
||||||
|
- högsta värde `99`;
|
||||||
|
- heltalssteg.
|
||||||
|
|
||||||
|
En kort hjälptext kan visas:
|
||||||
|
|
||||||
|
> 1–99 poäng beroende på hur tidskrävande, besvärlig eller viktig uppgiften är.
|
||||||
|
|
||||||
|
Fältet får tillfälligt vara tomt medan användaren redigerar värdet. Frontend ska
|
||||||
|
inte automatiskt återställa värdet till `1` medan användaren skriver.
|
||||||
|
|
||||||
|
Validering ska främst ske när användaren försöker skicka formuläret. Avancerad
|
||||||
|
validering vid varje tangenttryckning ingår inte i denna feature.
|
||||||
|
|
||||||
|
## Frontendvalidering
|
||||||
|
|
||||||
|
Frontend ska blockera skapandeanropet om poängen inte är ett heltal mellan 1 och
|
||||||
|
99.
|
||||||
|
|
||||||
|
Vid ett ogiltigt värde ska följande meddelande visas:
|
||||||
|
|
||||||
|
> Poäng måste vara ett heltal mellan 1 och 99.
|
||||||
|
|
||||||
|
Samma meddelande kan användas för:
|
||||||
|
|
||||||
|
- tomt värde;
|
||||||
|
- värde under 1;
|
||||||
|
- värde över 99;
|
||||||
|
- decimaltal;
|
||||||
|
- annat ogiltigt innehåll.
|
||||||
|
|
||||||
|
HTML-fältets attribut för minsta värde, högsta värde och heltalssteg får användas
|
||||||
|
som stöd, men formulärlogiken ska också kontrollera värdet explicit.
|
||||||
|
|
||||||
|
Backend är alltid den slutliga garanten för valideringsreglerna.
|
||||||
|
|
||||||
|
## Visning på uppgiftskortet
|
||||||
|
|
||||||
|
Uppgiftens poäng ska visas på uppgiftskortet som en kompakt och dynamisk badge.
|
||||||
|
|
||||||
|
Badgen ska:
|
||||||
|
|
||||||
|
- renderas som en vanlig React- och HTML-komponent;
|
||||||
|
- använda text och CSS;
|
||||||
|
- läsa värdet från uppgiftens `points`;
|
||||||
|
- visa värdet i formatet `{points} p`.
|
||||||
|
|
||||||
|
Exempel:
|
||||||
|
|
||||||
|
- `1 p`
|
||||||
|
- `7 p`
|
||||||
|
- `99 p`
|
||||||
|
|
||||||
|
Ingen genererad bild eller statisk grafik ska användas för själva poängvärdet.
|
||||||
|
|
||||||
|
Placering och visuell utformning ska följa projektets befintliga skärmbilder och
|
||||||
|
nuvarande kortdesign. Poängindikatorn ska ligga i kortets metadataområde på
|
||||||
|
motsvarande plats som poängindikatorn i designreferensen.
|
||||||
|
|
||||||
|
Mindre justeringar får göras för att passa den faktiska kortimplementationen.
|
||||||
|
Feature 3 ska däremot inte införa en ny övergripande design för uppgiftskortet.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
Fältnamnet ska vara `points` genomgående i API, backend och frontend.
|
||||||
|
|
||||||
|
### Skapa uppgift
|
||||||
|
|
||||||
|
Requesten för att skapa en uppgift ska innehålla:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"title": "Töm diskmaskinen",
|
||||||
|
"description": "Ställ in allt i rätt skåp",
|
||||||
|
"points": 3
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`points` är obligatoriskt.
|
||||||
|
|
||||||
|
Backend ska inte tolka ett saknat värde som `1`.
|
||||||
|
|
||||||
|
### Uppgiftssvar
|
||||||
|
|
||||||
|
API-svar som innehåller en uppgift ska också innehålla `points`.
|
||||||
|
|
||||||
|
Exempel:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "00000000-0000-0000-0000-000000000000",
|
||||||
|
"title": "Töm diskmaskinen",
|
||||||
|
"description": "Ställ in allt i rätt skåp",
|
||||||
|
"status": "WAITING",
|
||||||
|
"points": 3,
|
||||||
|
"createdAt": "2026-07-26T12:00:00Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Det gäller både:
|
||||||
|
|
||||||
|
- svaret efter att en uppgift skapats;
|
||||||
|
- listning av uppgifter.
|
||||||
|
|
||||||
|
Det exakta API-formatet ska i övrigt följa den befintliga implementationen.
|
||||||
|
|
||||||
|
## Backendregler
|
||||||
|
|
||||||
|
En uppgift får aldrig existera med ett poängvärde utanför intervallet 1–99.
|
||||||
|
|
||||||
|
Regeln ska skyddas genom hela backend, inte bara i HTTP-lagret.
|
||||||
|
|
||||||
|
Beroende på repositoryts befintliga struktur ska valideringen tillämpas på
|
||||||
|
relevanta nivåer, exempelvis:
|
||||||
|
|
||||||
|
- requestvalidering;
|
||||||
|
- applikations- eller domänlogik;
|
||||||
|
- entitetsmodell;
|
||||||
|
- databasens schema.
|
||||||
|
|
||||||
|
Implementation ska följa projektets etablerade kodstruktur och inte introducera
|
||||||
|
ett nytt arkitekturmönster enbart för denna feature.
|
||||||
|
|
||||||
|
## Felhantering
|
||||||
|
|
||||||
|
Ett ogiltigt eller saknat `points` ska ge:
|
||||||
|
|
||||||
|
```text
|
||||||
|
400 Bad Request
|
||||||
|
```
|
||||||
|
|
||||||
|
Backend ska använda projektets befintliga felformat och befintliga
|
||||||
|
felhantering.
|
||||||
|
|
||||||
|
Feature 3 ska inte introducera en separat felmodell endast för poäng.
|
||||||
|
|
||||||
|
Backend får ge mer precisa valideringsdetaljer för exempelvis:
|
||||||
|
|
||||||
|
- saknat värde;
|
||||||
|
- `null`;
|
||||||
|
- värde under 1;
|
||||||
|
- värde över 99.
|
||||||
|
|
||||||
|
Frontend behöver inte återge varje backenddetalj separat, utan kan visa det
|
||||||
|
gemensamma användarmeddelandet:
|
||||||
|
|
||||||
|
> Poäng måste vara ett heltal mellan 1 och 99.
|
||||||
|
|
||||||
|
Vid andra eller oväntade backendfel ska frontend fortsätta använda projektets
|
||||||
|
befintliga generella felhantering.
|
||||||
|
|
||||||
|
## Databas
|
||||||
|
|
||||||
|
Databasschemat ska innehålla ett obligatoriskt heltalsfält för uppgiftens poäng.
|
||||||
|
|
||||||
|
Det logiska slutläget är:
|
||||||
|
|
||||||
|
```text
|
||||||
|
points INTEGER NOT NULL
|
||||||
|
```
|
||||||
|
|
||||||
|
Databasen ska, om den befintliga schemahanteringen stödjer det, även skydda
|
||||||
|
intervallet 1–99 med en motsvarande constraint.
|
||||||
|
|
||||||
|
Databasen ska inte ha ett permanent defaultvärde för nya uppgifter. Nya
|
||||||
|
uppgifter ska alltid få ett uttryckligt poängvärde från applikationen.
|
||||||
|
|
||||||
|
Det förvalda värdet `1` är ett frontendbeteende och inte ett sätt för backend
|
||||||
|
eller databasen att tyst komplettera ofullständiga anrop.
|
||||||
|
|
||||||
|
## Lokal utvecklingsdatabas
|
||||||
|
|
||||||
|
Den lokala utvecklingsdatabasen ska vara en in-memory H2-databas.
|
||||||
|
|
||||||
|
Databasen och dess innehåll ska återställas när backend startas om.
|
||||||
|
|
||||||
|
Lokal utvecklingsdata betraktas därför som tillfällig. Användare och uppgifter
|
||||||
|
som skapats manuellt under utveckling behöver inte bevaras mellan starter.
|
||||||
|
|
||||||
|
Detta innebär att Feature 3 inte behöver migrera verkliga befintliga
|
||||||
|
utvecklingsposter. En ny databas skapas direkt med det obligatoriska
|
||||||
|
poängfältet.
|
||||||
|
|
||||||
|
Codex ska kontrollera repositoryts faktiska konfiguration. Om H2 för närvarande
|
||||||
|
är filbaserad ska den ändras till in-memory och relevant
|
||||||
|
utvecklingsdokumentation ska uppdateras.
|
||||||
|
|
||||||
|
## Schemahantering och framtida migrering
|
||||||
|
|
||||||
|
Att lokal utvecklingsdata inte bevaras innebär inte att framtida
|
||||||
|
produktionsdata kan återställas vid varje release.
|
||||||
|
|
||||||
|
När HemHub börjar använda en beständig Postgres-databas med data som ska bevaras
|
||||||
|
måste schemaändringar hanteras med kontrollerade migreringar.
|
||||||
|
|
||||||
|
Feature 3 behöver inte införa eller färdigställa hela den framtida
|
||||||
|
produktionsstrategin om den ännu inte finns i repositoryt.
|
||||||
|
|
||||||
|
Projektet använder redan Flyway och versionshanterade migreringar. Feature 3 ska
|
||||||
|
därför lägga till en ny Flyway-migrering för poängfältet och inte ändra tidigare
|
||||||
|
migreringar. Hibernate ska fortsatt validera schemat i stället för att skapa
|
||||||
|
det.
|
||||||
|
|
||||||
|
Bytet till in-memory H2 innebär att befintliga lokala utvecklingsposter inte
|
||||||
|
behöver bevaras eller fyllas på med poäng. Själva schemaändringen ska ändå
|
||||||
|
hanteras som en kontrollerad migrering så att migrationshistoriken förblir
|
||||||
|
sammanhängande inför framtida beständig data.
|
||||||
|
|
||||||
|
Repositoryts faktiska arkitektur och dokumentation har företräde.
|
||||||
|
|
||||||
|
## Backendtester
|
||||||
|
|
||||||
|
Feature 3 ska minst verifiera att:
|
||||||
|
|
||||||
|
- en uppgift kan skapas med ett giltigt `points`;
|
||||||
|
- det skapade API-svaret innehåller samma `points`;
|
||||||
|
- listning av uppgifter innehåller `points`;
|
||||||
|
- gränsvärdet `1` accepteras;
|
||||||
|
- gränsvärdet `99` accepteras;
|
||||||
|
- saknat `points` ger `400 Bad Request`;
|
||||||
|
- `points: null` ger `400 Bad Request`;
|
||||||
|
- `points: 0` ger `400 Bad Request`;
|
||||||
|
- negativa värden ger `400 Bad Request`;
|
||||||
|
- `points: 100` ger `400 Bad Request`.
|
||||||
|
|
||||||
|
Testerna ska följa befintlig teststil och utöka nuvarande tester där det är
|
||||||
|
lämpligt.
|
||||||
|
|
||||||
|
## Frontendtester
|
||||||
|
|
||||||
|
Feature 3 ska minst verifiera att:
|
||||||
|
|
||||||
|
- skapandedialogen öppnas med poängvärdet `1`;
|
||||||
|
- ett giltigt poängvärde skickas i create-anropet;
|
||||||
|
- tomt poängfält blockerar submit;
|
||||||
|
- ett värde under 1 blockerar submit;
|
||||||
|
- ett värde över 99 blockerar submit;
|
||||||
|
- ett ogiltigt värde visar felmeddelandet;
|
||||||
|
- formuläret återställs till poängvärdet `1` efter lyckad skapning;
|
||||||
|
- ett uppgiftskort visar uppgiftens dynamiska poängbadge;
|
||||||
|
- badgen visar värdet från uppgiftsdata, exempelvis `7 p`.
|
||||||
|
|
||||||
|
Testerna ska inte vara beroende av en viss pixelplacering eller detaljerad CSS.
|
||||||
|
|
||||||
|
## Manuell verifiering
|
||||||
|
|
||||||
|
Följande ska verifieras manuellt:
|
||||||
|
|
||||||
|
1. Starta frontend och backend enligt projektets utvecklingsinstruktioner.
|
||||||
|
2. Skapa en uppgift utan att ändra poängfältet.
|
||||||
|
3. Verifiera att uppgiften får `1 p`.
|
||||||
|
4. Skapa en uppgift med ett mellanvärde, exempelvis `7`.
|
||||||
|
5. Verifiera att uppgiften får `7 p`.
|
||||||
|
6. Skapa en uppgift med `99`.
|
||||||
|
7. Verifiera att uppgiften får `99 p`.
|
||||||
|
8. Försök skapa en uppgift med tomt poängfält.
|
||||||
|
9. Verifiera att anropet blockeras och att rätt felmeddelande visas.
|
||||||
|
10. Försök använda värdena `0` och `100`.
|
||||||
|
11. Verifiera att båda avvisas.
|
||||||
|
12. Kontrollera att poängbadgen följer projektets designreferens och fungerar
|
||||||
|
med ett- och tvåsiffriga värden.
|
||||||
|
13. Starta om backend.
|
||||||
|
14. Verifiera att den lokala utvecklingsdatan inte finns kvar.
|
||||||
|
|
||||||
|
## Acceptanskriterier
|
||||||
|
|
||||||
|
Feature 3 är klar när:
|
||||||
|
|
||||||
|
- varje ny uppgift har ett obligatoriskt `points`;
|
||||||
|
- `points` är ett heltal mellan 1 och 99;
|
||||||
|
- frontendens standardvärde är `1`;
|
||||||
|
- frontend alltid skickar `points` uttryckligen;
|
||||||
|
- backend avvisar saknat eller ogiltigt `points`;
|
||||||
|
- backend fyller inte automatiskt i ett saknat värde;
|
||||||
|
- uppgiftens poäng returneras av API:t;
|
||||||
|
- uppgiftens poäng visas dynamiskt på uppgiftskortet;
|
||||||
|
- frontend- och backendtester täcker centrala giltiga och ogiltiga fall;
|
||||||
|
- lokal H2 körs som in-memory och återställs vid omstart;
|
||||||
|
- relevant dokumentation är uppdaterad;
|
||||||
|
- Feature 3 inte inför funktionalitet som hör till senare features.
|
||||||
|
|
||||||
|
## Implementationsprinciper
|
||||||
|
|
||||||
|
När Feature 3 senare implementeras ska Codex först läsa:
|
||||||
|
|
||||||
|
```text
|
||||||
|
AGENTS.md
|
||||||
|
README.md
|
||||||
|
docs/architecture.md
|
||||||
|
docs/development.md
|
||||||
|
docs/roadmap.md
|
||||||
|
docs/decisions/
|
||||||
|
docs/features/
|
||||||
|
```
|
||||||
|
|
||||||
|
Codex ska även läsa relevant backendkod, frontendkod och befintliga tester innan
|
||||||
|
ändringar görs.
|
||||||
|
|
||||||
|
Repositoryts faktiska kod och dokumentation har företräde framför antaganden i
|
||||||
|
denna featurebeskrivning.
|
||||||
|
|
||||||
|
Dokumentation, implementation och tester ska uppdateras tillsammans.
|
||||||
|
|
||||||
|
Codex ska inte committa, pusha, skapa pull request eller merga utan uttrycklig
|
||||||
|
instruktion.
|
||||||
Reference in New Issue
Block a user