diff --git a/index.php b/index.php index 1795b07..9f3392d 100644 --- a/index.php +++ b/index.php @@ -1208,6 +1208,10 @@ document.addEventListener('DOMContentLoaded', function () { const formData = new FormData(); formData.append('person_id', personId); formData.append('process_id', processId); + if (instanceModalElement) { + instanceModalElement.dataset.lastPersonId = personId; + instanceModalElement.dataset.lastProcessId = processId; + } fetch('_init_single_instance.php', { method: 'POST', @@ -1225,7 +1229,7 @@ document.addEventListener('DOMContentLoaded', function () { modalBody.innerHTML = html; }); } else { - alert('Błąd: ' + (data.error || 'Nieznany błąd')); + alert('Błąd: ' + (data.error?.message || data.error || 'Nieznany błąd')); btn.disabled = false; btn.innerHTML = originalText; } @@ -1238,6 +1242,156 @@ document.addEventListener('DOMContentLoaded', function () { }); }); } + // --- Actions inside Instance Modal --- + if (instanceModalElement) { + instanceModalElement.addEventListener('click', function(event) { + // Apply Transition Button + if (event.target.classList.contains('apply-transition-btn')) { + event.preventDefault(); + const btn = event.target; + const instanceId = btn.dataset.instanceId; + const transitionId = btn.dataset.transitionId; + + // Get form data if transition form exists + const form = instanceModalElement.querySelector('#transition-form'); + const formData = new FormData(); + formData.append('instanceId', instanceId); + formData.append('transitionId', transitionId); + + if (form) { + const formElements = new FormData(form); + for (let [key, value] of formElements.entries()) { + formData.append('payload[' + key + ']', value); + } + } + + const originalText = btn.innerHTML; + btn.disabled = true; + btn.innerHTML = '...'; + + fetch('_apply_transition.php', { + method: 'POST', + body: formData + }) + .then(r => r.json()) + .then(data => { + if (data.success || !data.error) { + // Reload modal content + const personId = instanceModalElement.dataset.lastPersonId; + const processId = instanceModalElement.dataset.lastProcessId; + + fetch(`_get_instance_details.php?person_id=${personId}&process_id=${processId}`) + .then(r => r.text()) + .then(html => { + instanceModalElement.querySelector('.modal-body').innerHTML = html; + }); + } else { + alert('Błąd: ' + (data.error?.message || 'Nieznany błąd')); + btn.disabled = false; + btn.innerHTML = originalText; + } + }) + .catch(err => { + console.error(err); + alert('Błąd sieci'); + btn.disabled = false; + btn.innerHTML = originalText; + }); + } + + // Add Note Button + if (event.target.id === 'addNoteBtn') { + event.preventDefault(); + const btn = event.target; + const instanceId = btn.dataset.instanceId; + const noteMessage = instanceModalElement.querySelector('#noteMessage').value.trim(); + + if (!noteMessage) { + alert('Treść notatki nie może być pusta.'); + return; + } + + const formData = new FormData(); + formData.append('instanceId', instanceId); + formData.append('transitionId', 'note'); + formData.append('payload[message]', noteMessage); + + const originalText = btn.innerHTML; + btn.disabled = true; + btn.innerHTML = '...'; + + fetch('_apply_transition.php', { + method: 'POST', + body: formData + }) + .then(r => r.json()) + .then(data => { + if (data.success || !data.error) { + const personId = instanceModalElement.dataset.lastPersonId; + const processId = instanceModalElement.dataset.lastProcessId; + + fetch(`_get_instance_details.php?person_id=${personId}&process_id=${processId}`) + .then(r => r.text()) + .then(html => { + instanceModalElement.querySelector('.modal-body').innerHTML = html; + }); + } else { + alert('Błąd: ' + (data.error?.message || 'Nieznany błąd')); + btn.disabled = false; + btn.innerHTML = originalText; + } + }) + .catch(err => { + console.error(err); + alert('Błąd sieci'); + btn.disabled = false; + btn.innerHTML = originalText; + }); + } + }); + + instanceModalElement.addEventListener('change', function(event) { + // Task Checkbox + if (event.target.classList.contains('task-checkbox-modal')) { + const checkbox = event.target; + const container = checkbox.closest('.checklist-modal-container'); + const instanceId = container.dataset.instanceId; + const taskCode = checkbox.dataset.taskCode; + const isChecked = checkbox.checked; + + fetch('_update_training_checklist_status.php', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + instance_id: instanceId, + task_code: taskCode, + is_checked: isChecked + }) + }) + .then(r => r.json()) + .then(data => { + if (data.error) { + alert('Błąd: ' + (data.error?.message || 'Nieznany błąd')); + checkbox.checked = !isChecked; // revert + } + }) + .catch(err => { + console.error(err); + alert('Błąd sieci'); + checkbox.checked = !isChecked; // revert + }); + } + }); + + // Save personId and processId on modal show so we can use it to reload later + instanceModalElement.addEventListener('show.bs.modal', function (event) { + var button = event.relatedTarget; + if(button && button.dataset) { + if (button.dataset.personId) instanceModalElement.dataset.lastPersonId = button.dataset.personId; + if (button.dataset.processId) instanceModalElement.dataset.lastProcessId = button.dataset.processId; + } + }); + } }); diff --git a/lib/WorkflowExceptions.php b/lib/WorkflowExceptions.php index dbcac1d..d6fdc54 100644 --- a/lib/WorkflowExceptions.php +++ b/lib/WorkflowExceptions.php @@ -5,7 +5,7 @@ class WorkflowException extends Exception { protected $details; public function __construct($message = "", $httpCode = 500, $details = [], Throwable $previous = null) { - parent::__construct($message, 0, $previous); + parent::__construct($message, $httpCode, $previous); $this->httpCode = $httpCode; $this->details = $details; } @@ -19,19 +19,33 @@ class WorkflowException extends Exception { } } -class WorkflowNotFoundException extends Exception {} -class WorkflowNotAllowedException extends Exception {} -class WorkflowRuleFailedException extends Exception {} +class WorkflowNotFoundException extends WorkflowException { + public function __construct($message = "") { + parent::__construct($message, 404); + } +} -class WorkflowEligibilityException extends Exception { +class WorkflowNotAllowedException extends WorkflowException { + public function __construct($message = "") { + parent::__construct($message, 403); + } +} + +class WorkflowRuleFailedException extends WorkflowException { + public function __construct($message = "") { + parent::__construct($message, 400); + } +} + +class WorkflowEligibilityException extends WorkflowException { private $reasons; - public function __construct($message = "", $reasons = [], $code = 0, Throwable $previous = null) { - parent::__construct($message, $code, $previous); + public function __construct($message = "", $reasons = []) { + parent::__construct($message, 422, ['reasons' => $reasons]); $this->reasons = $reasons; } public function getReasons() { return $this->reasons; } -} +} \ No newline at end of file