111 Commits

Author SHA1 Message Date
ca521000bf Merge pull request 'feature/mcp-and-api-keys' (#11) from feature/mcp-and-api-keys into main
Reviewed-on: #11
latest
2026-03-16 16:46:26 +00:00
simon.franken
a7ab55932f fix: review fixes for MCP and API key feature
- Remove spurious ALTER TABLE client_targets DROP DEFAULT from migration
  (Prisma schema drift side-effect unrelated to this PR)
- Surface revoke errors in ApiKeysPage UI via deleteApiKey.isError
- Fix UpdateProjectInput.color type to allow null, removing unsafe cast
  in the update_project MCP tool handler
2026-03-16 15:35:06 +01:00
simon.franken
64211e6a49 feat: add MCP endpoint and API key management
- Add ApiKey Prisma model (SHA-256 hash, prefix, lastUsedAt) with migration
- Implement ApiKeyService (create, list, delete, verify)
- Extend requireAuth middleware to accept sk_-prefixed API keys alongside JWTs
- Add GET/POST /api-keys routes for creating and revoking keys
- Add stateless Streamable HTTP MCP server at POST/GET /mcp exposing all 20
  time-tracking tools (clients, projects, time entries, timer, statistics,
  client targets and corrections)
- Frontend: ApiKey types, apiKeys API module, useApiKeys hook
- Frontend: ApiKeysPage with key table, one-time raw-key reveal modal, and
  inline revoke confirmation
- Wire /api-keys route and add API Keys link to Management dropdown in Navbar
2026-03-16 15:26:09 +01:00
cd03d8751e fix: timer widget blocks dialogs 2026-03-13 17:08:21 +00:00
1964f76f74 fix: add bg-gray-50 back to Layout 2026-03-13 17:07:32 +00:00
1f4e12298e fix 2026-03-13 17:46:53 +01:00
simon.franken
1049410fee adaption 2026-03-09 11:20:53 +01:00
c9bd0abf18 feat: include ongoing timer in today's tracked time on Dashboard
The 'Today' stat card now adds the running timer's elapsed seconds to
the total, so the displayed duration ticks up live alongside the timer
widget. The timer is only counted when it started today (timers carried
over from the previous day are excluded).

A pulsing green indicator dot is shown on the stat card value while the
timer is active, consistent with the balance widget treatment. The dot
is implemented via a new optional 'indicator' prop on StatCard so it
can be reused elsewhere without changing existing call sites.
2026-03-09 11:14:21 +01:00
7ec76e3e8e feat: include ongoing timer in balance calculation
The balance now accounts for any active timer whose project belongs to
the tracked client. computeBalance() fetches the user's OngoingTimer,
computes its elapsed seconds, and adds them to the matching period's
tracked seconds before running the balance formula — so both
currentPeriodTrackedSeconds and totalBalanceSeconds reflect the live
timer without requiring a schema change.

On the frontend, useClientTargets polls every 30 s while a timer is
running, and a pulsing green dot is shown next to the balance figure on
the Dashboard and Clients pages to signal the live contribution.
2026-03-09 10:59:39 +01:00
784e71e187 fix: exclude soft-deleted entries from overlap conflict check 2026-03-05 12:18:48 +01:00
7677fdd73d revert 2026-02-24 21:57:21 +01:00
924b83eb4d fix: replace type=time with separate hours/minutes number inputs in correction form
type="time" renders a clock-time picker (with AM/PM), not a duration input.
Switch to two type="number" fields (h / m) so the intent is unambiguous.
2026-02-24 21:53:21 +01:00
91d13b19db fix: replace separate h/m number inputs with single HH:MM time input in correction form
- Remove stale corrHoursInt/corrMins state (leftover from previous refactor)
- Use corrDuration (HH:MM string) parsed once and reuse totalHours in submit handler
- Single type="time" input + +/− toggle button matches TimerWidget style
- flex-1 on Date and Duration columns for equal width and consistent height alignment
2026-02-24 21:49:54 +01:00
2a5e6d4a22 fix: display correction amounts as h/m and replace decimal input with h:m fields
- Correction list now shows '13h 32m' instead of '13.65h', using
  formatDurationHoursMinutes (same formatter used everywhere else)
- Sign shown as '−' (minus) for negative corrections instead of bare '-'
- Correction input replaced with separate hours + minutes integer fields
  and a +/− toggle button, removing the awkward decimal entry
2026-02-24 21:44:54 +01:00
b7bd875462 Merge pull request 'feat: implement client targets v2 (weekly/monthly periods, working days, pro-ration)' (#8) from client-targets-v2 into main
Reviewed-on: #8
2026-02-24 20:29:22 +00:00
a58dfcfa4a fix: clamp ongoing-period corrections to today to prevent future corrections inflating balance
A correction dated in the future (within the current period) was being
added to the balance immediately, while the corresponding expected hours
were not yet counted (elapsed working days only go up to today).

Fix: in the ongoing-period branch, sum only corrections whose date is
<= today, matching the same window used for elapsed working days and
tracked time.
2026-02-24 21:27:03 +01:00
7101f38bc8 feat: implement client targets v2 (weekly/monthly periods, working days, pro-ration)
- Add PeriodType enum and working_days column to ClientTarget schema
- Rename weekly_hours -> target_hours; remove Monday-only constraint
- Add migration 20260224000000_client_targets_v2
- Rewrite computeBalance() to support weekly/monthly periods, per-spec
  pro-ration for first period, ongoing vs completed period logic, and
  elapsed working-day counting (§4–§6 of requirements doc)
- Update Zod schemas and TypeScript input types for new fields
- Frontend: replace WeekBalance with PeriodBalance; update
  ClientTargetWithBalance to currentPeriod* fields
- ClientTargetPanel: period type radio, working-day toggles, free date
  picker, dynamic hours label
- DashboardPage: rename widget to Targets, dynamic This week/This month
  label
2026-02-24 19:02:32 +01:00
3850e2db06 docs: add client targets v2 feature requirements 2026-02-24 18:50:34 +01:00
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