From bad6b5afca3f29bd12ccad488f5fbba68c3eb5d5 Mon Sep 17 00:00:00 2001 From: Urban Modig Date: Sun, 26 Jul 2026 16:29:18 +0200 Subject: [PATCH] docs: specify task points feature --- docs/features/003-task-points.md | 439 +++++++++++++++++++++++++++++++ 1 file changed, 439 insertions(+) create mode 100644 docs/features/003-task-points.md diff --git a/docs/features/003-task-points.md b/docs/features/003-task-points.md new file mode 100644 index 0000000..e741bf1 --- /dev/null +++ b/docs/features/003-task-points.md @@ -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.