# Contributing Internal helpdesk project for a single production deployment — this guide covers the practical local workflow, not an open-source contribution process. ## Local setup See [install.md](install.md) for full environment setup (Docker Compose or bare-metal). For day-to-day development the app container mounts `./src` directly, so PHP/Blade/route changes apply immediately — no rebuild or restart needed. CSS/JS changes need a Vite build (see the "Local/dev notes" section of [README.md](README.md)); Node isn't installed on the host or in the app image, so build through a throwaway `node:22` container as documented there. ## Before opening a PR / merging 1. **Run the test suite** — see [TESTING.md](TESTING.md) for details: ```bash docker compose exec servicedesk php artisan test ``` 2. **Run Pint** (Laravel's code-style fixer, default preset, no project overrides): ```bash docker compose exec servicedesk ./vendor/bin/pint ``` 3. If you changed anything under `resources/`, rebuild the frontend bundle and commit the result if `public/build/` is tracked, or confirm the deploy step will rebuild it (see [install.md](install.md)). 4. If you touched the data model, add/update a migration rather than editing an existing one that has already shipped, and update [ARCHITECTURE.md](ARCHITECTURE.md) if the change affects the ticket lifecycle or role/permission model. ## Commit messages Short, imperative summary line (e.g. `Add SLA breach email toggle`); add a body only when the *why* isn't obvious from the diff. ## Code organization Follow the existing structure rather than introducing new patterns: - `app/Livewire/{Client,Operator,Admin,Auth}/` — one component per screen/area, gated by the matching route middleware (`role:client`, `role:operator`, `role:admin`). - `app/Services/TicketService.php` — ticket lifecycle logic (create/transition/ notify) lives here, not in Livewire components. - `app/Models/` — one Eloquent model per table; keep query scopes and display/ formatting helpers (labels, style/color helpers) on the model as done for `Ticket` (`statusLabel()`, `slaInfo()`, etc.) rather than duplicating them in views. - `database/migrations/` — one migration per table group, representing final shape (not an incremental history to replay for intuition). - `routes/web.php` / `routes/api.php` — keep role/ability gating at the route group level, matching the existing pattern. See [ARCHITECTURE.md](ARCHITECTURE.md) for how these pieces fit together.