Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/).

## [Unreleased]

## [0.2.0]

### Added
- Pausable timers: multiple timer sessions can stay open at once, with exactly
one running and the rest on hold.
- Pause / resume controls per timer, plus an **On hold** section on the
dashboard.

### Changed
- Starting or resuming a timer now puts the currently running timer **on hold**
(paused) instead of stopping it, so switching projects keeps prior sessions
open. Starting a project that already has an open session resumes it rather
than creating a duplicate.
- `TimeEntry` now tracks worked time across run/pause segments via new fields
`status`, `accumulated_minutes` and `segment_started_at`; `duration_minutes`
is the worked total and excludes paused gaps.

## [0.1.0] - Initial release

### Added
Expand All @@ -24,5 +41,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
- Test suite covering models, auth gating, timer flow, redirect safety, and
report generation.

[Unreleased]: https://github.com/c4pt4in/timetracker/compare/v0.1.0...HEAD
[Unreleased]: https://github.com/c4pt4in/timetracker/compare/v0.2.0...HEAD
[0.2.0]: https://github.com/c4pt4in/timetracker/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/c4pt4in/timetracker/releases/tag/v0.1.0
36 changes: 24 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@ up` away from running.
marker and an optional hourly rate.
- **Manual time entries** — pick a date, start and end time; duration is
computed automatically.
- **Live timer** — one-click start/stop on the dashboard, with a live JS counter
in the navbar. Only one timer runs at a time; starting a new one stops the
previous.
- **Live timer with pause/hold** — start a timer on any project from the
dashboard, with a live JS counter. Only one timer runs at a time; starting or
resuming another automatically puts the running one **on hold** instead of
stopping it, so you can switch between projects with a single click and resume
later. Each timer has pause / resume / stop controls, and worked time is
tracked across segments (paused gaps are excluded).
- **Dashboard** — today / this week / this month totals per project, plus the
most recent entries.
- **PDF report** — generated server-side with WeasyPrint. Filter by date range
Expand Down Expand Up @@ -98,9 +101,12 @@ full list of variables; the most important ones:
### Live timer

From the dashboard, click **Start Timer** on any project card. The timer ticks
live in the navbar; click **Stop & Save** to write the entry, or **Discard** to
throw it away. Starting a timer on a different project automatically stops the
running one.
live; use **Pause** to put it on hold (it stops counting but stays open),
**Resume** to continue, **Stop & Save** to write the entry, or **Discard** to
throw it away. Starting or resuming a timer on another project automatically
puts the currently running one on hold, so you can hop between projects with a
single click. Held timers are listed in an **On hold** section on the
dashboard; only one timer runs at a time.

### Manual entry

Expand Down Expand Up @@ -206,12 +212,18 @@ flow, redirect safety, and PDF/CSV report generation.

- **Project**: `name` (unique), `description`, `color` (validated hex),
`hourly_rate` (optional), `is_archived`, `created_at`
- **TimeEntry**: `project` (FK, CASCADE), `date`, `start_time`, `end_time`,
`duration_minutes` (auto-calculated when both timestamps set),
`description`, `created_at`

A running live timer is simply a `TimeEntry` with `start_time` set and
`end_time = NULL`.
- **TimeEntry**: `project` (FK, CASCADE), `date`, `start_time` (first start),
`end_time` (final stop), `status` (`running` / `paused` / `completed`),
`accumulated_minutes` (worked time from completed segments),
`segment_started_at` (start of the live segment; `NULL` while paused),
`duration_minutes` (worked total, excludes paused gaps), `description`,
`created_at`

An open timer is a `TimeEntry` with `end_time = NULL` and a `status` of
`running` or `paused`. While running, worked time is `accumulated_minutes` plus
the live segment since `segment_started_at`; pausing banks the live segment
into `accumulated_minutes`. Stopping writes the worked total into
`duration_minutes`. At most one entry is `running` at a time.

## Troubleshooting

Expand Down
Loading