Skip to content

Commit a2f27ff

Browse files
author
aligneddev
committed
frontend from Aurelia to React
1 parent 8a97cf5 commit a2f27ff

11 files changed

Lines changed: 388 additions & 282 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Commute Bike Tracker
22

3-
Local-first Bike Tracking application built with .NET Aspire orchestration, .NET 10 Minimal API, F# domain modules, and an Aurelia 2 frontend.
3+
Local-first Bike Tracking application built with .NET Aspire orchestration, .NET 10 Minimal API, F# domain modules, and a React frontend.
44

55
## Current Feature Slice
66

@@ -16,7 +16,7 @@ Local-first Bike Tracking application built with .NET Aspire orchestration, .NET
1616
- src/BikeTracking.Api - Minimal API service
1717
- src/BikeTracking.ServiceDefaults - Shared Aspire defaults and telemetry wiring
1818
- src/BikeTracking.Domain.FSharp - Domain event and type modules (F#)
19-
- src/BikeTracking.Frontend - Aurelia 2 frontend app
19+
- src/BikeTracking.Frontend - React + Vite frontend app
2020

2121
## Prerequisites
2222

specs/001-user-signup-pin/plan.md

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55

66
## Summary
77

8-
Deliver the first local identity vertical slice: a minimal Aurelia 2 signup/identify flow using name + PIN, local persistence with generated user IDs, secure PIN storage via salted non-reversible hash, progressive delay anti-bruteforce protection, and reliable `UserRegistered` event publication with retry semantics after persistence.
8+
Deliver the first local identity vertical slice: a minimal React signup/identify flow using name + PIN, local persistence with generated user IDs, secure PIN storage via salted non-reversible hash, progressive delay anti-bruteforce protection, and reliable `UserRegistered` event publication with retry semantics after persistence.
99

1010
## Technical Context
1111

12-
**Language/Version**: .NET 10 (C#), F# (domain project), TypeScript 5.x (Aurelia 2 frontend)
13-
**Primary Dependencies**: ASP.NET Core Minimal API, Microsoft Aspire AppHost, Entity Framework Core + SQLite provider, Aurelia 2 + `@aurelia/router`, .NET `System.Security.Cryptography` (PBKDF2), background worker for outbox retry
12+
**Language/Version**: .NET 10 (C#), F# (domain project), TypeScript 5.x (React 19 frontend)
13+
**Primary Dependencies**: ASP.NET Core Minimal API, Microsoft Aspire AppHost, Entity Framework Core + SQLite provider, React 19 + Vite, .NET `System.Security.Cryptography` (PBKDF2), background worker for outbox retry
1414
**Storage**: SQLite local database with EF Core migrations (users, credentials, attempt-state, outbox events)
15-
**Testing**: xUnit integration/unit tests for API/domain, Playwright MCP for end-to-end user journeys, Aurelia component tests for form validation
15+
**Testing**: xUnit integration/unit tests for API/domain, Playwright MCP for end-to-end user journeys, React component tests for form validation
1616
**Target Platform**: Local development on Windows/macOS/Linux; desktop and mobile browsers for UI
1717
**Project Type**: Aspire-orchestrated web application (frontend + API + local database)
1818
**Performance Goals**: API endpoints <500ms p95 under normal local load; identification throttle behavior deterministic; event publication catch-up <5s typical
@@ -31,9 +31,9 @@ Deliver the first local identity vertical slice: a minimal Aurelia 2 signup/iden
3131
| Functional Core / Impure Edge | PASS | Hashing, normalization, and delay calculation remain deterministic functions; DB and event publication isolated at edges. |
3232
| Event Sourcing & CQRS | PASS | `UserRegistered` event is immutable and drives projection/event consumers asynchronously. |
3333
| Quality-First (TDD) | PASS | Test plan will be created in `/speckit.tasks`; implementation remains gated on approved tests. |
34-
| UX Consistency & Accessibility | PASS | Aurelia 2 form flow with accessible labels, keyboard navigation, and clear validation feedback. |
34+
| UX Consistency & Accessibility | PASS | React form flow with accessible labels, keyboard navigation, and clear validation feedback. |
3535
| Performance & Observability | PASS | Response and event-lag targets align with constitution SLOs; service defaults keep telemetry enabled locally. |
36-
| Three-Layer Validation | PASS | Validation planned in Aurelia form, API DTO validation, and DB constraints/indexes. |
36+
| Three-Layer Validation | PASS | Validation planned in React form state, API DTO validation, and DB constraints/indexes. |
3737

3838
**Gate Decision**: PASS. No constitutional violations require exception handling.
3939

@@ -83,13 +83,14 @@ src/
8383
│ └── Library.fs
8484
├── BikeTracking.Frontend/
8585
│ └── src/
86+
│ ├── App.tsx
87+
│ ├── main.tsx
8688
│ ├── pages/
8789
│ │ └── signup/
88-
│ │ ├── signup-page.ts
89-
│ │ └── signup-page.html
90-
│ ├── services/
91-
│ │ └── users-api.ts
92-
│ └── main.ts
90+
│ │ ├── signup-page.tsx
91+
│ │ └── signup-page.css
92+
│ └── services/
93+
│ └── users-api.ts
9394
├── BikeTracking.AppHost/
9495
│ └── AppHost.cs
9596
└── BikeTracking.ServiceDefaults/

specs/001-user-signup-pin/research.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838

3939
## Decision 7: Validation layering mirrors constitution requirements
4040

41-
- Decision: Enforce name and PIN rules in three layers: Aurelia form, API DTO validation, and database constraints/indexes.
41+
- Decision: Enforce name and PIN rules in three layers: React form state, API DTO validation, and database constraints/indexes.
4242
- Rationale: Maintains constitution-mandated defense in depth and prevents invalid data from bypassing a single validation layer.
4343
- Alternatives considered: Client-only validation (rejected for bypass risk), API-only validation (rejected for weaker UX), DB-only validation (rejected for poor request feedback quality).
4444

specs/001-user-signup-pin/tasks.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,16 @@
4949

5050
### Implementation for User Story 1
5151

52-
- [X] T017 [P] [US1] Build signup page view-model with client-side validation state in src/BikeTracking.Frontend/src/pages/signup/signup-page.ts
53-
- [X] T018 [P] [US1] Build accessible signup form markup with field-level validation bindings in src/BikeTracking.Frontend/src/pages/signup/signup-page.html
52+
- [X] T017 [P] [US1] Build signup page React state model with client-side validation in src/BikeTracking.Frontend/src/pages/signup/signup-page.tsx
53+
- [X] T018 [P] [US1] Build accessible signup form JSX with field-level validation bindings in src/BikeTracking.Frontend/src/pages/signup/signup-page.tsx
5454
- [X] T019 [P] [US1] Implement signup API client method in src/BikeTracking.Frontend/src/services/users-api.ts
55-
- [X] T020 [US1] Register signup page bootstrap in src/BikeTracking.Frontend/src/main.ts
55+
- [X] T020 [US1] Register signup page bootstrap in src/BikeTracking.Frontend/src/App.tsx and src/BikeTracking.Frontend/src/main.tsx
5656
- [X] T021 [P] [US1] Define signup request/response DTOs and duplicate-name error code in src/BikeTracking.Api/Contracts/UsersContracts.cs
5757
- [X] T022 [US1] Implement signup application service with normalized-name duplicate check in src/BikeTracking.Api/Application/Users/SignupService.cs
5858
- [X] T023 [US1] Persist User, UserCredential, and AuthAttemptState transactionally in src/BikeTracking.Api/Application/Users/SignupService.cs
5959
- [X] T024 [US1] Queue UserRegistered outbox event during signup transaction in src/BikeTracking.Api/Application/Users/SignupService.cs
6060
- [X] T025 [US1] Implement POST /api/users/signup with 201/400/409 semantics in src/BikeTracking.Api/Endpoints/UsersEndpoints.cs
61-
- [X] T026 [US1] Wire frontend signup submit flow and server error rendering in src/BikeTracking.Frontend/src/pages/signup/signup-page.ts
61+
- [X] T026 [US1] Wire frontend signup submit flow and server error rendering in src/BikeTracking.Frontend/src/pages/signup/signup-page.tsx
6262

6363
**Checkpoint**: User Story 1 is complete and independently testable as the MVP.
6464

@@ -74,13 +74,13 @@
7474

7575
- [X] T027 [P] [US2] Define identify request/response contracts and throttle payload in src/BikeTracking.Api/Contracts/UsersContracts.cs
7676
- [X] T028 [P] [US2] Implement identify API client method with Retry-After handling in src/BikeTracking.Frontend/src/services/users-api.ts
77-
- [X] T029 [P] [US2] Add identify controls and throttle message placeholders in src/BikeTracking.Frontend/src/pages/signup/signup-page.html
77+
- [X] T029 [P] [US2] Add identify controls and throttle message placeholders in src/BikeTracking.Frontend/src/pages/signup/signup-page.tsx
7878
- [X] T030 [US2] Implement normalized-name lookup + PIN verification in src/BikeTracking.Api/Application/Users/IdentifyService.cs
7979
- [X] T031 [US2] Implement progressive delay calculation (1s to 30s cap) in src/BikeTracking.Api/Application/Users/IdentifyService.cs
8080
- [X] T032 [US2] Reset delay progression after successful identification in src/BikeTracking.Api/Application/Users/IdentifyService.cs
8181
- [X] T033 [US2] Implement POST /api/users/identify with 200/401/429 semantics in src/BikeTracking.Api/Endpoints/UsersEndpoints.cs
8282
- [X] T034 [US2] Return Retry-After header for throttled identify responses in src/BikeTracking.Api/Endpoints/UsersEndpoints.cs
83-
- [X] T035 [US2] Wire frontend identify submission, authorized state, and throttle UX in src/BikeTracking.Frontend/src/pages/signup/signup-page.ts
83+
- [X] T035 [US2] Wire frontend identify submission, authorized state, and throttle UX in src/BikeTracking.Frontend/src/pages/signup/signup-page.tsx
8484

8585
**Checkpoint**: User Story 2 is complete and independently testable.
8686

@@ -116,7 +116,7 @@
116116
- [X] T046 Harden API logging to exclude PIN/hash/salt data in src/BikeTracking.Api/Program.cs
117117
- [X] T047 [P] Add outbox worker diagnostics notes to orchestration setup in src/BikeTracking.AppHost/AppHost.cs
118118
- [X] T048 Run quickstart validation steps and record final verification notes in specs/001-user-signup-pin/quickstart.md
119-
- [X] T049 Finalize user-facing copy for validation/duplicate/throttle states in src/BikeTracking.Frontend/src/pages/signup/signup-page.html
119+
- [X] T049 Finalize user-facing copy for validation/duplicate/throttle states in src/BikeTracking.Frontend/src/pages/signup/signup-page.tsx
120120

121121
---
122122

src/BikeTracking.Frontend/eslint.config.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ import tseslint from 'typescript-eslint'
66
import { defineConfig, globalIgnores } from 'eslint/config'
77

88
export default defineConfig([
9-
globalIgnores(['dist']),
9+
globalIgnores([
10+
'dist',
11+
'build',
12+
'coverage',
13+
'node_modules',
14+
'**/*.min.js',
15+
]),
1016
{
1117
files: ['**/*.{ts,tsx}'],
1218
extends: [
Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,4 @@
11
.app-shell {
22
min-height: 100vh;
3-
display: grid;
4-
place-content: center;
5-
text-align: center;
6-
padding: 2rem;
7-
}
8-
9-
.app-shell h1 {
10-
margin: 0 0 0.5rem;
11-
font-size: clamp(1.75rem, 4vw, 2.5rem);
12-
}
13-
14-
.app-shell p {
15-
margin: 0;
16-
color: #334155;
3+
padding: 1rem;
174
}

src/BikeTracking.Frontend/src/App.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import './App.css'
2+
import { SignupPage } from './pages/signup/signup-page'
23

34
function App() {
45
return (
5-
<main className="app-shell">
6+
<div className="app-shell">
67
<h1>Commute Bike Tracker</h1>
7-
<p>React shell is running.</p>
8-
</main>
8+
<SignupPage />
9+
</div>
910
)
1011
}
1112

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
.identity-flow {
2+
max-width: 48rem;
3+
margin: 1.5rem auto;
4+
display: grid;
5+
gap: 1rem;
6+
}
7+
8+
.identity-flow > h1 {
9+
margin: 0;
10+
font-size: clamp(1.75rem, 4vw, 2.4rem);
11+
color: #152238;
12+
}
13+
14+
.intro {
15+
margin: 0;
16+
color: #4b5563;
17+
}
18+
19+
.card {
20+
border: 1px solid #d4dbe5;
21+
border-radius: 0.75rem;
22+
background: #fff;
23+
padding: 1rem;
24+
display: grid;
25+
gap: 0.75rem;
26+
box-shadow: 0 1px 3px rgb(15 23 42 / 8%);
27+
}
28+
29+
.card > h2 {
30+
margin: 0;
31+
font-size: 1.25rem;
32+
color: #1f2937;
33+
}
34+
35+
.card form {
36+
display: grid;
37+
gap: 0.6rem;
38+
}
39+
40+
.card label {
41+
font-weight: 600;
42+
color: #1f2937;
43+
}
44+
45+
.card input {
46+
border: 1px solid #bcc7d6;
47+
border-radius: 0.4rem;
48+
padding: 0.65rem;
49+
font-size: 1rem;
50+
}
51+
52+
.card input:focus {
53+
outline: 2px solid #0a5fd7;
54+
outline-offset: 1px;
55+
}
56+
57+
.card button {
58+
margin-top: 0.25rem;
59+
border: 0;
60+
border-radius: 0.4rem;
61+
padding: 0.7rem 0.95rem;
62+
background: #0b5fd7;
63+
color: #fff;
64+
font-size: 1rem;
65+
font-weight: 600;
66+
cursor: pointer;
67+
}
68+
69+
.card button:disabled {
70+
background: #90a6cb;
71+
cursor: not-allowed;
72+
}
73+
74+
.errors {
75+
margin: 0;
76+
padding: 0.75rem 1rem 0.75rem 1.5rem;
77+
border: 1px solid #f1b9b8;
78+
border-radius: 0.4rem;
79+
background: #fff3f2;
80+
color: #8f1d1c;
81+
}
82+
83+
.success {
84+
margin: 0;
85+
border: 1px solid #9fd7b2;
86+
border-radius: 0.4rem;
87+
background: #ecfaf1;
88+
color: #155a2f;
89+
padding: 0.75rem 1rem;
90+
}
91+
92+
.warning {
93+
margin: 0;
94+
border: 1px solid #f0d39f;
95+
border-radius: 0.4rem;
96+
background: #fff8e9;
97+
color: #8a5a00;
98+
padding: 0.75rem 1rem;
99+
}
100+
101+
@media (width <= 640px) {
102+
.app-shell {
103+
padding: 0.75rem;
104+
}
105+
106+
.identity-flow {
107+
margin-top: 0.75rem;
108+
}
109+
}

src/BikeTracking.Frontend/src/pages/signup/signup-page.html

Lines changed: 0 additions & 116 deletions
This file was deleted.

0 commit comments

Comments
 (0)