docs: update CLAUDE.md with first-time setup instructions and enhance response helpers documentation

This commit is contained in:
hamed
2026-06-12 18:18:41 +03:30
parent d8c4248059
commit 762a4794cf
+22 -4
View File
@@ -16,6 +16,15 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
All commands run inside ddev: prefix with `ddev exec` unless noted.
### First-time setup
```bash
ddev exec composer install
ddev exec php bin/console lexik:jwt:generate-keypair # generate JWT keys
ddev exec php bin/console doctrine:migrations:migrate --no-interaction
ddev exec yarn install && ddev exec yarn dev
ddev exec php bin/console app:create-admin # create first admin user
```
### Backend (PHP/Symfony)
```bash
ddev exec php bin/console cache:clear
@@ -28,7 +37,7 @@ ddev exec php bin/console messenger:consume async # start q
ddev exec php bin/phpunit
ddev exec php bin/phpunit tests/SomeTest.php # single test file
# Static analysis
# Static analysis (level 5, with Symfony + Doctrine extensions)
ddev exec php vendor/bin/phpstan analyse
```
@@ -63,13 +72,16 @@ src/
Shared/Constant/ErrorCodes.php
```
**Every controller extends `BaseController`** which provides three response helpers:
**Every controller extends `BaseController`** which provides four response helpers:
| Method | Shape | When to use |
|--------|-------|-------------|
| `$this->success($data)` | `{ success, data: $data }` | Single resource / action |
| `$this->paginated($items, $total, $page, $limit)` | `{ success, data: $items[], meta: { totalRecords, totalPages, currentPage } }` | Admin list endpoints |
| `$this->error($code, $message, $status)` | `{ success:false, errors:[{code,message}] }` | All error responses |
| `$this->validationError($violations)` | `{ success:false, errors:[{code,field,message}] }` HTTP 422 | Input validation failures |
**Domain exceptions:** throw `AppException(ErrorCodes::ERR_XXX, null, $httpStatus)` anywhere in the domain — `ExceptionSubscriber` catches it and calls `$this->error()` automatically. All error codes and their Persian messages live in `src/Shared/Constant/ErrorCodes.php`.
**Critical pitfall — double-nested responses:**
`$this->success(['data' => $rep->toArray()])` produces `{ data: { data: {...} } }`, so the frontend must extract with `data?.data?.data`. The `paginated()` helper does NOT nest — it returns `data` as a flat array.
@@ -82,11 +94,17 @@ Single-page app mounted at `/admin/*`:
assets/admin/
App.tsx # React Router routes
pages/ # one file per page
components/ui/ # DataTable, Modal, ConfirmDialog, PageHeader, StatusBadge, Pagination
components/
ui/ # DataTable, Modal, ConfirmDialog, PageHeader, StatusBadge, Pagination,
# SearchableSelect, PersianDateInput, PersianCalendar, AppointmentStatusDropdown
layout/ # AdminLayout, Sidebar, Topbar
hooks/ # custom React hooks
lib/api.ts # fetch wrapper (reads JWT from localStorage key: clinicpro-auth)
lib/utils.ts # formatRial, formatNumber, formatDate, formatDateTime
types/index.ts # all TypeScript interfaces
stores/authStore.ts # Zustand auth store (persisted to localStorage)
stores/
authStore.ts # Zustand auth store (persisted to localStorage)
uiStore.ts # sidebar open/close state
```
**Data fetching pattern:** TanStack Query v5 (`useQuery` / `useMutation`). Query keys use `['resource-name', page, filters]`.