121 lines
5.2 KiB
Markdown
121 lines
5.2 KiB
Markdown
# 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.
|
||
|
||
```bash
|
||
# 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:
|
||
|
||
```bash
|
||
# 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:
|
||
|
||
```bash
|
||
docker compose -f docker-compose.full.yml up --build
|
||
```
|
||
|
||
- App: http://localhost:8080
|
||
- API: http://localhost:8080/api
|
||
- Database: postgres://app:app@localhost:5432/app_dev
|
||
|
||
## Verify everything
|
||
|
||
```bash
|
||
mise run check # format-check + lint + test (both stacks)
|
||
```
|
||
|
||
Without mise:
|
||
|
||
```bash
|
||
# 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`.
|