feat(patients): inline tag popover + advanced filters on the records list

Port the remaining pieces of tauri /files list into /admin/patients:

- inline tag assignment: the برچسب‌ها cell (table + card) opens a popover to
  assign/remove tenant tags without leaving the list. Uses existing endpoints
  (GET /api/v1/tenant-tags + PATCH /api/v1/patient/{uuid} { tags:[uuid] }).
  New component assets/admin/components/PatientTagsCell.tsx.
- advanced filter modal (PatientsFilterModal): admission date range, insurance,
  service status (pending/completed), has-debt, gender, tags — wired to the
  list query with an active-filter badge on the button.

Backend: GET /api/v1/patients gains tags/gender/insurance_id/admitted_from/
admitted_to/service_status/has_debt filters via a shared applyFilters() on
PatientRecordRepository (findByEntity + countByEntity stay consistent). Debt
and service status derive from unpaid sessions (payment_method='pending'),
documented in docs/api/patient.md.

Tests: tests/Patient/PatientListFilterTest.php (5) + PatientsListPage tag-popover
and filter-apply tests. Pre-existing LoginPage.test failures are unrelated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-14 19:40:54 +03:30
co-authored by Claude Opus 4.8
parent 4edeffe325
commit fd91840ba2
8 changed files with 578 additions and 52 deletions
+13 -2
View File
@@ -528,8 +528,19 @@ class PatientController extends BaseController
$limit = min(50, max(10, (int) $request->query->get('limit', 20)));
$search = $request->query->get('search') ?: null;
$records = $this->recordRepo->findByEntity($entityType, $entityId, $page, $limit, $search);
$total = $this->recordRepo->countByEntity($entityType, $entityId, $search);
$tags = $request->query->get('tags');
$filters = [
'tags' => $tags ? array_filter(array_map('trim', explode(',', $tags))) : null,
'gender' => $request->query->get('gender') ?: null,
'insurance_id' => $request->query->get('insurance_id') ?: null,
'admitted_from' => $request->query->get('admitted_from') ?: null,
'admitted_to' => $request->query->get('admitted_to') ?: null,
'service_status' => $request->query->get('service_status') ?: null,
'has_debt' => $request->query->getBoolean('has_debt'),
];
$records = $this->recordRepo->findByEntity($entityType, $entityId, $page, $limit, $search, $filters);
$total = $this->recordRepo->countByEntity($entityType, $entityId, $search, $filters);
return $this->paginated(
array_map(fn(PatientRecord $r) => $r->toArray(), $records),