# Contributor Guide

Single-page overview for contributors: architecture, local dev, testing, how to add routes/services/templates, and versioning. For full guidelines see [CONTRIBUTING.md](CONTRIBUTING.md); for structure see [Project Structure](PROJECT_STRUCTURE.md).

---

## Repo architecture

- **Stack**: Flask app (server-rendered HTML + REST API), optional SocketIO/scheduler, Docker + Nginx + PostgreSQL.
- **Layers**: Routes (`app/routes/`) → Services (`app/services/`) → Repositories (`app/repositories/`) / Models (`app/models/`). API under `/api/v1/`.
- **Blueprint registration**: All route blueprints are registered in `app/blueprint_registry.py` (single place). Use the main registration list for required modules; optional feature blueprints go in `_register_optional_blueprints`—failures are logged with a full traceback, and the process re-raises in **development** only so optional routes are not silently missing locally.

```mermaid
flowchart LR
  Routes[routes/] --> Services[services/]
  Services --> Repos[repositories/]
  Repos --> Models[models/]
  Models --> DB[(DB)]
```

**More**: [ARCHITECTURE.md](../ARCHITECTURE.md) · [Project Structure](PROJECT_STRUCTURE.md)

---

## Local dev workflow

1. **Clone** the repo and `cd TimeTracker`.
2. **Venv**: `python -m venv venv` then activate (`venv\Scripts\activate` on Windows, `source venv/bin/activate` on Linux/macOS).
3. **Deps**: `pip install -r requirements.txt`; for tests also `pip install -r requirements-test.txt`.
4. **Env**: `cp env.example .env` and set at least `SECRET_KEY` (e.g. `python -c "import secrets; print(secrets.token_hex(32))"`).
5. **DB**: `flask db upgrade`.
6. **Run**: `flask run` → http://127.0.0.1:5000.

**Docker (no local Python)**:
- **SQLite (quick test)**: `docker-compose -f docker/docker-compose.local-test.yml up --build` → http://localhost:8080.
- **Default (HTTPS)**: `docker-compose up -d` → https://localhost (self-signed cert).
- **HTTP 8080**: `docker-compose -f docker-compose.example.yml up -d` → http://localhost:8080.

**More**: [Local Testing with SQLite](LOCAL_TESTING_WITH_SQLITE.md) · [DEVELOPMENT.md](../DEVELOPMENT.md)

---

## Testing workflow

- **Full suite**: `pytest` or `make test`.
- **Coverage (required for CI)**: `make test-coverage` or `pytest --cov=app --cov-report=html --cov-fail-under=50`.
- **By type**: `make test-routes`, `make test-models`, `make test-api`, `make test-unit`, `make test-integration`, `make test-smoke`.
- **Markers**: `pytest -m routes`, `pytest -m api`, etc.

Run the full test suite before opening a PR. Add tests for new behavior (e.g. in `tests/test_routes/`, `tests/test_services/`, `tests/test_api_*`).

**More**: [Testing Quick Reference](../TESTING_QUICK_REFERENCE.md) · [Testing Coverage Guide](../TESTING_COVERAGE_GUIDE.md)

---

## How to add a route

1. Add or extend a blueprint in `app/routes/` (e.g. new file or existing `api_v1_*.py`).
2. **Register** the blueprint in `app/blueprint_registry.py` (import and `app.register_blueprint(...)` in `register_all_blueprints`, or add an optional `(module_path, bp_attr)` tuple if the module may be absent in some installs).
3. Prefer calling a **service** for business logic; keep the route thin.
4. Add tests in `tests/test_routes/` or `tests/test_api_*` as appropriate.

**More**: [Service Layer and Base CRUD](SERVICE_LAYER_AND_BASE_CRUD.md) · [CONTRIBUTING.md](CONTRIBUTING.md)

---

## How to add a service or repository

1. **Service**: Add a class in `app/services/` (e.g. `app/services/my_domain_service.py`). Put business logic and orchestration here.
2. **Repository** (optional): Add a class in `app/repositories/` for data access and shared queries; use it from the service or route.
3. Follow existing patterns (see [Service Layer and Base CRUD](SERVICE_LAYER_AND_BASE_CRUD.md)); use `BaseCRUDService` only when the domain is simple CRUD with an existing repository.
4. Call the service from routes; add tests in `tests/test_services/` or `tests/test_repositories/`.

**More**: [SERVICE_LAYER_AND_BASE_CRUD.md](SERVICE_LAYER_AND_BASE_CRUD.md) · [ARCHITECTURE.md](../ARCHITECTURE.md)

---

## How to add a template

1. Create a template that extends `app/templates/base.html` and overrides blocks (`content`, `title`, etc.).
2. Use components from `app/templates/components/ui.html` (e.g. `page_header`, `empty_state`, `modal`, `confirm_dialog`, form macros). Prefer these over legacy `_components.html`.
3. Follow [UI Guidelines](../UI_GUIDELINES.md) and [FRONTEND.md](../FRONTEND.md) for layout, buttons, and accessibility.
4. Styles: Tailwind; edit `app/static/src/input.css` and build to `app/static/dist/output.css` if needed.

---

## Versioning

- **Application version**: Defined **only** in `setup.py`. Do not duplicate it in README or other docs.
- **Desktop / mobile**: Desktop and mobile builds may use their own version numbers; see [Build Guide](../../scripts/README-BUILD.md) and repo scripts. Align with app version when releasing together.
- **Releases and Docker images**: Tagging, GitHub releases, and image publishing are in [VERSION_MANAGEMENT.md](../admin/deployment/VERSION_MANAGEMENT.md) and [RELEASE_PROCESS.md](../admin/deployment/RELEASE_PROCESS.md).

**For contributors**: When updating the app version, change only `setup.py`. Do not add the version number to README, FEATURES_COMPLETE, or PROJECT_STRUCTURE.
