Introduces a reusable core detail-drawer primitive that slides in from the right and loads any view via a `*-fragment(none).phtml` endpoint. Bundles the address book list overhaul that is its first consumer. Core additions: - `app-detail-drawer.js` — generic drawer with stepper, focus trap, body scroll-lock, URL-hash deep-linking, session-expiry detection - `app-fragment-init.js` — auto-wires tabs/lookups/confirm/file-upload/ fslightbox inside injected HTML; consumers do not re-initialize components - `app-focus-trap.js` — shared focus-trap + refcounted scroll-lock, used by both filter-drawer and detail-drawer - `getHtml()` in `app-http.js` + `SessionExpiredError`; drawer reloads the page on auth redirect instead of rendering the login form in the panel - `DetailDrawerFragmentContractTest` enforces that every `initDetailDrawer` consumer ships matching `*-fragment($id).php` + `*-fragment(none).phtml` Address book list: - Grid collapses from 9 columns to 4 (identity / context / phone / actions) with a two-line identity cell (avatar + name + email) - Tenant register tabs above the grid using the `app-list-tabs` partial; tenant filter wired via hidden toolbar field so grid.js forwards it on every data fetch - Profile body extracted to a shared partial so the full-page view and the new drawer fragment share the same markup - New i18n keys for the drawer/list labels Also refactors `app-filter-drawer` to reuse the shared focus-trap and scroll-lock instead of maintaining its own copy, and documents the detail-drawer convention in CLAUDE.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
943 B
PHP
36 lines
943 B
PHP
<?php
|
|
|
|
use MintyPHP\Http\SessionStoreInterface;
|
|
use MintyPHP\Support\Guard;
|
|
|
|
$session = app(SessionStoreInterface::class)->all();
|
|
Guard::requireLogin();
|
|
Guard::requireAbilityOrForbidden(\MintyPHP\Module\AddressBook\AddressBookAuthorizationPolicy::ABILITY_VIEW);
|
|
|
|
$currentUserId = (int) ($session['user']['id'] ?? 0);
|
|
$uuid = trim((string) ($id ?? ''));
|
|
if ($uuid === '') {
|
|
http_response_code(400);
|
|
return;
|
|
}
|
|
|
|
$addressBookService = app(\MintyPHP\Module\AddressBook\Service\AddressBookService::class);
|
|
$viewContext = $addressBookService->buildViewContext($currentUserId, $uuid);
|
|
$status = (string) ($viewContext['status'] ?? '');
|
|
if ($status === 'not_found') {
|
|
http_response_code(404);
|
|
$user = null;
|
|
return;
|
|
}
|
|
if ($status === 'forbidden') {
|
|
http_response_code(403);
|
|
$user = null;
|
|
return;
|
|
}
|
|
$user = $viewContext['user'] ?? null;
|
|
if (!is_array($user)) {
|
|
http_response_code(404);
|
|
$user = null;
|
|
return;
|
|
}
|