import { confirmDialog } from '../core/app-confirm-dialog.js'; import { warnOnce } from '../core/app-dom.js'; export function initUsersListPage(options = {}) { const { gridConfig, appBase, csrf, labels = {}, selectors = {}, bulkDownloadForms = {}, exportPath = 'admin/users/export', listPath = 'admin/users', resetOptions = {}, buildBulkUrl, showFlash, withLoading } = options; if (!gridConfig) {return;} const exportSelector = selectors.exportButton || '[data-users-export]'; const resetSelector = selectors.resetButton || '[data-users-reset]'; const bulkSelector = selectors.bulkButtons || '[data-users-bulk]'; const resolveBulkUrl = buildBulkUrl ? buildBulkUrl : (action) => new URL(`admin/users/bulk/${action}`, appBase).toString(); const postAction = async (url, data = {}) => { const body = new URLSearchParams({ ...data, [csrf.key]: csrf.token }); return fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': 'application/json', 'X-Requested-With': 'fetch' }, body }); }; const exportButton = document.querySelector(exportSelector); if (exportButton) { exportButton.addEventListener('click', () => { const exportUrl = new URL(exportPath, appBase); const dataUrl = new URL(gridConfig.baseUrl()); dataUrl.searchParams.forEach((value, key) => exportUrl.searchParams.set(key, value)); const sortParams = gridConfig.getSortParams ? gridConfig.getSortParams() : null; if (sortParams && sortParams.order) { exportUrl.searchParams.set('order', sortParams.order); exportUrl.searchParams.set('dir', sortParams.dir || 'asc'); } window.location.href = exportUrl.toString(); }); } const resetButton = document.querySelector(resetSelector); if (resetButton) { resetButton.addEventListener('click', () => { if (typeof gridConfig.resetFilters === 'function') { gridConfig.resetFilters(resetOptions); } else { gridConfig.updateGrid(resetOptions); } document.dispatchEvent(new CustomEvent('app:filters-updated')); }); } const bulkButtons = Array.from(document.querySelectorAll(bulkSelector)); if (bulkButtons.length) { bulkButtons.forEach((button) => { button.addEventListener('click', async () => { const action = button.getAttribute('data-users-bulk') || ''; const ids = gridConfig.selection?.getSelectedIds?.() || []; const validActions = ['activate', 'deactivate', 'delete', 'send-access', 'access-pdf']; if (!ids.length || !validActions.includes(action)) { if (action && !validActions.includes(action)) { warnOnce('UI_ACTION_UNSUPPORTED', `Unsupported users bulk action: ${action}`, { module: 'users-list', component: 'bulk-action', }); } return; } const confirmTexts = { 'activate': labels.bulkActivateConfirm, 'deactivate': labels.bulkDeactivateConfirm, 'delete': labels.bulkDeleteConfirm, 'send-access': labels.bulkSendAccessConfirm, 'access-pdf': labels.bulkAccessPdfConfirm }; const confirmText = confirmTexts[action]; if (confirmText) { const approved = await confirmDialog.confirm({ message: confirmText, actionKind: action, }); if (!approved) { return; } } const downloadFormSelector = bulkDownloadForms?.[action]; if (downloadFormSelector) { const downloadForm = document.querySelector(downloadFormSelector); if (!downloadForm) { window.location.href = new URL(listPath, appBase).toString(); return; } const uuidsInput = downloadForm.querySelector('input[name="uuids"]'); if (uuidsInput) { uuidsInput.value = ids.join(','); } downloadForm.submit(); return; } const executeBulk = async () => { const url = resolveBulkUrl(action); const response = await postAction(url, { uuids: ids.join(',') }); const data = await response.json().catch(() => null); if (response.ok && data && data.ok) { gridConfig.selection?.clear?.(); gridConfig.grid?.forceRender(); if (showFlash && labels.bulkMessages) { const msg = labels.bulkMessages[action]; if (msg) { const count = data.count ?? 0; const failed = data.failed ?? 0; let text = msg.success.replace('%d', count); if (failed > 0 && msg.partial) { text = msg.partial.replace('%d', count).replace('%f', failed); } showFlash('success', text); } } } else { if (showFlash && labels.bulkMessages) { const msg = labels.bulkMessages[action]; if (msg?.error) { showFlash('error', msg.error); } else { window.location.href = new URL(listPath, appBase).toString(); } } else { window.location.href = new URL(listPath, appBase).toString(); } } }; if (withLoading) { await withLoading(executeBulk); } else { await executeBulk(); } }); }); } }