# Coding Standards

## PHP / Laravel

- **PHP 8.2+** typed properties, typed returns, union types where appropriate
- **Controllers**: singular PascalCase + `Controller` suffix. One controller per resource.
- **Models**: singular PascalCase. Use `$fillable` or `$guarded` consistently (prefer `$fillable`).
- **Migrations**: snake_case, `create_<table>_table` or `add_<field>_to_<table>_table`
- **Routes**: kebab-case plurals in URL (`/admin/modalities`), camelCase route names (`admin.modalities.index`)
- **Middleware**: single-responsibility; register aliases in `bootstrap/app.php`
- **Validation**: use `Validator::make()` or `$request->validate()` inline in controllers
- **Queries**: use Eloquent ORM with eager loading; avoid raw SQL
- **Soft deletes**: not used (hard deletes only)
- **Permissions**: snake_case permission keys (`manage_patients`, `view_reports`)
- **Services**: put business logic in `app/Services/` (e.g., `AiService`, `ReportService`)
- **N+1 prevention**: always eager-load relationships with `->with()` or `->load()`
- **Comments**: minimal. Name methods and variables clearly instead.

## Blade / Views

- **Layout**: extend `layouts.adminlte` for all pages
- **Sections**: `@section('content')` for page body, `@section('title')` for `<title>`
- **Icons**: Font Awesome 6 (`fas fa-xxx`), not Bootstrap Icons
- **Forms**: CSRF `@csrf` always; use `@method('PUT'|'DELETE')` for non-GET
- **Pagination**: `$items->links('components.pagination')`
- **Alerts**: `@include('components.alert', ['type' => 'success', 'message' => '...'])`
- **Components**: reusable Blade components in `resources/views/components/`
- **Indentation**: 4 spaces, no tabs

## JavaScript

- **Vanilla ES modules** (no jQuery, no Vue/React)
- **AdminLTE**: ESM imports (`import { CardWidget, PushMenu, Treeview, Layout } from 'admin-lte'`)
- **Quill**: initialize with `new Quill('#report_body', { theme: 'snow', modules: { toolbar: [...] } })`
- **Event listeners**: `document.addEventListener('DOMContentLoaded', ...)` or inline for simple pages
- **AJAX**: `fetch()` API, not XMLHttpRequest
- **DOM queries**: `document.querySelector` / `document.querySelectorAll`
- **Formatting**: semicolons, single quotes, 2-space indentation

## CSS / SCSS

- **Framework**: AdminLTE + Bootstrap 5 utility classes
- **Custom styles**: in `resources/scss/app.scss`
- **Conventions**: BEM-like naming where custom classes needed; prefer Bootstrap utilities
- **Font**: Inter (Google Fonts, imported in app.scss)
- **Variables**: AdminLTE SCSS variables overridden before import

## Database

- **Naming**: snake_case, plural table names (`modalities`, `regions`)
- **Pivot tables**: singular alphabetical (`permission_role`, `role_user`, `study_user`)
- **Timestamps**: `created_at`, `updated_at` on all tables; `deleted_at` only if needed
- **Foreign keys**: `{singular_table}_id` convention
- **Indexes**: FK columns indexed; unique indexes on `mrn`, `accession_no`, `identity_no`
- **Charset**: utf8mb4 (MariaDB default)

## Git

- Make focused commits per feature/fix
- Use present tense imperative messages: "Add modality CRUD", "Fix status transition bug"
- Do not commit secrets, `.env`, `node_modules/`, or `vendor/`
