var organizationResetFilterBtn = document.getElementById('organizationResetFilterBtn'); var organizationRows = Array.prototype.slice.call(document.querySelectorAll('#organizationTable .organization-row')); var organizationPaginationWrap = document.getElementById('organizationPaginationWrap'); var organizationPaginationPrev = document.getElementById('organizationPaginationPrev'); var organizationPaginationNext = document.getElementById('organizationPaginationNext'); var organizationPageNumbers = document.getElementById('organizationPageNumbers'); var organizationPage = 1; var organizationPerPage = getResponsiveAdminTablePageSize(); var preservedOrganizationState = window.consumeAdminTabUiState('organizations'); if (preservedOrganizationState) { var preservedOrganizationValues = preservedOrganizationState.values || {}; if (organizationSearch && Object.prototype.hasOwnProperty.call(preservedOrganizationValues, 'organizationSearch')) { organizationSearch.value = preservedOrganizationValues.organizationSearch; } if (organizationStatusFilter && Object.prototype.hasOwnProperty.call(preservedOrganizationValues, 'organizationStatusFilter')) { organizationStatusFilter.value = preservedOrganizationValues.organizationStatusFilter; } organizationPage = Math.max(1, Number(preservedOrganizationState.page) || 1); } function renderOrganizationPageButtons(totalPages) { window.DocuFlowPagination.render(organizationPageNumbers, organizationPage, totalPages, function (page) { organizationPage = page; applyOrganizationFilter(); }); } function applyOrganizationFilter() { var search = organizationSearch ? organizationSearch.value.toLowerCase().trim() : ''; var status = organizationStatusFilter ? organizationStatusFilter.value : 'all'; var filteredRows = []; organizationRows.forEach(function (row) { var matchSearch = search === '' || row.dataset.nameSearch.indexOf(search) !== -1; var matchStatus = status === 'all' || row.dataset.status === status; row.style.display = 'none'; if (matchSearch && matchStatus) { filteredRows.push(row); } }); var totalPages = Math.max(1, Math.ceil(filteredRows.length / organizationPerPage)); if (organizationPage > totalPages) organizationPage = totalPages; filteredRows.slice((organizationPage - 1) * organizationPerPage, organizationPage * organizationPerPage).forEach(function (row) { row.style.display = ''; }); var showPagination = filteredRows.length > organizationPerPage; if (organizationPaginationWrap) organizationPaginationWrap.style.display = showPagination ? 'flex' : 'none'; if (showPagination) renderOrganizationPageButtons(totalPages); if (organizationPaginationPrev) organizationPaginationPrev.classList.toggle('disabled', organizationPage <= 1); if (organizationPaginationNext) organizationPaginationNext.classList.toggle('disabled', organizationPage >= totalPages); } if (organizationSearch) organizationSearch.addEventListener('input', function () { organizationPage = 1; applyOrganizationFilter(); }); if (organizationStatusFilter) organizationStatusFilter.addEventListener('change', function () { organizationPage = 1; applyOrganizationFilter(); }); if (organizationResetFilterBtn) organizationResetFilterBtn.addEventListener('click', function () { if (organizationSearch) organizationSearch.value = ''; if (organizationStatusFilter) organizationStatusFilter.value = 'all'; organizationPage = 1; applyOrganizationFilter(); }); if (organizationPaginationPrev) organizationPaginationPrev.addEventListener('click', function (e) { e.preventDefault(); if (!this.classList.contains('disabled')) { organizationPage = Math.max(1, organizationPage - 1); applyOrganizationFilter(); } }); if (organizationPaginationNext) organizationPaginationNext.addEventListener('click', function (e) { e.preventDefault(); if (!this.classList.contains('disabled')) { organizationPage = organizationPage + 1; applyOrganizationFilter(); } }); window.addEventListener('resize', function () { var nextPerPage = getResponsiveAdminTablePageSize(); if (nextPerPage !== organizationPerPage) { organizationPerPage = nextPerPage; organizationPage = 1; applyOrganizationFilter(); } }); document.addEventListener('dashboard-data-table:sort', function (event) { if (!event.detail || !event.detail.table || event.detail.table.id !== 'organizationTable') { return; } event.preventDefault(); event.detail.handled = true; organizationRows = sortAdminDashboardRows(organizationRows, event.detail.columnIndex, event.detail.order); organizationPage = 1; applyOrganizationFilter(); }); function getOrganizationFormError(payload) { if (!payload || typeof payload !== 'object') return ''; if (payload.errors && typeof payload.errors === 'object') { var keys = Object.keys(payload.errors); if (keys.length > 0 && Array.isArray(payload.errors[keys[0]]) && payload.errors[keys[0]].length > 0) { return payload.errors[keys[0]][0]; } } return payload.message || ''; } function submitOrganizationFormWithAlert(formEl, successTitle) { if (!formEl) return; var submitBtn = formEl.querySelector('button[type="submit"]'); if (submitBtn) submitBtn.disabled = true; fetch(formEl.action, { method: 'POST', headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' }, body: new FormData(formEl) }) .then(function (response) { return response.json().catch(function () { return {}; }).then(function (payload) { if (!response.ok) { throw new Error(getOrganizationFormError(payload) || '{{ __('Unable to save organization.') }}'); } return payload; }); }) .then(function (payload) { var modalEl = formEl.closest('.modal'); if (modalEl) { if (formEl.id === 'formCreateOrganization') { allowCreateOrganizationModalClose = true; } else if (formEl.id === 'formEditOrganization') { allowEditOrganizationModalClose = true; } var modalInstance = bootstrap.Modal.getInstance(modalEl); if (modalInstance) modalInstance.hide(); } return Swal.fire({ title: successTitle, text: payload.message || '{{ __('Saved successfully.') }}', icon: 'success', confirmButtonText: '{{ __('OK') }}', customClass: { confirmButton: 'btn btn-primary w-xs mt-2' }, buttonsStyling: false }); }) .then(function () { window.refreshAdminTabContent('organizations', @json(route('role.dashboard', ['admin_tab' => 'organizations']))); }) .catch(function (error) { Swal.fire({ title: '{{ __('Save Failed') }}', text: error.message || '{{ __('Please check your input and try again.') }}', icon: 'error', confirmButtonText: '{{ __('OK') }}', customClass: { confirmButton: 'btn btn-primary w-xs mt-2' }, buttonsStyling: false }); }) .finally(function () { if (submitBtn) submitBtn.disabled = false; }); } var createOrganizationForm = document.getElementById('formCreateOrganization'); var createOrganizationModalEl = document.getElementById('modalCreateOrganization'); var createOrganizationInitialState = ''; var allowCreateOrganizationModalClose = false; if (createOrganizationForm) { createOrganizationForm.addEventListener('submit', function (e) { e.preventDefault(); submitOrganizationFormWithAlert(createOrganizationForm, '{{ __('Organization Created') }}'); }); } if (createOrganizationModalEl) { createOrganizationModalEl.addEventListener('shown.bs.modal', function () { allowCreateOrganizationModalClose = false; createOrganizationInitialState = getCreateOrganizationSnapshot(); }); createOrganizationModalEl.addEventListener('hide.bs.modal', function (event) { if (allowCreateOrganizationModalClose) { allowCreateOrganizationModalClose = false; return; } if (!createOrganizationInitialState || getCreateOrganizationSnapshot() === createOrganizationInitialState) { return; } event.preventDefault(); Swal.fire({ title: '{{ __('Unsaved Changes') }}', text: '{{ __('You have unsaved changes. Save first before leaving.') }}', icon: 'warning', showCancelButton: true, confirmButtonText: '{{ __('Leave Without Saving') }}', cancelButtonText: '{{ __('Stay') }}', customClass: { confirmButton: 'btn btn-primary w-xs me-2 mt-2', cancelButton: 'btn btn-light w-xs mt-2' }, buttonsStyling: false }).then(function (result) { if (result.value) { allowCreateOrganizationModalClose = true; var modalInstance = bootstrap.Modal.getInstance(createOrganizationModalEl); if (modalInstance) { modalInstance.hide(); } } }); }); } function getCreateOrganizationSnapshot() { var form = document.getElementById('formCreateOrganization'); if (!form) return ''; return JSON.stringify({ name_kh: (form.querySelector('input[name="name_kh"]') || {}).value || '', name_en: (form.querySelector('input[name="name_en"]') || {}).value || '', is_active: !!((form.querySelector('input[name="is_active"]') || {}).checked) }); } var editOrganizationForm = document.getElementById('formEditOrganization'); var editOrganizationModalEl = document.getElementById('modalEditOrganization'); var editOrganizationInitialState = ''; var allowEditOrganizationModalClose = false; function getEditOrganizationSnapshot() { return JSON.stringify({ name_en: (document.getElementById('editOrganizationNameEn') || {}).value || '', name_kh: (document.getElementById('editOrganizationNameKh') || {}).value || '' }); } if (editOrganizationForm) { editOrganizationForm.addEventListener('submit', function (e) { e.preventDefault(); submitOrganizationFormWithAlert(editOrganizationForm, '{{ __('Organization Updated') }}'); }); } if (editOrganizationModalEl && editOrganizationForm) { editOrganizationModalEl.addEventListener('shown.bs.modal', function () { allowEditOrganizationModalClose = false; editOrganizationInitialState = getEditOrganizationSnapshot(); }); editOrganizationModalEl.addEventListener('hide.bs.modal', function (event) { if (allowEditOrganizationModalClose) { allowEditOrganizationModalClose = false; return; } if (!editOrganizationInitialState || getEditOrganizationSnapshot() === editOrganizationInitialState) { return; } event.preventDefault(); Swal.fire({ title: '{{ __('Unsaved Changes') }}', text: '{{ __('You have unsaved changes. Save first before leaving.') }}', icon: 'warning', showCancelButton: true, confirmButtonText: '{{ __('Leave Without Saving') }}', cancelButtonText: '{{ __('Stay') }}', customClass: { confirmButton: 'btn btn-primary w-xs me-2 mt-2', cancelButton: 'btn btn-light w-xs mt-2' }, buttonsStyling: false }).then(function (result) { if (result.value) { allowEditOrganizationModalClose = true; var modalInstance = bootstrap.Modal.getInstance(editOrganizationModalEl); if (modalInstance) { modalInstance.hide(); } } }); }); } organizationTable.addEventListener('click', function (e) { var row = e.target.closest('tr.organization-row'); if (!row) return; var organizationId = row.dataset.id; var usersLink = e.target.closest('.organization-users-link'); if (usersLink) { e.preventDefault(); var usersSearch = usersLink.dataset.usersSearch || ''; var targetUrl = new URL(window.location.href); targetUrl.searchParams.set('admin_tab', 'users'); targetUrl.searchParams.set('user_organization', usersSearch); targetUrl.searchParams.delete('user_search'); targetUrl.searchParams.delete('user_role'); window.navigateDashboardContent(targetUrl.toString()); return; } if (e.target.closest('.organization-edit-btn')) { fetch('/admin/organizations/' + organizationId, { headers: { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'application/json' } }) .then(function (r) { return r.json(); }) .then(function (data) { var form = document.getElementById('formEditOrganization'); form.action = '/admin/organizations/' + organizationId; document.getElementById('editOrganizationNameEn').value = data.name_en || data.name || ''; document.getElementById('editOrganizationNameKh').value = data.name_kh || data.name || ''; new bootstrap.Modal(document.getElementById('modalEditOrganization')).show(); }); } if (e.target.closest('.organization-toggle-btn')) { var btn = e.target.closest('.organization-toggle-btn'); var isDisabling = btn.dataset.action === 'disable'; Swal.fire({ title: isDisabling ? '{{ __('Make this organization inactive?') }}' : '{{ __('Make this organization active?') }}', text: isDisabling ? '{{ __('This organization will be hidden from new user assignments and workflow stages. Existing records stay unchanged, but pending documents assigned here must be reassigned or the organization re-enabled.') }}' : '{{ __('It will become selectable again for users and workflow stages.') }}', icon: 'warning', showCancelButton: true, customClass: { confirmButton: 'btn btn-primary w-xs me-2 mt-2', cancelButton: 'btn btn-danger w-xs mt-2' }, confirmButtonText: isDisabling ? '{{ __('Yes, make inactive') }}' : '{{ __('Yes, make active') }}', cancelButtonText: '{{ __('Cancel') }}', buttonsStyling: false, showCloseButton: true }).then(function (result) { if (result.value) { var form = document.getElementById('formToggleOrganization'); form.action = '/admin/organizations/' + organizationId + '/status'; window.captureAdminTabUiState('organizations'); form.submit(); } }); } if (e.target.closest('.organization-delete-btn')) { var organizationName = row.querySelector('p.fw-semibold') ? row.querySelector('p.fw-semibold').textContent.trim() : '{{ __('this organization') }}'; Swal.fire({ title: '{{ __('Are you sure?') }}', text: '{{ __('Delete') }} "' + organizationName + '"? {{ __('This action cannot be undone.') }}', icon: 'warning', showCancelButton: true, customClass: { confirmButton: 'btn btn-primary w-xs me-2 mt-2', cancelButton: 'btn btn-danger w-xs mt-2' }, confirmButtonText: '{{ __('Yes, delete it!') }}', cancelButtonText: '{{ __('Cancel') }}', buttonsStyling: false, showCloseButton: true }).then(function (result) { if (result.isConfirmed || result.value) { var form = document.getElementById('formDeleteOrganization'); if (!form) { console.error('formDeleteOrganization not found.'); alert(@json(__('Delete form not found.'))); return; } form.action = '/admin/organizations/' + encodeURIComponent(organizationId) + '?admin_tab=organizations'; window.submitAdminActionWithoutReload(form, 'organizations', '{{ __('Organization Deleted') }}'); } }); } }); applyOrganizationFilter(); })();