diff --git a/config/tablar-kit.php b/config/tablar-kit.php index b7d0b3b..90e519f 100644 --- a/config/tablar-kit.php +++ b/config/tablar-kit.php @@ -29,6 +29,8 @@ 'dependent-select' => Takielias\TablarKit\Components\Forms\Inputs\DependentSelect::class, 'tom-select' => Takielias\TablarKit\Components\Forms\Inputs\TomSelect::class, 'email' => Takielias\TablarKit\Components\Forms\Inputs\Email::class, + 'modal' => Takielias\TablarKit\Components\Modals\Modal::class, + 'modal-form' => Takielias\TablarKit\Components\Modals\ModalForm::class, 'error' => Takielias\TablarKit\Components\Forms\Error::class, 'lite-picker' => Takielias\TablarKit\Components\Forms\Inputs\LitePicker::class, 'flat-picker' => Takielias\TablarKit\Components\Forms\Inputs\FlatPicker::class, diff --git a/resources/js/plugins/load.js b/resources/js/plugins/load.js index 6ae3af0..064294f 100644 --- a/resources/js/plugins/load.js +++ b/resources/js/plugins/load.js @@ -6,4 +6,5 @@ import './filepond.js' import './tabulator.js' import './xlsx.js' import './jspdf.js' +import './modal' import './common.js' diff --git a/resources/js/plugins/modal.js b/resources/js/plugins/modal.js new file mode 100644 index 0000000..071b251 --- /dev/null +++ b/resources/js/plugins/modal.js @@ -0,0 +1,102 @@ +const TablarModal = { + init() { + this.bindModalTriggers(); + this.bindFormSubmissions(); + }, + + loadModal(url, containerId = 'modal-container') { + fetch(url) + .then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } + return response.text(); + }) + .then(html => { + document.getElementById(containerId).innerHTML = html; + // Initialize the new modal + const modalElement = document.querySelector('.modal'); + const modal = new bootstrap.Modal(modalElement); + modal.show(); + + // Rebind form submissions for the new modal + this.bindFormSubmissions(); + }) + .catch(error => { + console.error('Error loading modal:', error); + // Optionally show error message to user + alert('Error loading modal content. Please try again.'); + }); + }, + + bindModalTriggers() { + // For buttons with data-modal-url + document.querySelectorAll('[data-modal-url]').forEach(button => { + button.addEventListener('click', (e) => { + e.preventDefault(); + const url = button.dataset.modalUrl; + this.loadModal(url); + }); + }); + + // For links with data-modal-trigger + document.querySelectorAll('[data-modal-trigger]').forEach(link => { + link.addEventListener('click', (e) => { + e.preventDefault(); + const url = link.href; + this.loadModal(url); + }); + }); + }, + + bindFormSubmissions() { + document.querySelectorAll('.modal form').forEach(form => { + form.addEventListener('submit', async (e) => { + e.preventDefault(); + + try { + const response = await fetch(form.action, { + method: form.method, + body: new FormData(form), + headers: { + 'X-Requested-With': 'XMLHttpRequest' + } + }); + + const data = await response.json(); + + if (data.success) { + // Close modal + const modal = bootstrap.Modal.getInstance(form.closest('.modal')); + modal.hide(); + + // Clear modal container + document.getElementById('modal-container').innerHTML = ''; + + // Optional: Show success message + if (data.message) { + alert(data.message); + } + + // Optional: Refresh page or update specific content + if (data.reload) { + window.location.reload(); + } + } + } catch (error) { + console.error('Error submitting form:', error); + } + }); + }); + } +}; + +// Initialize TablarModal when DOM is ready +document.addEventListener('DOMContentLoaded', () => { + TablarModal.init(); +}); + +// Global function to open any modal +window.openModal = (url) => { + TablarModal.loadModal(url); +} diff --git a/resources/views/components/modals/form.blade.php b/resources/views/components/modals/form.blade.php new file mode 100644 index 0000000..30e6d61 --- /dev/null +++ b/resources/views/components/modals/form.blade.php @@ -0,0 +1,16 @@ +@props([ + 'id' => 'modal-form', + 'action' => '', + 'method' => 'POST' +]) + +
+ @csrf + @if(!in_array($method, ['GET', 'POST'])) + @method($method) + @endif + + + {{ $slot }} + +
diff --git a/resources/views/components/modals/modal.blade.php b/resources/views/components/modals/modal.blade.php new file mode 100644 index 0000000..e20aa3e --- /dev/null +++ b/resources/views/components/modals/modal.blade.php @@ -0,0 +1,46 @@ +@props([ + 'id' => 'modal-default', + 'size' => '', // sm, lg, full-width + 'status' => '', // success, danger + 'title' => '', + 'scrollable' => false, + 'centered' => true, +]) + +
merge(['class' => 'modal modal-blur fade']) }} + id="{{ $id }}" + tabindex="-1" + role="dialog" + aria-hidden="true"> + +
diff --git a/src/Commands/InstallTablarKit.php b/src/Commands/InstallTablarKit.php index 822b8d5..973dfc4 100644 --- a/src/Commands/InstallTablarKit.php +++ b/src/Commands/InstallTablarKit.php @@ -31,7 +31,7 @@ public function handle(): void self::updateTablarJs(); self::scaffoldConfig(); $this->newLine(); - $this->comment('Tablar kit is now installed 🚀'); + $this->comment('Tablar kit has been installed successfully. 🚀'); $this->newLine(); $this->comment('Run "npm install" first. Once the installation is done, run "npm run dev"'); $this->newLine(); @@ -103,14 +103,24 @@ protected static function updateTablarJs(): void // Array of lines to be added $linesToAdd = [ - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/filepond.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/jodit-editor.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/tom-select.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/flat-picker.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/lite-picker.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/tabulator.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/xlsx.js';\n", - "import '../../vendor/takielias/tablar-kit/resources/js/plugins/jspdf.js';\n", + "\n// Tablar Kit components' JavaScript dependencies.\n", + "// Uncomment the required dependencies and run npm run build to include them. \n", + "\n // Filepond components' JavaScript dependencies. \n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/filepond.js';\n", + "\n // Editor components' JavaScript dependencies. \n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/jodit-editor.js';\n", + "\n // Select/DropDown components' JavaScript dependencies. \n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/tom-select.js';\n", + "\n // Date & Time Picker components' JavaScript dependencies. \n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/flat-picker.js';\n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/lite-picker.js';\n", + "\n // Table components' JavaScript dependencies. \n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/tabulator.js';\n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/xlsx.js';\n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/jspdf.js';\n", + "\n // Modal components' JavaScript dependencies. \n", + "//import '../../vendor/takielias/tablar-kit/resources/js/plugins/modal.js';\n", + "\n // Common JavaScript dependencies. \n", "import '../../vendor/takielias/tablar-kit/resources/js/plugins/common.js';\n", ]; diff --git a/src/Components/Modals/Modal.php b/src/Components/Modals/Modal.php new file mode 100644 index 0000000..07c4277 --- /dev/null +++ b/src/Components/Modals/Modal.php @@ -0,0 +1,13 @@ +id = $id; + $this->action = $action; + $this->method = $method; + $this->title = $title; + } + + public function render() + { + return view('tablar-kit::components.modals.form'); + } +} diff --git a/tests/Components/Modals/ModalTest.php b/tests/Components/Modals/ModalTest.php new file mode 100644 index 0000000..ae1afd2 --- /dev/null +++ b/tests/Components/Modals/ModalTest.php @@ -0,0 +1,35 @@ +blade('' + ); + + $view->assertSee('class="modal modal-blur fade"', false) + ->assertSee('class="modal-status bg-success"', false) + ->assertSee('class="modal-content"', false); + } + + /** @test */ + public function can_render_danger() + { + $view = $this->blade('' + ); + + $view->assertSee('class="modal modal-blur fade"', false) + ->assertSee('class="modal-status bg-danger"', false) + ->assertSee('class="modal-content"', false); + } + +}