feat(services): match Figma خدمات page in settings shell + multi-staff

Render the clinic services page (sections → services) inside the settings
sub-navigation shell (SettingsLayout, "خدمات" active) to match the Figma
settings design. Restyle section cards to show the service count and a
status toggle with edit/delete actions, and service cards with labelled
price/duration and personnel chips.

A service can now have multiple personnel: add an additive many-to-many
ServiceItem↔ClinicStaff (staffMembers, EAGER) while keeping the legacy
single `staff` column mirrored for backward compatibility. Endpoints accept
`staff_uuids[]` (falling back to the legacy single `staff_uuid`) and return
`staff_members[]`; the section list now reports `items_count`.

Backfill-safe: pre-migration rows fall back to the single staff in toArray.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
hamed
2026-07-13 13:28:51 +03:30
co-authored by Claude Opus 4.8
parent 5e59785854
commit 9e4ee11831
10 changed files with 464 additions and 71 deletions
@@ -29,6 +29,34 @@ class ServiceItemRepository extends ServiceEntityRepository
->getResult();
}
/**
* Count services per section in a single query (avoids N+1 in the section list).
*
* @param ServiceSection[] $sections
* @return array<string,int> section uuid → number of services
*/
public function countBySections(array $sections): array
{
if (empty($sections)) {
return [];
}
$rows = $this->createQueryBuilder('i')
->select('s.uuid AS uuid, COUNT(i.id) AS cnt')
->join('i.section', 's')
->where('i.section IN (:sections)')
->setParameter('sections', $sections)
->groupBy('s.uuid')
->getQuery()
->getScalarResult();
$counts = [];
foreach ($rows as $row) {
$counts[$row['uuid']] = (int) $row['cnt'];
}
return $counts;
}
public function save(ServiceItem $item): void
{
$this->getEntityManager()->persist($item);