From 762a4794cff4c33e7d69fa66c17b3dc231b16655 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Fri, 12 Jun 2026 18:18:41 +0330 Subject: [PATCH] docs: update CLAUDE.md with first-time setup instructions and enhance response helpers documentation --- CLAUDE.md | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index f97ef0a0..4e009c33 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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]`.