Skip to content

Time Tracking

The Time Tracking app provides a full time management solution with a live timer, manual entry logging, project organization, weekly overviews, reporting, and integration with the invoicing system for billable time.

  • Live timer with start, pause, resume, stop, and discard controls
  • Manual time entry with duration input, project/customer assignment, and billable flag
  • Today’s entries view with running totals
  • Weekly overview bar chart (total vs. billable minutes per day)
  • Project management with color coding and hourly rates
  • Customer assignment via invoicing integration
  • Configurable settings (default hourly rate, rounding increment, week start day)
  • Report generation grouped by project, customer, or date
  • Unbilled time summary for invoicing
RoutePurpose
/business/apps/timetrackingDashboard with timer, today stats, weekly chart, and today’s entries
/business/apps/timetracking/entriesFull time entry list with filtering
/business/apps/timetracking/projectsProject management (create, edit, archive)
/business/apps/timetracking/reportsReport generation and export
/business/apps/timetracking/settingsApp configuration

The dashboard is the primary workspace, organized into several sections:

  1. Timer widget (TimerWidget component) — live timer with project and customer selectors; supports start, pause, resume, stop, and discard actions via form submissions
  2. Quick stats — two cards showing today’s total time and this week’s total
  3. Weekly overview — bar chart visualization with each day showing total (light) and billable (dark) bars, scaled relative to the max day
  4. Today’s entries — list rendered via EntryRow components with a “Quick Add” button
  5. Quick nav — four-item grid linking to Entries, Projects, Reports, and Settings

A dialog modal form for manual time entry with fields for:

  • Description
  • Date and duration (custom DurationInput component)
  • Project selector (color-coded options)
  • Customer selector (from invoicing customers)
  • Hourly rate and billable checkbox
TableDescription
ext_timetracking.time_entriesTime entry records (date, duration, project, customer, billable, rate, invoiced)
ext_timetracking.timer_statesActive timer state per user (started_at, elapsed_seconds, is_paused)
ext_timetracking.projectsProjects with color, hourly rate, and billable default
ext_timetracking.settingsPer-user settings (default rate, rounding, week start)
  • TimeEntry — id, user_id, project_id, customer_id, date, start_time, end_time, duration_minutes, description, is_billable, hourly_rate, invoiced, invoice_id
  • TimerState — id, user_id, project_id, customer_id, description, started_at, elapsed_seconds, is_paused
  • Project — id, user_id, customer_id, name, description, color, hourly_rate, is_billable, is_active
  • TimeTrackingSettings — default_hourly_rate, rounding_increment, week_start
  • DaySummary — date, total_minutes, billable_minutes, entries_count
  • ReportRow — group_key, group_label, total_minutes, billable_minutes, billable_amount, entries_count
  • UnbilledSummary — customer_id, customer_name, total_minutes, total_amount, entry_count
ComponentLocation
TimerWidget$lib/apps/timetracking/modules/timer/index.js
EntryRow$lib/apps/timetracking/modules/entries/index.js
DurationInput$lib/apps/timetracking/modules/entries/index.js

Server-side logic lives in $lib/apps/timetracking/services/index.js:

  • getTimerState(userId) — fetch active timer
  • startTimer(userId, opts) / pauseTimer(userId) / resumeTimer(userId) / stopTimer(userId) / discardTimer(userId) — timer lifecycle
  • getEntriesToday(userId) — today’s time entries
  • getWeeklySummary(userId, weekStart) — daily aggregates for the current week
  • getSettings(userId) — user settings
  • listProjects(userId) — project list
  • createEntry(userId, data) — manual entry creation
ActionDescription
start-timerStart the timer with optional project, customer, and description
stop-timerStop the timer and convert to a time entry
pause-timerPause the running timer
resume-timerResume a paused timer
discard-timerDiscard the timer without saving
create-entryManually add a time entry