Files
qavion-time-tracker-assessment/README.md
T
2026-05-21 16:59:30 +02:00

5.2 KiB
Raw Blame History

Time Tracker

A browser-based time-tracking app: log daily work against projects, review totals in weekly and monthly views, and track project budgets with automatic cost calculation and soft breach warnings.

Stack: React 19 + Vite 6 (TypeScript strict) — Spring Boot 3.4 (Java 21) — PostgreSQL 17 via Docker Compose — Flyway for schema migrations — Tailwind CSS v4 — Biome 1.9 — Vitest.

AI disclosure: Code in this application was written with the help of AI agents. Architecture decisions were still driven by the creator of this project, with agent engineering used to steer implementation.

Features

  • Daily time entries — date, project, duration (entered as h:mm), automatic cost from hourly rate; entries can be created, edited, and deleted
  • Weekly view — navigate by ISO week; see total hours per day, individual entries, and a running week total
  • Monthly view — per-project summary with time and cost progress bars; red banner when a budget is exceeded
  • Project management — create and edit projects with time and cost budgets; set a project-level hourly rate or fall back to the user's default
  • Multi-user — pick any seeded user from the dropdown and edit that user's name/default rate; cost is calculated using that user's rate when no project rate is set
  • Soft budget enforcement — entries always save; over-budget projects are highlighted with a warning banner and colored bars

Quick start

Requires a full Java 21 JDK (not just a JRE) for Maven compilation. mise install below handles this and sets JAVA_HOME when commands are run through mise. Without mise: sudo apt install openjdk-21-jdk, then ensure java -version reports 21 and JAVA_HOME points at that JDK.

# 1. Pin toolchain — installs Java 21 JDK, Node 22, Maven, lefthook, gitleaks
mise install

# 2. Install deps, git hooks, .env, and validate Java + Maven wrapper
mise run setup

# 3. Start the database
docker compose up -d

Open two terminals:

# Backend → http://localhost:8080
mise run backend

# Frontend → http://localhost:5173  (proxies /api → :8080)
mise run frontend

If you have activated mise in your shell, the direct commands also work: backend/mvnw -f backend/pom.xml spring-boot:run and cd frontend && npm run dev.

Docker (all-in-one app + database)

Build and run the bundled app container plus PostgreSQL:

docker compose -f docker-compose.full.yml up --build

Verify everything

mise run check       # format-check + lint + test (both stacks)

Without mise:

# one-time setup
sudo apt install openjdk-21-jdk docker-compose-plugin
# Install Node 22 with your preferred Node version manager or distro-specific package.
export JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64  # adjust if your JDK is elsewhere
npm --prefix frontend install
cp -n .env.example .env
backend/mvnw -f backend/pom.xml -v                 # primes the Maven wrapper cache

# checks
backend/mvnw -f backend/pom.xml spotless:check -q
cd frontend && npx biome check src
backend/mvnw -f backend/pom.xml test -q
cd frontend && npx vitest run

Design notes

Money and duration are stored as integers (cents and minutes respectively) to avoid floating-point drift. Cost for a time entry is computed at read time: duration_minutes × effective_rate_cents / 60, where the effective rate is the project's hourly_rate_cents if set, otherwise the user's default_hourly_rate_cents. This means changing a rate retroactively updates all historical cost totals — a deliberate trade-off for simplicity (see NEXT_STEPS.md for a snapshot-based alternative).

Budget warnings are soft: any entry saves regardless of budget status. Breach is detected in the reporting layer by comparing aggregated totals to the project's time_budget_minutes and cost_budget_cents. The monthly view renders a red warning banner and saturated progress bars for any over-budget project.

Schema migrations are managed exclusively by Flyway (V1__init.sql for schema, V2__seed_demo_data.sql for demo users and projects). Hibernate is set to validate — it never modifies the schema.

API shape — aggregation is done server-side via two dedicated endpoints: GET /api/reports/weekly?userId=&week=YYYY-Www and GET /api/reports/monthly?userId=&month=YYYY-MM. Resource endpoints live under /api/: users can be listed and updated, projects can be listed, created, and updated, and time entries can be listed by date range, created, updated, and deleted.

Environment

.env.example documents all env vars. mise run setup copies it to .env automatically on first run.

Troubleshooting

  • backend/mvnw: ... exec: .../apache-maven-3.9.9/bin/mvn: not found — run mise run setup again. The setup task primes the Maven wrapper cache. If it still fails, remove the broken cache with rm -rf ~/.m2/wrapper/dists/apache-maven-3.9.9* and rerun mise run setup.
  • JAVA_HOME environment variable is not defined correctly — install a Java 21 JDK and set JAVA_HOME, or use the mise tasks (mise run backend, mise run check) after mise install.