Commit Graph

93 Commits

Author SHA1 Message Date
5b7b8e47cb ui adaptions 2026-02-23 20:59:01 +01:00
7dd3873148 Merge branch 'main' into feature/soft-delete 2026-02-23 17:59:29 +01:00
850f12e09d Merge pull request 'feature/ios-time-entries-rework' (#2) from feature/ios-time-entries-rework into main
Reviewed-on: #2
2026-02-23 16:58:44 +00:00
74999ce265 Merge pull request 'ios-rebuild' (#3) from ios-rebuild into main
Reviewed-on: #3
2026-02-23 16:57:45 +00:00
0c0fbf42ef updates icons 2026-02-23 17:57:25 +01:00
0d116c8c26 Merge branch 'ios-rebuild' into feature/ios-time-entries-rework 2026-02-23 17:29:21 +01:00
25b7371d08 Merge branch 'main' into ios-rebuild 2026-02-23 17:28:51 +01:00
simon.franken
ddb0926dba Implement soft-delete for client targets and balance corrections
Deleting a target or correction sets deletedAt instead of hard-deleting.
Creating a target for a user+client that has a soft-deleted record
reactivates it (clears deletedAt, applies new weeklyHours/startDate)
rather than failing the unique constraint. All reads filter deletedAt = null
on the target, its corrections, and the parent client.
2026-02-23 15:48:07 +01:00
simon.franken
1b0f5866a1 Restore onDelete: Cascade on Project->Client and TimeEntry->Project
Direct database deletes should still cascade to avoid orphaned records.
The migration now only adds the three deleted_at columns without touching
the existing FK constraints.
2026-02-23 15:32:31 +01:00
simon.franken
159022ef38 Exclude client targets for soft-deleted clients
findAll and findById filter on client.deletedAt = null so targets
belonging to a soft-deleted client are invisible. The create guard
also rejects soft-deleted clients. The raw SQL balance query now
excludes soft-deleted time entries and projects from tracked totals.
2026-02-23 15:24:58 +01:00
simon.franken
1a7d13d5b9 Implement soft-delete for clients, projects, and time entries
Replace hard deletes with deletedAt timestamp flags on all three entities.
Deleting a client or project only sets its own deletedAt; child records are
excluded implicitly by filtering on parent deletedAt in every read query.
Raw SQL statistics queries also filter out soft-deleted parents.
FK ON DELETE CASCADE removed from Project→Client and TimeEntry→Project.
2026-02-23 15:21:13 +01:00
simon.franken
685a311001 Add break time feature to time entries
- Add breakMinutes field to TimeEntry model and database migration
- Users can now add break duration (minutes) to time entries
- Break time is subtracted from total tracked duration
- Validation ensures break time cannot exceed total entry duration
- Statistics and client target balance calculations account for breaks
- Frontend UI includes break time input in TimeEntryFormModal
- Duration displays show break time deduction (e.g., '7h (−1h break)')
- Both project/client statistics and weekly balance calculations updated
2026-02-23 14:39:30 +01:00
d09247d2a5 Merge pull request 'Add Prisma session store for persistent sessions' (#5) from feature/prisma-session-store into main
Reviewed-on: #5
2026-02-23 13:35:21 +00:00
simon.franken
078dc8c304 Add Prisma session store for persistent sessions 2026-02-23 11:39:09 +01:00
simon.franken
59eda58ee6 update agents.md 2026-02-23 10:59:17 +01:00
d56eed8dde Merge pull request 'Add ability to manually adjust the running timer's start time' (#4) from feature/adjust-timer-start-time into main
Reviewed-on: #4
2026-02-23 09:57:23 +00:00
simon.franken
3fa13e1428 Use icon.svg in Navbar and LoginPage instead of Clock icon 2026-02-23 10:55:33 +01:00
simon.franken
2e629d8017 Merge branch 'main' into feature/adjust-timer-start-time 2026-02-23 10:53:54 +01:00
simon.franken
6e0567d021 icon update 2026-02-23 10:53:39 +01:00
simon.franken
3ab39643dd Disable Stop button when no project is selected 2026-02-23 10:47:07 +01:00
simon.franken
e01e5e59df Remove cancel confirmation — discard timer immediately on click 2026-02-23 10:44:34 +01:00
simon.franken
06596dcee9 Add cancel (discard) timer feature
Allows users to discard a running timer without creating a time entry.
A trash icon in the timer widget reveals a confirmation step ('Discard / Keep')
to prevent accidental data loss. Backend exposes a new DELETE /api/timer
endpoint that simply deletes the ongoingTimer row.
2026-02-23 10:41:50 +01:00
simon.franken
7358fa6256 Add ability to manually adjust the running timer's start time
Allows users to retroactively correct the start time of an ongoing timer
without stopping it. A pencil icon in the timer widget opens an inline
time input pre-filled with the current start time; confirming sends the
new time to the backend which validates it is in the past before persisting.
2026-02-23 10:32:38 +01:00
simon.franken
c99bdf56e6 Merge branch 'ios-rebuild' into feature/ios-time-entries-rework 2026-02-23 10:12:12 +01:00
simon.franken
15abfe0511 Merge branch 'main' into ios-rebuild 2026-02-23 10:12:01 +01:00
simon.franken
c9f5bbb25a adds agents md 2026-02-23 10:11:51 +01:00
simon.franken
544b86c948 fix(ios): replace 2001-page TabView with 3-page recycling carousel
Eliminates the eager instantiation of 2001 view bodies by keeping only
three pages (previous, current, next) alive at all times. After each
swipe settles, dayOffset is shifted and tabSelection is silently reset
to the middle page, preserving the native paging animation.
2026-02-23 10:09:51 +01:00
simon.franken
b971569983 feat(ios): replace week strip with native DatePicker and TabView paging 2026-02-23 10:02:24 +01:00
b613fe4edd Replace full-month UICalendarView with compact week strip in time entries 2026-02-21 18:01:02 +01:00
30d5139ad8 update 2026-02-21 14:03:56 +01:00
ef38578596 Fix .accentColor ShapeStyle compile error — use Color.accentColor 2026-02-21 13:57:31 +01:00
ba4765b8a2 Rebuild iOS app: calendar entries, overtime dashboard, settings tab, full CRUD
- Replace 5-tab layout with 4 tabs: Dashboard, Timer, Entries, Settings
- Dashboard: add Work Time Balance section using /client-targets API, showing
  per-client weekly progress bar, overtime/undertime label and expandable week breakdown
- Time Entries: replace flat list with UICalendarView month grid; tap a day to see
  that day's entries; add filter sheet (date range, project, client); new
  TimeEntryDetailSheet for creating and editing entries; duration shown as Xh Ymin
- Settings tab: user info header, navigation to Clients and Projects, logout button
- ClientsListView: list with NavigationLink to ClientDetailView
- ClientDetailView: inline client editing + full work time target CRUD (create,
  edit, delete target; add/delete balance corrections with date, hours, description)
- ProjectsListView: grouped by client, NavigationLink to ProjectDetailView
- ProjectDetailView: edit name, description, colour, client assignment
- Add ClientTarget, WeekBalance, BalanceCorrection models and APIEndpoints for
  /client-targets routes
- Update TimeInterval formatter: add formattedShortDuration (Xh Ymin / Xmin / <1min)
  used throughout app; keep formattedDuration for live timer display
2026-02-21 13:51:41 +01:00
d37170fc5d Disable stop timer button when no project is selected 2026-02-20 18:19:58 +01:00
fc3b7d7c2c adds group 2026-02-20 17:45:32 +01:00
32cb200408 Fix iOS timer widget not displaying active timers
The widget was failing to decode the cached timer data because WidgetTimer
struct didn't match the OngoingTimer JSON structure saved by the app.

Changes:
- Added missing fields (project, createdAt, updatedAt) to WidgetTimer
- Added WidgetProjectReference struct for nested project data
- Fixed project name to use project.name instead of projectId
- Added project color support
- Increased refresh interval from 15 min to 1 min for live updates
2026-02-20 15:57:16 +01:00
e0dd2f1fbc Merge branch 'main' into feature/ios-delete-confirmation 2026-02-20 15:35:02 +01:00
a39f8b07df Add delete confirmation dialogs for clients, projects, and time entries
- Add confirmation alert when deleting clients with warning about
deleted dependencies (projects and time entries)
- Add confirmation alert when deleting projects with warning about
deleted time entries
- Add confirmation alert when deleting time entries
- All alerts include item name and emphasize action cannot be undone
2026-02-20 15:32:40 +01:00
ed8a160a49 update 2026-02-20 15:24:10 +01:00
f42de3353c Fix iOS time display and add timer unit labels
Times were always showing 0 because ISO8601DateFormatter with default
options does not parse fractional seconds, but Prisma/Node.js serialises
dates as "2026-02-20T09:00:00.000Z" (with .000). Every date(from:) call
silently returned nil, so elapsedTime and duration always fell back to 0.

- Date+Extensions: fromISO8601 now tries .withFractionalSeconds first,
  then falls back to whole seconds — single place to maintain
- OngoingTimer.elapsedTime: use Date.fromISO8601() instead of bare formatter
- TimeEntry.duration: use Date.fromISO8601() instead of bare formatters
- TimerView: add TimerUnitLabels view showing h/min/sec column headers
  under the monospaced clock digits
2026-02-20 14:53:30 +01:00
da0cd302bf Fix OIDC web flow redirect URI not being sent to IDP
The /login route was not passing an explicit redirect_uri to the IDP for
the web flow, so openid-client would silently pick a default which could
resolve to localhost:3001 if OIDC_REDIRECT_URI was not set.

- AuthSession.redirectUri is now required (non-optional)
- createAuthSession() requires a redirectUri; detects native vs web via
  the timetracker:// scheme prefix instead of presence/absence of the arg
- /login route resolves the URI explicitly: request param for native
  flows, config.oidc.redirectUri for web flows
- getAuthorizationUrl() reads redirect_uri from session, no longer
  accepts it as a separate argument
- handleCallback() uses session.redirectUri directly, removing the
  fallback to config.oidc.redirectUri
2026-02-20 14:32:23 +01:00
f758aa2fcd Add iOS redirect URI and JWT secret to Helm chart
Add backend.oidc.iosRedirectUri (default: timetracker://oauth/callback) and
backend.jwt.secret to values.yaml and wire them into the backend deployment
as OIDC_IOS_REDIRECT_URI and JWT_SECRET env vars. Update NOTES.txt to surface
both values post-install.
2026-02-20 11:17:18 +01:00
e51dd58a6b Fix remaining ProjectListResponse reference in TimeEntryFormView 2026-02-19 19:07:36 +01:00
39d6ea00d9 Fix iOS list response decoding to match plain-array backend responses
GET /clients and GET /projects return bare arrays, not wrapped objects.
Remove ClientListResponse and ProjectListResponse wrapper structs and
update ClientsViewModel, ProjectsViewModel, and TimerViewModel to decode
[Client] and [Project] directly.
2026-02-19 19:05:43 +01:00
48cd82ab4f Fix token loss: cache JWT in-memory, log keychain errors
Keychain writes silently failed (missing keychain-access-groups entitlement
on simulator), causing the token to disappear between handleTokenResponse
and the first API call. The in-memory cache ensures the token is always
available within the session; the keychain still persists it across launches
when entitlements allow.
2026-02-19 19:00:16 +01:00
062af3b2da Add AuthManager OSLog tracing and fix URL construction in APIEndpoints 2026-02-19 18:58:31 +01:00
1aac76af4a Add detailed logging to auth flow on backend and iOS 2026-02-19 18:55:00 +01:00
f1f60ef685 Pass OIDC_IOS_REDIRECT_URI and JWT_SECRET to backend container 2026-02-19 18:49:32 +01:00
bb2e51cd0a Add JWT_SECRET and OIDC iOS redirect vars to env template 2026-02-19 18:47:19 +01:00
946cd35832 Replace IDP token passthrough with backend-issued JWT for iOS auth
iOS clients now exchange the OIDC authorization code for a backend-signed
HS256 JWT via POST /auth/token. All subsequent API requests authenticate
using this JWT as a Bearer token, verified locally — no per-request IDP
call is needed. Web frontend session-cookie auth is unchanged.
2026-02-19 18:45:03 +01:00
1ca76b0fec fix 2026-02-18 22:58:41 +01:00