update
This commit is contained in:
@@ -58,7 +58,6 @@
|
||||
</div>
|
||||
</div>
|
||||
@yield('content')
|
||||
<div id="fui-toast"></div>
|
||||
</div>
|
||||
@include('administrator.layout.partials.footer')
|
||||
</div>
|
||||
|
||||
@@ -1,60 +1,74 @@
|
||||
<!-- Toast Dependencies -->
|
||||
<link rel="stylesheet" type="text/css" href="{{ asset('lib/fui-toast/fuiToast.min.css') }}">
|
||||
<script type="text/javascript" src="{{ asset('lib/fui-toast/fuiToast.min.js') }}"></script>
|
||||
<!-- Notyf Dependencies -->
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/notyf@3/notyf.min.js"></script>
|
||||
|
||||
<!-- Toast Logic -->
|
||||
<script type="text/javascript">
|
||||
var notyf;
|
||||
|
||||
// Initialize Notyf
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
notyf = new Notyf({
|
||||
duration: 5000,
|
||||
position: {
|
||||
x: 'right',
|
||||
y: 'top',
|
||||
},
|
||||
types: [
|
||||
{
|
||||
type: 'success',
|
||||
background: '#10b981',
|
||||
dismissible: true
|
||||
},
|
||||
{
|
||||
type: 'error',
|
||||
background: '#ef4444',
|
||||
dismissible: true
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
// Show alerts from session
|
||||
setTimeout(function () {
|
||||
showAlerts();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// Function to safely show toast notifications
|
||||
function showToast(message, type = 'error', title = '') {
|
||||
// Check if FuiToast is available and container exists
|
||||
if (typeof FuiToast !== 'undefined' && document.getElementById('fui-toast')) {
|
||||
try {
|
||||
if (type === 'success') {
|
||||
FuiToast.success(message, title || 'Success!');
|
||||
} else {
|
||||
FuiToast.error(message, title || 'Error!');
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('FuiToast failed:', e);
|
||||
return false;
|
||||
if (!notyf) {
|
||||
console.warn('Notyf not initialized yet');
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
if (type === 'success') {
|
||||
notyf.success(message);
|
||||
} else {
|
||||
notyf.error(message);
|
||||
}
|
||||
return true;
|
||||
} catch (e) {
|
||||
console.error('Notyf failed:', e);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Function to show alerts with fallback
|
||||
// Function to show alerts from Laravel session
|
||||
function showAlerts() {
|
||||
@if ($errors->any() || session()->has('success'))
|
||||
@foreach ($errors->all() as $item)
|
||||
if (!showToast('{{ addslashes($item) }}', 'error', 'Opp!')) {
|
||||
alert('{{ addslashes($item) }}');
|
||||
}
|
||||
showToast('{{ addslashes($item) }}', 'error');
|
||||
@endforeach
|
||||
@if (session()->has('success'))
|
||||
if (!showToast('{{ addslashes(session()->get('success')) }}', 'success', 'Success!')) {
|
||||
alert('{{ addslashes(session()->get('success')) }}');
|
||||
}
|
||||
showToast('{{ addslashes(session()->get('success')) }}', 'success');
|
||||
@endif
|
||||
@endif
|
||||
}
|
||||
|
||||
// Wait for all scripts to load and DOM to be ready
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
// Initialize FuiToast configuration
|
||||
if (typeof FuiToast !== 'undefined' && FuiToast.config) {
|
||||
try {
|
||||
FuiToast.config({
|
||||
position: "top-center",
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('FuiToast config failed:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a small delay to ensure everything is fully initialized
|
||||
setTimeout(function() {
|
||||
showAlerts();
|
||||
}, 100);
|
||||
});
|
||||
</script>
|
||||
// Compatibility layer with old FuiToast calls
|
||||
window.FuiToast = {
|
||||
success: function (message) { return showToast(message, 'success'); },
|
||||
error: function (message) { return showToast(message, 'error'); }
|
||||
};
|
||||
</script>
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="d-flex gap-2">
|
||||
<x-button-crm type="button" variant="outline-primary" size="sm" route="products.group.edit" :params="['id' => $row->id]" icon="pencil" />
|
||||
<x-button-crm type="button" variant="outline-danger" size="sm" icon="trash"
|
||||
data-micromodal-trigger="deleteModal-{{ $row->id }}" />
|
||||
data-bs-toggle="modal" data-bs-target="#deleteModal-{{ $row->id }}" />
|
||||
</div>
|
||||
|
||||
@include('administrator.pages.product.categories.datatable.modal', [
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<div class="d-flex gap-2">
|
||||
<x-button-crm type="button" variant="outline-success" size="sm" route="products.group.restore" :params="['id' => $row->id]" icon="rotate-ccw" />
|
||||
<x-button-crm type="button" variant="outline-danger" size="sm" icon="trash-2"
|
||||
data-micromodal-trigger="forceDeleteModal-{{ $row->id }}" />
|
||||
data-bs-toggle="modal" data-bs-target="#forceDeleteModal-{{ $row->id }}" />
|
||||
</div>
|
||||
|
||||
@include('administrator.pages.product.categories.datatable.modal', [
|
||||
|
||||
@@ -1,33 +1,36 @@
|
||||
<!-- Delete Confirmation Modal -->
|
||||
<div class="modal micromodal-slide" id="{{ $modalId ?? 'deleteModal' }}" aria-hidden="true">
|
||||
<div class="modal__overlay" tabindex="-1" data-micromodal-close>
|
||||
<div class="modal__container modal--sm" role="dialog" aria-modal="true" aria-labelledby="deleteModalLabel-{{ $modalId ?? 'deleteModal' }}">
|
||||
<header class="modal__header bg-primary text-white">
|
||||
<h6 class="modal__title" id="deleteModalLabel-{{ $modalId ?? 'deleteModal' }}">
|
||||
<i data-lucide="trash-2" class="w-15px h-15px me-2"></i>
|
||||
Confirm Delete
|
||||
<div class="modal fade" id="{{ $modalId ?? 'deleteModal' }}" tabindex="-1"
|
||||
aria-labelledby="deleteModalLabel-{{ $modalId ?? 'deleteModal' }}" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered modal-sm">
|
||||
<div class="modal-content shadow-lg border-0">
|
||||
<div class="modal-header bg-danger text-white py-2">
|
||||
<h6 class="modal-title d-flex align-items-center" id="deleteModalLabel-{{ $modalId ?? 'deleteModal' }}">
|
||||
<i data-lucide="trash-2" class="me-2" style="width: 16px; height: 16px;"></i>
|
||||
Xác nhận xóa
|
||||
</h6>
|
||||
<button class="modal__close" aria-label="Close modal" data-micromodal-close>
|
||||
<i data-lucide="x"></i>
|
||||
</button>
|
||||
</header>
|
||||
<main class="modal__content">
|
||||
<div class="text-center">
|
||||
<i data-lucide="alert-triangle" class="text-warning mb-3" style="width: 48px; height: 48px;"></i>
|
||||
<h6 class="mb-2">Are you sure?</h6>
|
||||
<p class="text-muted small mb-1">Delete {{ $itemLabel }}:</p>
|
||||
<p class="fw-bold mb-2">{{ $itemName ?? '' }}</p>
|
||||
<p class="text-danger small mb-0">This action cannot be undone!</p>
|
||||
<button type="button" class="btn-close btn-close-white shadow-none" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
</main>
|
||||
<footer class="modal__footer">
|
||||
<x-button-crm type="button" variant="secondary" size="sm" icon="x" data-micromodal-close>Cancel</x-button-crm>
|
||||
<form action="{{ route($deleteRoute, ['id' => $itemId ?? 0]) }}" method="POST" class="d-inline">
|
||||
<div class="modal-body py-4">
|
||||
<div class="text-center">
|
||||
<div class="mb-3">
|
||||
<i data-lucide="alert-triangle" class="text-warning" style="width: 54px; height: 54px;"></i>
|
||||
</div>
|
||||
<h6 class="fw-bold mb-2">Bạn có chắc chắn không?</h6>
|
||||
<p class="text-muted small mb-1">Xóa {{ $itemLabel }}:</p>
|
||||
<p class="fw-bold mb-3 text-dark">{{ $itemName ?? '' }}</p>
|
||||
<div class="px-3 py-2 bg-danger-subtle rounded-3">
|
||||
<p class="text-danger small mb-0 fw-medium">Hành động này không thể hoàn tác!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-light border-0 py-2 d-flex justify-content-center gap-2">
|
||||
<x-button-c-r-m type="button" variant="secondary" size="sm" icon="x" data-bs-dismiss="modal">Hủy bỏ</x-button-c-r-m>
|
||||
<form action="{{ route($deleteRoute, ['id' => $itemId ?? 0]) }}" method="POST" class="d-inline m-0">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<x-button-crm type="submit" variant="danger" size="sm" icon="trash-2">Confirm Delete</x-button-crm>
|
||||
<x-button-c-r-m type="submit" variant="danger" size="sm" icon="trash-2">Xác nhận xóa</x-button-c-r-m>
|
||||
</form>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -64,36 +64,8 @@ $tabs = [
|
||||
@push('custom-scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Function to initialize MicroModal
|
||||
function initMicroModal() {
|
||||
if (typeof MicroModal !== 'undefined') {
|
||||
MicroModal.init({
|
||||
onShow: modal => console.info(`${modal.id} is shown`),
|
||||
onClose: modal => console.info(`${modal.id} is hidden`),
|
||||
openTrigger: 'data-micromodal-trigger',
|
||||
closeTrigger: 'data-micromodal-close',
|
||||
disableScroll: true,
|
||||
disableFocus: false,
|
||||
awaitOpenAnimation: false,
|
||||
awaitCloseAnimation: false,
|
||||
debugMode: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize on page load
|
||||
initMicroModal();
|
||||
|
||||
// Re-initialize after DataTable draws (when action column renders)
|
||||
$('#productTable').on('draw.dt', function() {
|
||||
setTimeout(function() {
|
||||
initMicroModal();
|
||||
// Re-initialize Lucide icons for modal content
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
// DataTable is already initialized in components/datatable
|
||||
// If we need custom behavior here, we can add it.
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
@@ -7,28 +7,28 @@
|
||||
|
||||
@section('breadcrumb')
|
||||
@php
|
||||
$breadcrumbItems = [
|
||||
['label' => 'Product'],
|
||||
['label' => 'Product Group', 'route' => route('products.group.index')],
|
||||
['label' => 'Trash List', 'active' => true]
|
||||
];
|
||||
$breadcrumbItems = [
|
||||
['label' => 'Product'],
|
||||
['label' => 'Product Group', 'route' => route('products.group.index')],
|
||||
['label' => 'Trash List', 'active' => true]
|
||||
];
|
||||
@endphp
|
||||
<x-admin-breadcrumb :items="$breadcrumbItems" />
|
||||
@endsection
|
||||
@section('tab')
|
||||
@php
|
||||
$tabs = [
|
||||
[
|
||||
'label' => 'Product',
|
||||
'route' => 'products.index',
|
||||
'icon' => 'server',
|
||||
],
|
||||
[
|
||||
'label' => 'Product Group',
|
||||
'route' => 'products.group.index',
|
||||
'icon' => 'server',
|
||||
],
|
||||
];
|
||||
$tabs = [
|
||||
[
|
||||
'label' => 'Product',
|
||||
'route' => 'products.index',
|
||||
'icon' => 'server',
|
||||
],
|
||||
[
|
||||
'label' => 'Product Group',
|
||||
'route' => 'products.group.index',
|
||||
'icon' => 'server',
|
||||
],
|
||||
];
|
||||
@endphp
|
||||
<x-admin-tab :items="$tabs" />
|
||||
@endsection
|
||||
@@ -40,11 +40,11 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<x-datatable id="productTable" ajax="{{ route('products.group.datatable', ['trashed' => 1]) }}" :columns="[
|
||||
['key' => 'name', 'label' => 'Group'],
|
||||
['key' => 'slug', 'label' => 'Slug'],
|
||||
['key' => 'deleted_at', 'label' => 'Deleted At'],
|
||||
['key' => 'action', 'label' => 'Action', 'searchable' => false],
|
||||
]" />
|
||||
['key' => 'name', 'label' => 'Group'],
|
||||
['key' => 'slug', 'label' => 'Slug'],
|
||||
['key' => 'deleted_at', 'label' => 'Deleted At'],
|
||||
['key' => 'action', 'label' => 'Action', 'searchable' => false],
|
||||
]" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -63,36 +63,7 @@
|
||||
@push('custom-scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
// Function to initialize MicroModal
|
||||
function initMicroModal() {
|
||||
if (typeof MicroModal !== 'undefined') {
|
||||
MicroModal.init({
|
||||
onShow: modal => console.info(`${modal.id} is shown`),
|
||||
onClose: modal => console.info(`${modal.id} is hidden`),
|
||||
openTrigger: 'data-micromodal-trigger',
|
||||
closeTrigger: 'data-micromodal-close',
|
||||
disableScroll: true,
|
||||
disableFocus: false,
|
||||
awaitOpenAnimation: false,
|
||||
awaitCloseAnimation: false,
|
||||
debugMode: true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize on page load
|
||||
initMicroModal();
|
||||
|
||||
// Re-initialize after DataTable draws (when action column renders)
|
||||
$('#productTable').on('draw.dt', function() {
|
||||
setTimeout(function() {
|
||||
initMicroModal();
|
||||
// Re-initialize Lucide icons for modal content
|
||||
if (typeof lucide !== 'undefined') {
|
||||
lucide.createIcons();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
// DataTable is already initialized in components/datatable
|
||||
});
|
||||
</script>
|
||||
@endpush
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user