Files
breadcrumb-the-shire/modules/addressbook/pages/address-book/index(default).phtml
fs c328067aa6 refactor: align addressbook module to MintyPHP\Module\AddressBook namespace
Migrates addressbook service classes from core namespace
(MintyPHP\Service\AddressBook\*) to proper module namespace
(MintyPHP\Module\AddressBook\Service\*), consistent with the
bookmarks module pattern.

Moved to module:
- AddressBookService → modules/addressbook/lib/Module/AddressBook/Service/
- AddressBookServicesFactory → modules/addressbook/lib/Module/AddressBook/Service/
- AddressBookServiceTest → modules/addressbook/tests/Module/AddressBook/Service/
- Pages, templates, CSS, JS all in module directory

All module PHP classes now live under MintyPHP\Module\<Name>\*,
enforced by ModuleStructureContractTest::testModuleClassesUseModuleNamespace.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 22:20:54 +01:00

243 lines
9.8 KiB
PHTML

<?php
use MintyPHP\Buffer;
use MintyPHP\Session;
$csrfKey = $csrfKey ?? Session::$csrfSessionKey;
$csrfToken = $csrfToken ?? ($_SESSION[$csrfKey] ?? '');
$customFieldFilterDefinitions = is_array($customFieldFilterDefinitions ?? null) ? $customFieldFilterDefinitions : [];
$activeCustomFieldQuery = is_array($customFieldFilterQuery ?? null) ? $customFieldFilterQuery : [];
$toolbarFilterSchema = is_array($toolbarFilterSchema ?? null) ? $toolbarFilterSchema : [];
$searchToolbarFilterSchema = is_array($searchToolbarFilterSchema ?? null) ? $searchToolbarFilterSchema : [];
$drawerToolbarFilterSchema = is_array($drawerToolbarFilterSchema ?? null) ? $drawerToolbarFilterSchema : [];
$toolbarFilterState = is_array($toolbarFilterState ?? null) ? $toolbarFilterState : [];
$toolbarOptionSets = is_array($toolbarOptionSets ?? null) ? $toolbarOptionSets : [];
$clientFilterSchema = is_array($clientFilterSchema ?? null) ? $clientFilterSchema : [];
$filterChipMeta = is_array($filterChipMeta ?? null) ? $filterChipMeta : [];
$searchConfig = is_array($searchConfig ?? null) ? $searchConfig : null;
?>
<?php
$breadcrumbs = [
['label' => t('Home'), 'path' => 'admin'],
['label' => t('Address book')],
];
require templatePath('partials/app-breadcrumb.phtml');
?>
<?php
$listTitle = t('Address book');
$listTitleActionsHtml = '';
require templatePath('partials/app-list-titlebar.phtml');
?>
<div
class="app-list-toolbar"
id="address-book-toolbar"
>
<?php renderGridFilterToolbar($searchToolbarFilterSchema, $toolbarFilterState, $toolbarOptionSets); ?>
<button
type="button"
class="outline secondary icon-button"
data-filter-drawer-open
data-tooltip="<?php e(t('Filter')); ?>"
data-tooltip-pos="top"
aria-label="<?php e(t('Filter')); ?>"
aria-expanded="false"
>
<i class="bi bi-funnel"></i> <?php e(t('Filter')); ?>
</button>
</div>
<div
class="app-active-filters"
data-active-filter-chips
data-filter-chips-clear-all-label="<?php e(t('Clear all filters')); ?>"
data-filter-chips-remove-label="<?php e(t('Remove filter')); ?>"
></div>
<p
class="app-visually-hidden"
data-filter-live-region
data-filter-live-applied-message="<?php e(t('Filters applied')); ?>"
data-filter-live-removed-message="<?php e(t('Filter removed')); ?>"
data-filter-live-cleared-message="<?php e(t('All filters cleared')); ?>"
aria-live="polite"
aria-atomic="true"
></p>
<div
class="app-filter-drawer"
data-filter-drawer
role="dialog"
aria-modal="true"
aria-hidden="true"
aria-labelledby="address-book-filter-drawer-title"
hidden
>
<aside class="app-filter-drawer-panel" data-filter-drawer-panel>
<header class="app-filter-drawer-header">
<h2 id="address-book-filter-drawer-title"><?php e(t('Filter')); ?></h2>
<button
type="button"
class="transparent icon-button"
data-filter-drawer-close
aria-label="<?php e(t('Close filters')); ?>"
>
<i class="bi bi-x-lg"></i>
</button>
</header>
<div class="app-filter-drawer-body">
<div
class="app-list-toolbar"
id="address-book-drawer-toolbar"
data-tenant-dept-map="<?php e(json_encode($tenantDepartmentMap ?? [], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)); ?>"
>
<?php renderGridFilterToolbar($drawerToolbarFilterSchema, $toolbarFilterState, $toolbarOptionSets); ?>
</div>
<?php if ($customFieldFilterDefinitions): ?>
<div class="app-list-toolbar" id="address-book-custom-filters">
<?php foreach ($customFieldFilterDefinitions as $definition): ?>
<?php
$definitionUuid = strtolower(trim((string) ($definition['uuid'] ?? '')));
$definitionType = strtolower(trim((string) ($definition['type'] ?? '')));
$definitionLabel = trim((string) ($definition['label'] ?? ''));
$definitionOptions = is_array($definition['options'] ?? null) ? $definition['options'] : [];
if ($definitionUuid === '' || $definitionLabel === '' || $definitionType === '') {
continue;
}
$label = $definitionLabel;
$idSuffix = preg_replace('/[^a-z0-9]+/', '-', $definitionUuid);
$paramScalar = 'cf_' . $definitionUuid;
$paramMulti = 'cfm_' . $definitionUuid;
$paramDateFrom = 'cfd_' . $definitionUuid . '_from';
$paramDateTo = 'cfd_' . $definitionUuid . '_to';
?>
<?php if ($definitionType === 'select'): ?>
<?php $currentValue = (string) ($activeCustomFieldQuery[$paramScalar] ?? ''); ?>
<?php
$selectItems = [['id' => '', 'description' => 'Please select']];
foreach ($definitionOptions as $option) {
$optionId = (string) ($option['id'] ?? '');
if ($optionId === '') {
continue;
}
$selectItems[] = [
'id' => $optionId,
'description' => (string) ($option['description'] ?? ''),
'translate' => false,
];
}
selectFilter(
'address-book-custom-filter-' . $idSuffix,
$label,
$selectItems,
$currentValue,
['for' => 'address-book-custom-filter-' . $idSuffix],
[
'data-address-book-custom-filter' => true,
'data-address-book-custom-filter-param' => $paramScalar,
]
);
?>
<?php elseif ($definitionType === 'boolean'): ?>
<?php $currentValue = strtolower(trim((string) ($activeCustomFieldQuery[$paramScalar] ?? ''))); ?>
<?php
$selectedBoolean = '';
if (in_array($currentValue, ['1', 'true'], true)) {
$selectedBoolean = '1';
} elseif (in_array($currentValue, ['0', 'false'], true)) {
$selectedBoolean = '0';
}
selectFilter(
'address-book-custom-filter-' . $idSuffix,
$label,
[
['id' => '', 'description' => 'Please select'],
['id' => '1', 'description' => 'Yes'],
['id' => '0', 'description' => 'No'],
],
$selectedBoolean,
['for' => 'address-book-custom-filter-' . $idSuffix],
[
'data-address-book-custom-filter' => true,
'data-address-book-custom-filter-param' => $paramScalar,
]
);
?>
<?php elseif ($definitionType === 'multiselect'): ?>
<?php
$currentValues = array_values(array_filter(array_map(
'trim',
explode(',', (string) ($activeCustomFieldQuery[$paramMulti] ?? ''))
), static fn ($item): bool => $item !== ''));
multiSelectFilter(
'address-book-custom-filter-' . $idSuffix,
$label,
'Select options',
$definitionOptions,
$currentValues
);
?>
<input type="hidden"
data-address-book-custom-filter
data-address-book-custom-filter-type="multiselect"
data-address-book-custom-filter-param="<?php e($paramMulti); ?>"
data-address-book-custom-filter-input="#address-book-custom-filter-<?php e($idSuffix); ?>"
>
<?php elseif ($definitionType === 'date'): ?>
<?php
$currentFrom = (string) ($activeCustomFieldQuery[$paramDateFrom] ?? '');
$currentTo = (string) ($activeCustomFieldQuery[$paramDateTo] ?? '');
?>
<label class="app-field" for="address-book-custom-filter-<?php e($idSuffix); ?>-from">
<span><?php e($label . ' ' . t('From')); ?></span>
<input type="date"
id="address-book-custom-filter-<?php e($idSuffix); ?>-from"
value="<?php e($currentFrom); ?>"
data-address-book-custom-filter
data-address-book-custom-filter-param="<?php e($paramDateFrom); ?>">
</label>
<label class="app-field" for="address-book-custom-filter-<?php e($idSuffix); ?>-to">
<span><?php e($label . ' ' . t('To')); ?></span>
<input type="date"
id="address-book-custom-filter-<?php e($idSuffix); ?>-to"
value="<?php e($currentTo); ?>"
data-address-book-custom-filter
data-address-book-custom-filter-param="<?php e($paramDateTo); ?>">
</label>
<?php endif; ?>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<footer class="app-filter-drawer-footer">
<button type="button" class="primary" data-filter-drawer-apply>
<?php e(t('Apply filters')); ?>
</button>
</footer>
</aside>
</div>
<div class="app-list-table">
<div id="address-book-grid"></div>
</div>
<?php
$gridLang = json_decode(appBufferValue('grid_lang'), true);
if (!is_array($gridLang)) {
$gridLang = [];
}
$pageConfig = [
'gridSearch' => $searchConfig,
'filterSchema' => $clientFilterSchema,
'filterChipMeta' => $filterChipMeta,
'gridLang' => $gridLang,
'labels' => [
'name' => t('Name'),
'email' => t('Email'),
'phone' => t('Phone'),
'mobile' => t('Mobile'),
'shortDial' => t('Short dial'),
'tenants' => t('Tenants'),
'departments' => t('Departments'),
'roles' => t('Roles'),
],
];
?>
<script src="<?php e(assetVersion('vendor/gridjs/gridjs.umd.js')); ?>"></script>
<script type="application/json" id="page-config-address-book-index"><?php gridJsonForJs($pageConfig); ?></script>
<script type="module" src="<?php e(assetVersion('modules/addressbook/js/pages/address-book-index.js')); ?>"></script>