# Code Patterns & Conventions

## PHP / Laravel

- **Thin controllers.** Methods < 30 lines. All business logic goes in a Service class.
- **Typed everything.** PHP 8 typed properties, return types, and argument types — no exceptions.
- **No raw queries.** Eloquent or Query Builder only. Never `DB::statement()` for business logic.
- **Form Requests.** Every POST/PUT/PATCH route must have a corresponding `App\Http\Requests\*` class. Never validate directly in controllers.
- **No hardcoded strings.** Use `config/` files for domain constants (see `config/ameneties.php`, `config/roles.php`).
- **Service pattern.** Controller receives request → calls service → returns `Inertia::render()`. Nothing else.

## TypeScript / React

- **No `any` types.** Define all types in `resources/js/types/`.
- **No inline styles.** Tailwind classes only.
- **Reuse existing components.** Check `resources/js/components/ui/` (44 shadcn/ui components) before building new ones.
- **Inertia forms.** Always use `useForm()` from `@inertiajs/react` for forms that submit to Laravel.
- **No direct `fetch()` calls.** Use Inertia's `router` object for all navigation and data mutations.
- **Zod validation on frontend too.** Add Zod schemas for all complex forms even though Laravel validates server-side.
- **react-hook-form + Zod pattern:**
  ```tsx
  const schema = z.object({ name: z.string().min(1) });
  const form = useForm<z.infer<typeof schema>>({ resolver: zodResolver(schema) });
  ```

## Naming Conventions

| Element | Convention | Example |
|---|---|---|
| PHP Classes | PascalCase | `ReservationService` |
| PHP Methods | camelCase | `getUpcomingReservations()` |
| PHP Variables | camelCase | `$coHostId` |
| DB Columns | snake_case | `co_host_id` |
| React Components | PascalCase | `ReservationCard.tsx` |
| React Hooks | `use*` camelCase | `useReservationFilters.ts` |
| Inertia Pages | PascalCase path | `pages/reservations/index.tsx` |
| CSS | Tailwind utilities only | `className="flex items-center gap-4"` |
| Artisan Commands | `app:<verb>-<noun>` | `app:sync-properties-with-rentals` |
| Permissions | `<domain>.<action>` | `reservation.create` |
| Route Names | `<domain>.<action>` | `reservations.index` |

## Git Discipline

- One logical change per commit.
- **Conventional Commits format:**
  ```
  feat(reservations): add overlapping dates validation
  fix(caisse): correct recovery total calculation
  test(onboarding): add folder status transition tests
  refactor(property): extract image upload to PropertyService
  chore(migrations): add internal_name to properties table
  ```
- Never commit broken code — all tests must pass first.
- Never commit `.env` or secrets.
- **Branch naming:** `feature/`, `fix/`, `refactor/`, `chore/` prefixes.
