docs: update README with features and design notes; add NEXT_STEPS
README now covers features list, run instructions, design rationale (integer money/duration, read-time cost resolution, soft budget enforcement, Flyway-only schema, API shape). NEXT_STEPS.md catalogs deferred work: user CRUD UI, rate snapshots, notes field, CSV export, auth, pagination, Playwright e2e, i18n, dark mode, bookmarkable URLs, full backend test pyramid. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Next Steps
|
||||
|
||||
Items that were out of scope for the initial 6-hour build, with notes on how to approach each.
|
||||
|
||||
## Features
|
||||
|
||||
### User management UI
|
||||
Currently, users are seeded via Flyway (`V2__seed_demo_data.sql`). A `POST /api/users` endpoint
|
||||
with a "New User" form in the frontend would complete the CRUD cycle. Straightforward to add
|
||||
following the same pattern as project creation.
|
||||
|
||||
### Edit existing time entry (project-create form was shipped; entry edit is partially done)
|
||||
The backend `PUT /api/time-entries/{id}` endpoint exists. The frontend `TimeEntryForm` handles
|
||||
editing when `editEntry` is passed. Wire up the Edit button per entry row in `WeeklyView` —
|
||||
already scaffolded, just needs end-to-end smoke-testing.
|
||||
|
||||
### Notes / description field on time entries
|
||||
Add a `TEXT` column to `time_entries` (new Flyway migration), expose it in the DTOs, and add a
|
||||
textarea to `TimeEntryForm`. Straightforward schema change.
|
||||
|
||||
### Rate history — audit-stable costs
|
||||
Currently, cost is computed at read time from the current project/user hourly rate. If a rate
|
||||
changes, historical costs change retroactively. To fix: add `hourly_rate_cents_snapshot INTEGER NOT NULL`
|
||||
to `time_entries`, resolve and snapshot the rate in `TimeEntryService.create()`. Historical queries
|
||||
then use the snapshot instead of joining to current rates.
|
||||
|
||||
### CSV export of reports
|
||||
Add a `GET /api/reports/weekly.csv?userId=&week=` and `/monthly.csv` endpoint that streams
|
||||
`text/csv`. Frontend adds a "Download CSV" button that opens the URL in a new tab.
|
||||
|
||||
## Technical quality
|
||||
|
||||
### Full backend test pyramid
|
||||
The current happy-path tests cover the repository date-range query, service cost/budget logic, and
|
||||
one end-to-end MockMvc flow. Gaps to fill:
|
||||
- `@WebMvcTest` controller-slice tests for validation error responses (400 on invalid fields).
|
||||
- More `@DataJpaTest` cases (zero entries, multiple users, rate fallback).
|
||||
- `@SpringBootTest` with Testcontainers so tests do not depend on an externally-running PostgreSQL.
|
||||
|
||||
### Frontend end-to-end tests (Playwright)
|
||||
A Playwright suite covering the golden paths:
|
||||
1. Log a time entry → verify it appears in the weekly view.
|
||||
2. Create a project → verify it appears in the project list.
|
||||
3. Exceed a project budget → verify the budget banner appears.
|
||||
|
||||
### Pagination of time entries
|
||||
`GET /api/time-entries` returns all entries in a date range. For large datasets, add Spring Data
|
||||
pagination (`Pageable` parameter) and a "Load more" button or cursor in the frontend.
|
||||
|
||||
## UX improvements
|
||||
|
||||
### Delete confirmation modal
|
||||
Currently `confirm()` is used for delete. Replace with a small Tailwind dialog / Headless UI
|
||||
`Dialog` for a consistent UX.
|
||||
|
||||
### Bookmarkable week/month URLs
|
||||
Weekly and monthly views use component state for the selected period. Moving the period to the
|
||||
URL (e.g., `/weekly/2026-W20`, `/monthly/2026-05`) enables bookmarking and browser back/forward.
|
||||
React Router v7 `useParams` + `useNavigate` is the implementation path.
|
||||
|
||||
### Validation error UI polish
|
||||
Form errors are shown as a banner above the form. Inline per-field errors
|
||||
(below each input) would be more discoverable.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Authentication & per-user data isolation
|
||||
No auth in the current build — user is selected via a dropdown. For production, add Spring
|
||||
Security with JWT or session-based auth. The `user_id` on `time_entries` already supports
|
||||
per-user isolation; the API just needs to enforce it from the authenticated principal.
|
||||
|
||||
### Per-project currency
|
||||
Add `currency CHAR(3) NOT NULL DEFAULT 'EUR'` to `projects`. The aggregation queries then need
|
||||
currency-aware math; cross-currency totals on the monthly report would require a conversion rate
|
||||
or report per-currency totals separately.
|
||||
|
||||
### Time zone awareness
|
||||
`time_entries.entry_date` is a `LocalDate` (no zone). If users span time zones, "today" must
|
||||
be resolved from the user's local zone rather than the server's. Pass a `timeZone` parameter or
|
||||
derive it from the authenticated user's profile.
|
||||
|
||||
### Dark mode
|
||||
Tailwind v4 supports `prefers-color-scheme` media queries via the `dark:` variant. Add
|
||||
`@media (prefers-color-scheme: dark)` styles or a toggle stored in `localStorage`.
|
||||
|
||||
### i18n (de/en)
|
||||
Hardcoded strings are in English; currency formatting uses German locale (`de-DE`). Introduce
|
||||
`react-intl` or a similar library and extract string constants. Language preference lives in user
|
||||
settings or `Accept-Language`.
|
||||
|
||||
### Performance
|
||||
- N+1 in `ProjectService.findAll()`: one aggregate query for all projects avoids it (already done
|
||||
via `aggregateAllByProject`). No further action needed at small scale.
|
||||
- Large datasets: consider materialized views or a dedicated reporting aggregate table updated
|
||||
via a database trigger or scheduled job.
|
||||
Reference in New Issue
Block a user