1aea91da55
The deployment was unreachable because the Next.js server was binding to localhost:3000 (127.0.0.1) instead of 0.0.0.0, making it only accessible inside the Docker container. - Added HOSTNAME=0.0.0.0 to Dockerfile build and runtime stages - Added HOSTNAME=0.0.0.0 to docker-compose.yml for nextjs service This allows the server to accept connections from external hosts.
3.4 KiB
3.4 KiB
Context
Currently, the frontend displays raw UUIDs for user references:
- Task list shows
assigneeId(e.g., "a1b2c3d4-e5f6...") or "Unassigned" - Task detail shows
assigneeIdandcreatedById - Shift detail shows
memberIdfor each signup
The backend already stores DisplayName in the Member entity but the API DTOs don't expose it. The ShiftService already demonstrates the pattern of joining with Members (lines 82-87), which we can replicate for Tasks.
Goals / Non-Goals
Goals:
- Add member name fields to backend DTOs
- Update TaskService to query and include member names
- Update ShiftService to include member name in ShiftSignupDto
- Update frontend TypeScript interfaces
- Replace UUID displays with names in task/shift UIs
Non-Goals:
- No database schema changes
- No changes to authentication or authorization
- No changes to how tasks/shifts are created or updated
- No caching layer for member names
Decisions
1. Add names to existing DTOs vs create new DTOs
Decision: Add optional fields to existing DTOs
Rationale:
- Keeps API surface simple
- Backward compatible - existing clients ignore new fields
- No breaking changes to existing integrations
Alternative considered: Create new DTO versions (e.g., TaskDetailDtoV2)
- Rejected: Unnecessary complexity for a simple additive change
2. Fetch member names via JOIN vs separate query
Decision: Use JOIN in TaskService methods
Rationale:
- More efficient - single query per endpoint
- Pattern already exists in ShiftService
- Avoids N+1 query problem
Alternative considered: Query members separately and build lookup dictionary
- Rejected: Adds complexity and extra database round-trips
3. Handle missing members (orphaned IDs)
Decision: Return null for name when member not found
Rationale:
- Data integrity issue should surface visibly
- Frontend can display fallback like "Unknown" or keep showing ID
- Logging can track data inconsistencies
4. Frontend handling of null names
Decision: Frontend shows fallback text when name is null
Implementation:
// Task list
task.assigneeName || 'Unassigned'
// Task detail
task.assigneeName || 'Unassigned'
task.createdByName || 'Unknown'
// Shift signups
signup.memberName || 'Unknown Member'
Risks / Trade-offs
| Risk | Mitigation |
|---|---|
| JOIN adds query complexity | Keep JOINs simple, only on indexed columns (Member.Id) |
| Larger API response payloads | Minimal impact - names are small strings |
| Member names become stale | Acceptable - names rarely change; eventual consistency |
| Database performance degradation | Monitor query execution plans; add caching if needed |
| Partial data on member deletion | Show "Unknown" fallback; log orphaned references |
Migration Plan
- Backend DTO changes - Add new optional fields
- Backend service changes - Update queries to include names
- Frontend type updates - Add name fields to interfaces
- Frontend UI updates - Replace ID displays with names
Rollback:
- DTO changes are backward compatible
- Frontend can revert to showing IDs by changing display logic
- No database changes required
Open Questions
- Should we include
externalUserIdin the signup display? (Currently available in ShiftSignupDto) - Do we need to include member email for any display purposes?
- Should we add name fields to shift list items (showing creator name)?