Skip to content

Commit e3b0326

Browse files
aligneddevaligneddev
andauthored
009 create a per user (#27)
* spec * Add per-user settings page * location specs --------- Co-authored-by: aligneddev <aligneddev@github.com>
1 parent e7e9898 commit e3b0326

31 files changed

Lines changed: 3692 additions & 99 deletions
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Specification Quality Checklist: Per-User Settings Page
2+
3+
**Purpose**: Validate specification completeness and quality before proceeding to planning
4+
**Created**: 2026-03-30
5+
**Feature**: [spec.md](../spec.md)
6+
7+
## Content Quality
8+
9+
- [x] No implementation details (languages, frameworks, APIs)
10+
- [x] Focused on user value and business needs
11+
- [x] Written for non-technical stakeholders
12+
- [x] All mandatory sections completed
13+
14+
## Requirement Completeness
15+
16+
- [x] No [NEEDS CLARIFICATION] markers remain
17+
- [x] Requirements are testable and unambiguous
18+
- [x] Success criteria are measurable
19+
- [x] Success criteria are technology-agnostic (no implementation details)
20+
- [x] All acceptance scenarios are defined
21+
- [x] Edge cases are identified
22+
- [x] Scope is clearly bounded
23+
- [x] Dependencies and assumptions identified
24+
25+
## Feature Readiness
26+
27+
- [x] All functional requirements have clear acceptance criteria
28+
- [x] User scenarios cover primary flows
29+
- [x] Feature meets measurable outcomes defined in Success Criteria
30+
- [x] No implementation details leak into specification
31+
32+
## Notes
33+
34+
- Validation pass completed on 2026-03-30; no blocking issues found.
35+
- Spec is ready for `/speckit.plan`.
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Feature Specification: Per-User Settings Page
2+
3+
**Feature Branch**: `001-create-a-per-user`
4+
**Created**: 2026-03-30
5+
**Status**: Draft
6+
**Input**: User description: "Create a per user settings page. Allow entry of average car mpg, a yearly goal, location picker for lat and long, oil change price, and mileage rate (in cents)."
7+
8+
## User Scenarios & Testing *(mandatory)*
9+
10+
<!--
11+
IMPORTANT: User stories should be PRIORITIZED as user journeys ordered by importance.
12+
Each user story/journey must be INDEPENDENTLY TESTABLE - meaning if you implement just ONE of them,
13+
you should still have a viable MVP (Minimum Viable Product) that delivers value.
14+
15+
Assign priorities (P1, P2, P3, etc.) to each story, where P1 is the most critical.
16+
Think of each story as a standalone slice of functionality that can be:
17+
- Developed independently
18+
- Tested independently
19+
- Deployed independently
20+
- Demonstrated to users independently
21+
-->
22+
23+
### User Story 1 - Save Personal Ride and Cost Settings (Priority: P1)
24+
25+
As an authenticated rider, I want a personal settings page where I can enter my average car mpg, yearly goal, oil change price, and mileage rate so the app can reflect my own commuting assumptions instead of generic defaults.
26+
27+
**Why this priority**: This is the core value of the feature because it gives each rider a place to define the personal values that drive their own targets and cost comparisons.
28+
29+
**Independent Test**: Can be fully tested by visiting the settings page as a signed-in rider, entering valid values for the numeric fields, saving, and confirming the same values appear when returning to the page.
30+
31+
**Acceptance Scenarios**:
32+
33+
1. **Given** an authenticated rider opens the settings page for the first time, **When** the page loads, **Then** the rider sees fields for average car mpg, yearly goal, oil change price, and mileage rate.
34+
2. **Given** an authenticated rider enters valid values in the settings fields, **When** the rider saves the page, **Then** the system stores those values for that rider and confirms the save succeeded.
35+
3. **Given** a rider has previously saved settings, **When** the rider returns to the settings page, **Then** the page shows the rider's currently saved values.
36+
37+
---
38+
39+
### User Story 2 - Set a Personal Reference Location (Priority: P2)
40+
41+
As an authenticated rider, I want to pick a location that stores latitude and longitude so the app can use a rider-specific reference point for location-based features and calculations.
42+
43+
**Why this priority**: A saved location is part of the requested settings set, but it is secondary to the core need to store the rider's numeric personal settings.
44+
45+
**Independent Test**: Can be fully tested by opening the settings page, selecting a location through the picker, saving, and verifying the saved location is shown again on a later visit.
46+
47+
**Acceptance Scenarios**:
48+
49+
1. **Given** an authenticated rider is on the settings page, **When** the rider selects a location from the location picker, **Then** the page captures the associated latitude and longitude values for that rider.
50+
2. **Given** a rider selects a valid location and saves, **When** the rider revisits the settings page later, **Then** the previously selected location remains associated with the rider.
51+
52+
---
53+
54+
### User Story 3 - Update Settings Safely Over Time (Priority: P3)
55+
56+
As an authenticated rider, I want to update individual settings later without affecting other riders or losing unrelated saved values so my personal assumptions can change over time.
57+
58+
**Why this priority**: Riders will revisit these values occasionally, but the feature still delivers clear value even before ongoing edits are polished beyond the initial save flow.
59+
60+
**Independent Test**: Can be fully tested by saving an initial full settings profile, changing one field later, saving again, and verifying only that rider's intended value changed while the remaining saved values stay intact.
61+
62+
**Acceptance Scenarios**:
63+
64+
1. **Given** a rider already has saved settings, **When** the rider updates only one setting and saves, **Then** the updated value replaces the previous value and the rider's other saved settings remain unchanged.
65+
2. **Given** two different riders have their own settings, **When** one rider changes and saves a value, **Then** the other rider's settings are unchanged.
66+
67+
---
68+
69+
### Edge Cases
70+
71+
- A rider has never saved settings before: the page loads with empty values or agreed defaults rather than another rider's data.
72+
- A rider enters a non-numeric, zero, or negative value for a field that requires a positive amount: the system blocks saving that field value and shows a clear validation message.
73+
- A rider provides a mileage rate with decimals in cents: the system preserves the entered precision supported by the product rather than silently rounding to a misleading value.
74+
- A rider changes the selected location before saving: only the final confirmed location is stored.
75+
- A rider leaves some settings blank because they do not know all values yet: the system saves only the completed valid settings and keeps incomplete optional fields unset.
76+
- A rider opens the settings page without being authenticated: personal settings are not exposed.
77+
78+
## Requirements *(mandatory)*
79+
80+
### Functional Requirements
81+
82+
- **FR-001**: System MUST provide a settings page for authenticated riders.
83+
- **FR-002**: System MUST store settings separately for each rider so one rider can only view and change their own settings.
84+
- **FR-003**: System MUST allow a rider to enter and save an average car mpg value.
85+
- **FR-004**: System MUST allow a rider to enter and save a yearly goal value representing the rider's annual riding target.
86+
- **FR-005**: System MUST allow a rider to enter and save an oil change price value.
87+
- **FR-006**: System MUST allow a rider to enter and save a mileage rate value expressed in cents per mile.
88+
- **FR-007**: System MUST allow a rider to choose a location and store the resulting latitude and longitude for that rider.
89+
- **FR-008**: System MUST load a rider's existing saved settings when the rider opens the settings page.
90+
- **FR-009**: System MUST require an explicit save action before changed settings are persisted.
91+
- **FR-010**: System MUST validate each entered value before saving and prevent invalid values from being persisted.
92+
- **FR-011**: System MUST show which field values failed validation in language a non-technical rider can understand.
93+
- **FR-012**: System MUST preserve previously saved valid settings when a rider updates only a subset of fields.
94+
- **FR-013**: System MUST support leaving individual settings unset when a rider has not provided a value for that field.
95+
- **FR-014**: System MUST not expose personal settings to unauthenticated users.
96+
97+
### Key Entities *(include if feature involves data)*
98+
99+
- **User Settings Profile**: A rider-owned collection of personal settings including average car mpg, yearly goal, oil change price, mileage rate, and an optional saved location.
100+
- **Location Preference**: A saved rider location represented by a selected place and its latitude and longitude coordinates.
101+
- **Settings Field Value**: An individual user-provided value within the settings profile that can be saved, updated, validated, or left unset.
102+
103+
## Success Criteria *(mandatory)*
104+
105+
### Measurable Outcomes
106+
107+
- **SC-001**: At least 90% of authenticated riders can complete their first-time settings entry in under 2 minutes.
108+
- **SC-002**: At least 95% of valid settings submissions succeed on the rider's first save attempt.
109+
- **SC-003**: 100% of saved settings remain isolated to the rider who created or updated them.
110+
- **SC-004**: At least 90% of riders who revisit the settings page can update a single field without re-entering unchanged values.
111+
112+
## Assumptions
113+
114+
- The settings page is available only after a rider has authenticated.
115+
- The yearly goal is measured in the same ride-distance unit already used elsewhere in the product.
116+
- Average car mpg, yearly goal, oil change price, and mileage rate are user-editable numeric values that must be positive when provided.
117+
- A rider may save a partial settings profile if some requested values are still unknown.
118+
- The saved location represents one rider-selected reference point at a time.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Specification Quality Checklist: Per-User Settings Page
2+
3+
**Purpose**: Validate specification completeness and quality before proceeding to planning
4+
**Created**: 2026-03-30
5+
**Feature**: [spec.md](../spec.md)
6+
7+
## Content Quality
8+
9+
- [x] No implementation details (languages, frameworks, APIs)
10+
- [x] Focused on user value and business needs
11+
- [x] Written for non-technical stakeholders
12+
- [x] All mandatory sections completed
13+
14+
## Requirement Completeness
15+
16+
- [x] No [NEEDS CLARIFICATION] markers remain
17+
- [x] Requirements are testable and unambiguous
18+
- [x] Success criteria are measurable
19+
- [x] Success criteria are technology-agnostic (no implementation details)
20+
- [x] All acceptance scenarios are defined
21+
- [x] Edge cases are identified
22+
- [x] Scope is clearly bounded
23+
- [x] Dependencies and assumptions identified
24+
25+
## Feature Readiness
26+
27+
- [x] All functional requirements have clear acceptance criteria
28+
- [x] User scenarios cover primary flows
29+
- [x] Feature meets measurable outcomes defined in Success Criteria
30+
- [x] No implementation details leak into specification
31+
32+
## Notes
33+
34+
- Validation pass completed on 2026-03-30; no blocking issues found.
35+
- Spec is ready for `/speckit.plan`.
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
openapi: 3.0.3
2+
info:
3+
title: BikeTracking User Settings API
4+
version: 1.0.0
5+
description: Authenticated rider-scoped settings retrieval and save contract.
6+
7+
paths:
8+
/api/users/me/settings:
9+
get:
10+
summary: Get per-user settings for the authenticated rider
11+
operationId: getUserSettings
12+
responses:
13+
'200':
14+
description: Settings resolved
15+
content:
16+
application/json:
17+
schema:
18+
$ref: '#/components/schemas/UserSettingsResponse'
19+
'401':
20+
description: Unauthorized
21+
content:
22+
application/json:
23+
schema:
24+
$ref: '#/components/schemas/ErrorResponse'
25+
put:
26+
summary: Save per-user settings for the authenticated rider
27+
operationId: saveUserSettings
28+
requestBody:
29+
required: true
30+
content:
31+
application/json:
32+
schema:
33+
$ref: '#/components/schemas/UserSettingsUpsertRequest'
34+
responses:
35+
'200':
36+
description: Settings saved
37+
content:
38+
application/json:
39+
schema:
40+
$ref: '#/components/schemas/UserSettingsResponse'
41+
'400':
42+
description: Validation failed
43+
content:
44+
application/json:
45+
schema:
46+
$ref: '#/components/schemas/ErrorResponse'
47+
'401':
48+
description: Unauthorized
49+
content:
50+
application/json:
51+
schema:
52+
$ref: '#/components/schemas/ErrorResponse'
53+
54+
components:
55+
schemas:
56+
UserSettingsUpsertRequest:
57+
type: object
58+
properties:
59+
averageCarMpg:
60+
type: number
61+
nullable: true
62+
exclusiveMinimum: 0
63+
yearlyGoalMiles:
64+
type: number
65+
nullable: true
66+
exclusiveMinimum: 0
67+
oilChangePrice:
68+
type: number
69+
nullable: true
70+
exclusiveMinimum: 0
71+
mileageRateCents:
72+
type: number
73+
nullable: true
74+
exclusiveMinimum: 0
75+
description: Rate value expressed in cents per mile.
76+
locationLabel:
77+
type: string
78+
nullable: true
79+
maxLength: 200
80+
latitude:
81+
type: number
82+
nullable: true
83+
minimum: -90
84+
maximum: 90
85+
longitude:
86+
type: number
87+
nullable: true
88+
minimum: -180
89+
maximum: 180
90+
91+
UserSettingsView:
92+
type: object
93+
required:
94+
- averageCarMpg
95+
- yearlyGoalMiles
96+
- oilChangePrice
97+
- mileageRateCents
98+
- locationLabel
99+
- latitude
100+
- longitude
101+
- updatedAtUtc
102+
properties:
103+
averageCarMpg:
104+
type: number
105+
nullable: true
106+
yearlyGoalMiles:
107+
type: number
108+
nullable: true
109+
oilChangePrice:
110+
type: number
111+
nullable: true
112+
mileageRateCents:
113+
type: number
114+
nullable: true
115+
locationLabel:
116+
type: string
117+
nullable: true
118+
latitude:
119+
type: number
120+
nullable: true
121+
longitude:
122+
type: number
123+
nullable: true
124+
updatedAtUtc:
125+
type: string
126+
format: date-time
127+
128+
UserSettingsResponse:
129+
type: object
130+
required:
131+
- hasSettings
132+
- settings
133+
properties:
134+
hasSettings:
135+
type: boolean
136+
settings:
137+
$ref: '#/components/schemas/UserSettingsView'
138+
139+
ErrorResponse:
140+
type: object
141+
required:
142+
- code
143+
- message
144+
properties:
145+
code:
146+
type: string
147+
message:
148+
type: string
149+
details:
150+
type: array
151+
items:
152+
type: string

0 commit comments

Comments
 (0)