state cart null
This commit is contained in:
parent
156978e669
commit
9a23e75f5b
|
|
@ -79,4 +79,18 @@ class CartController extends Controller
|
||||||
|
|
||||||
return redirect()->route('cart.index');
|
return redirect()->route('cart.index');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function clear(MemberCartRepository $repository)
|
||||||
|
{
|
||||||
|
$repository->clearAll();
|
||||||
|
|
||||||
|
if (request()->expectsJson()) {
|
||||||
|
return response()->json([
|
||||||
|
'success' => true,
|
||||||
|
'message' => 'Cart cleared successfully'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('cart.index');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,14 @@ class MemberCartRepository
|
||||||
->sum('qty');
|
->sum('qty');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static public function clearAll($locationId = null)
|
||||||
|
{
|
||||||
|
$location = $locationId ?? session('location_id', 22);
|
||||||
|
return Cart::where('user_id', auth()->user()->id)
|
||||||
|
->where('location_id', $location)
|
||||||
|
->delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function getList($request)
|
public function getList($request)
|
||||||
|
|
|
||||||
|
|
@ -56,27 +56,42 @@
|
||||||
<th scope="col" class="py-0 px-0">
|
<th scope="col" class="py-0 px-0">
|
||||||
<div class="nav justify-content-end">
|
<div class="nav justify-content-end">
|
||||||
<button type="button"
|
<button type="button"
|
||||||
class="nav-link d-inline-block text-decoration-underline text-nowrap py-3 px-0">Clear
|
class="nav-link d-inline-block text-decoration-underline text-nowrap py-3 px-0"
|
||||||
|
onclick="clearCart()">Clear
|
||||||
cart</button>
|
cart</button>
|
||||||
</div>
|
</div>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="align-middle">
|
<tbody class="align-middle">
|
||||||
|
@if ($carts->count() == 0)
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="text-center py-5">
|
||||||
|
<div class="py-4">
|
||||||
|
<i class="ci-shopping-bag text-muted" style="font-size: 3rem;"></i>
|
||||||
|
<h5 class="mt-3 mb-2">Your cart is empty</h5>
|
||||||
|
<p class="text-muted mb-4">Looks like you haven't added any items to your
|
||||||
|
cart yet.</p>
|
||||||
|
<a href="{{ route('home') }}" class="btn btn-primary">
|
||||||
|
<i class="ci-shopping-bag me-2"></i>Start Shopping
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@else
|
||||||
@foreach ($carts as $key => $cart)
|
@foreach ($carts as $key => $cart)
|
||||||
<tr data-cart-id="{{ $cart->id }}">
|
<tr data-cart-id="{{ $cart->id }}">
|
||||||
<td class="py-3 ps-0">
|
<td class="py-3 ps-0">
|
||||||
<div class="d-flex align-items-center">
|
<div class="d-flex align-items-center">
|
||||||
<a class="flex-shrink-0"
|
<a class="flex-shrink-0"
|
||||||
href="{{ route('second', ['shop', 'product-general-electronics']) }}">
|
href="{{ route('product.detail', $cart->itemVariant->item->slug) }}">
|
||||||
<img src="{{ $cart->itemReference->item->image_url ?? '' }}" width="110"
|
<img src="{{ $cart->itemReference->item->image_url ?? '' }}"
|
||||||
alt="{{ $cart->name ?? 'Product' }}">
|
width="110" alt="{{ $cart->name ?? 'Product' }}">
|
||||||
</a>
|
</a>
|
||||||
<div class="w-100 min-w-0 ps-2 ps-xl-3">
|
<div class="w-100 min-w-0 ps-2 ps-xl-3">
|
||||||
<h5 class="d-flex animate-underline mb-2">
|
<h5 class="d-flex animate-underline mb-2">
|
||||||
<a class="d-block fs-sm fw-medium text-truncate animate-target"
|
<a class="d-block fs-sm fw-medium text-truncate animate-target"
|
||||||
href="{{ $cart->itemVariant->item->slug != null ? route('product.detail', [$cart->item->slug]) : '#' }}">{{ $cart->itemVariant->display_name ?? $cart->itemVariant->description ?? 'Product Name' }}</a>
|
href="{{ $cart->itemVariant->item->slug != null ? route('product.detail', [$cart->item->slug]) : '#' }}">{{ $cart->itemVariant->display_name ?? ($cart->itemVariant->description ?? 'Product Name') }}</a>
|
||||||
</h5>
|
</h5>
|
||||||
{{-- <ul class="list-unstyled gap-1 fs-xs mb-0">
|
{{-- <ul class="list-unstyled gap-1 fs-xs mb-0">
|
||||||
<li><span class="text-body-secondary">Color:</span> <span
|
<li><span class="text-body-secondary">Color:</span> <span
|
||||||
|
|
@ -89,14 +104,14 @@
|
||||||
</li>
|
</li>
|
||||||
</ul> --}}
|
</ul> --}}
|
||||||
<div class="count-input rounded-2 d-md-none mt-3">
|
<div class="count-input rounded-2 d-md-none mt-3">
|
||||||
<button type="button" class="btn btn-sm btn-icon" data-decrement
|
<button type="button" class="btn btn-sm btn-icon"
|
||||||
aria-label="Decrement quantity">
|
data-decrement aria-label="Decrement quantity">
|
||||||
<i class="ci-minus"></i>
|
<i class="ci-minus"></i>
|
||||||
</button>
|
</button>
|
||||||
<input type="number" class="form-control form-control-sm"
|
<input type="number" class="form-control form-control-sm"
|
||||||
value="{{ $cart->qty ?? 1 }}" readonly>
|
value="{{ $cart->qty ?? 1 }}" readonly>
|
||||||
<button type="button" class="btn btn-sm btn-icon" data-increment
|
<button type="button" class="btn btn-sm btn-icon"
|
||||||
aria-label="Increment quantity">
|
data-increment aria-label="Increment quantity">
|
||||||
<i class="ci-plus"></i>
|
<i class="ci-plus"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -104,24 +119,32 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="h6 py-3 d-none d-xl-table-cell">
|
<td class="h6 py-3 d-none d-xl-table-cell">
|
||||||
<input type="hidden" id="price_{{ $cart->id }}" value="{{ $cart->itemVariant->display_price ?? 0 }}">
|
<input type="hidden" id="price_{{ $cart->id }}"
|
||||||
Rp {{ number_format($cart->itemVariant->display_price ?? 0, 0,",",".") }}</td>
|
value="{{ $cart->itemVariant->display_price ?? 0 }}">
|
||||||
|
Rp {{ number_format($cart->itemVariant->display_price ?? 0, 0, ',', '.') }}
|
||||||
|
</td>
|
||||||
<td class="py-3 d-none d-md-table-cell">
|
<td class="py-3 d-none d-md-table-cell">
|
||||||
<div class="count-input">
|
<div class="count-input">
|
||||||
<button type="button" class="btn btn-icon" data-decrement
|
<button type="button" class="btn btn-icon" data-decrement
|
||||||
aria-label="Decrement quantity" onclick="updateCartItem({{ $cart->id }}, 'decrement', this)">
|
aria-label="Decrement quantity"
|
||||||
|
onclick="updateCartItem({{ $cart->id }}, 'decrement', this)">
|
||||||
<i class="ci-minus"></i>
|
<i class="ci-minus"></i>
|
||||||
</button>
|
</button>
|
||||||
<input type="number" class="form-control" value="{{ $cart->qty ?? 1 }}" readonly>
|
<input type="number" class="form-control"
|
||||||
|
value="{{ $cart->qty ?? 1 }}" readonly>
|
||||||
<button type="button" class="btn btn-icon" data-increment
|
<button type="button" class="btn btn-icon" data-increment
|
||||||
aria-label="Increment quantity" onclick="updateCartItem({{ $cart->id }}, 'increment', this)">
|
aria-label="Increment quantity"
|
||||||
|
onclick="updateCartItem({{ $cart->id }}, 'increment', this)">
|
||||||
<i class="ci-plus"></i>
|
<i class="ci-plus"></i>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="h6 py-3 d-none d-md-table-cell total-row">Rp {{ number_format(($cart->display_price ?? 0) * ($cart->qty ?? 1), 0,",",".") }}</td>
|
<td class="h6 py-3 d-none d-md-table-cell total-row">Rp
|
||||||
|
{{ number_format(($cart->display_price ?? 0) * ($cart->qty ?? 1), 0, ',', '.') }}
|
||||||
|
</td>
|
||||||
<td class="text-end py-3 px-0">
|
<td class="text-end py-3 px-0">
|
||||||
<form action="{{ route('cart.delete', $cart->id) }}" method="POST" onsubmit="deleteCartItem(event, this, {{ $cart->id }})">
|
<form action="{{ route('cart.delete', $cart->id) }}" method="POST"
|
||||||
|
onsubmit="deleteCartItem(event, this, {{ $cart->id }})">
|
||||||
@csrf
|
@csrf
|
||||||
@method('DELETE')
|
@method('DELETE')
|
||||||
<button type="submit" class="btn-close fs-sm" data-bs-toggle="tooltip"
|
<button type="submit" class="btn-close fs-sm" data-bs-toggle="tooltip"
|
||||||
|
|
@ -131,13 +154,13 @@
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
@endif
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="nav position-relative z-2 mb-4 mb-lg-0">
|
<div class="nav position-relative z-2 mb-4 mb-lg-0">
|
||||||
<a class="nav-link animate-underline px-0"
|
<a class="nav-link animate-underline px-0" href="{{ route('home') }}">
|
||||||
href="{{ route('home') }}">
|
|
||||||
<i class="ci-chevron-left fs-lg me-1"></i>
|
<i class="ci-chevron-left fs-lg me-1"></i>
|
||||||
<span class="animate-target">Continue shopping</span>
|
<span class="animate-target">Continue shopping</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -147,6 +170,7 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- Order summary (sticky sidebar) -->
|
<!-- Order summary (sticky sidebar) -->
|
||||||
|
@if ($carts->count() > 0)
|
||||||
<aside class="col-lg-4" style="margin-top: -100px">
|
<aside class="col-lg-4" style="margin-top: -100px">
|
||||||
<div class="position-sticky top-0" style="padding-top: 100px">
|
<div class="position-sticky top-0" style="padding-top: 100px">
|
||||||
<div class="bg-body-tertiary rounded-5 p-4 mb-3">
|
<div class="bg-body-tertiary rounded-5 p-4 mb-3">
|
||||||
|
|
@ -154,7 +178,9 @@
|
||||||
<h5 class="border-bottom pb-4 mb-4">Order summary</h5>
|
<h5 class="border-bottom pb-4 mb-4">Order summary</h5>
|
||||||
<ul class="list-unstyled fs-sm gap-3 mb-0">
|
<ul class="list-unstyled fs-sm gap-3 mb-0">
|
||||||
<li class="d-flex justify-content-between">
|
<li class="d-flex justify-content-between">
|
||||||
<div>Subtotal (<span class="cart-count">{{ auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0 }}</span> items):</div>
|
<div>Subtotal (<span
|
||||||
|
class="cart-count">{{ auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0 }}</span>
|
||||||
|
items):</div>
|
||||||
<span class="text-dark-emphasis fw-medium" id="cart-subtotal">Rp 0</span>
|
<span class="text-dark-emphasis fw-medium" id="cart-subtotal">Rp 0</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="d-flex justify-content-between">
|
<li class="d-flex justify-content-between">
|
||||||
|
|
@ -205,9 +231,10 @@
|
||||||
<div class="accordion-body pt-3 pb-2 ps-sm-2 px-lg-0 px-xl-2">
|
<div class="accordion-body pt-3 pb-2 ps-sm-2 px-lg-0 px-xl-2">
|
||||||
<form class="needs-validation d-flex gap-2" novalidate>
|
<form class="needs-validation d-flex gap-2" novalidate>
|
||||||
<div class="position-relative w-100">
|
<div class="position-relative w-100">
|
||||||
<input type="text" class="form-control" placeholder="Enter promo code"
|
<input type="text" class="form-control"
|
||||||
required>
|
placeholder="Enter promo code" required>
|
||||||
<div class="invalid-tooltip bg-transparent py-0">Enter a valid promo code!
|
<div class="invalid-tooltip bg-transparent py-0">Enter a valid promo
|
||||||
|
code!
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" class="btn btn-dark">Apply</button>
|
<button type="submit" class="btn btn-dark">Apply</button>
|
||||||
|
|
@ -218,6 +245,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</aside>
|
</aside>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
@ -728,6 +756,54 @@
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- Clear Cart Confirmation Modal -->
|
||||||
|
<div class="modal fade" id="clearCartModal" tabindex="-1" aria-labelledby="clearCartModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header border-0">
|
||||||
|
<h5 class="modal-title" id="clearCartModalLabel">Clear Cart</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center py-4">
|
||||||
|
<div class="mb-4">
|
||||||
|
<i class="ci-trash text-danger" style="font-size: 3rem;"></i>
|
||||||
|
</div>
|
||||||
|
<h6 class="mb-3">Are you sure you want to clear your entire cart?</h6>
|
||||||
|
<p class="text-muted mb-4">This action cannot be undone. All items will be removed from your cart.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer border-0 justify-content-center">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-danger" id="confirmClearCart">Clear Cart</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Delete Item Confirmation Modal -->
|
||||||
|
<div class="modal fade" id="deleteItemModal" tabindex="-1" aria-labelledby="deleteItemModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header border-0">
|
||||||
|
<h5 class="modal-title" id="deleteItemModalLabel">Remove Item</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center py-4">
|
||||||
|
<div class="mb-4">
|
||||||
|
<i class="ci-trash text-warning" style="font-size: 3rem;"></i>
|
||||||
|
</div>
|
||||||
|
<h6 class="mb-3">Are you sure you want to remove this item from cart?</h6>
|
||||||
|
<p class="text-muted mb-4">This action cannot be undone. The item will be removed from your cart.</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer border-0 justify-content-center">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-warning" id="confirmDeleteItem">Remove Item</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@include('layouts.partials/footer')
|
@include('layouts.partials/footer')
|
||||||
@endsection
|
@endsection
|
||||||
|
|
||||||
|
|
@ -781,7 +857,8 @@ async function updateCartItem(cartId, action, button) {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
|
||||||
|
'content'),
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
|
|
@ -819,16 +896,82 @@ async function updateCartItem(cartId, action, button) {
|
||||||
async function deleteCartItem(event, form, cartId) {
|
async function deleteCartItem(event, form, cartId) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (!confirm('Are you sure you want to remove this item from cart?')) {
|
// Store the cart ID and form for later use
|
||||||
return;
|
window.pendingDelete = {
|
||||||
|
cartId,
|
||||||
|
form
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show Bootstrap modal instead of native confirm
|
||||||
|
showDeleteItemModal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to show the delete item modal
|
||||||
|
function showDeleteItemModal() {
|
||||||
|
// Try to use Bootstrap Modal if available
|
||||||
|
if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
|
||||||
|
const modal = new bootstrap.Modal(document.getElementById('deleteItemModal'));
|
||||||
|
modal.show();
|
||||||
|
} else {
|
||||||
|
// Fallback: manually show the modal
|
||||||
|
const modalElement = document.getElementById('deleteItemModal');
|
||||||
|
if (modalElement) {
|
||||||
|
modalElement.style.display = 'block';
|
||||||
|
modalElement.classList.add('show');
|
||||||
|
modalElement.setAttribute('aria-modal', 'true');
|
||||||
|
modalElement.setAttribute('role', 'dialog');
|
||||||
|
|
||||||
|
// Add backdrop
|
||||||
|
const backdrop = document.createElement('div');
|
||||||
|
backdrop.className = 'modal-backdrop fade show';
|
||||||
|
backdrop.id = 'deleteItemBackdrop';
|
||||||
|
document.body.appendChild(backdrop);
|
||||||
|
|
||||||
|
// Handle close buttons
|
||||||
|
const closeButtons = modalElement.querySelectorAll('[data-bs-dismiss="modal"]');
|
||||||
|
closeButtons.forEach(button => {
|
||||||
|
button.onclick = hideDeleteItemModal;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle backdrop click
|
||||||
|
backdrop.onclick = hideDeleteItemModal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to hide the delete item modal
|
||||||
|
function hideDeleteItemModal() {
|
||||||
|
const modalElement = document.getElementById('deleteItemModal');
|
||||||
|
const backdrop = document.getElementById('deleteItemBackdrop');
|
||||||
|
|
||||||
|
if (modalElement) {
|
||||||
|
modalElement.style.display = 'none';
|
||||||
|
modalElement.classList.remove('show');
|
||||||
|
modalElement.removeAttribute('aria-modal');
|
||||||
|
modalElement.removeAttribute('role');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backdrop) {
|
||||||
|
backdrop.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to actually delete the item (called when confirm button is clicked)
|
||||||
|
async function executeDeleteItem() {
|
||||||
|
if (!window.pendingDelete) return;
|
||||||
|
|
||||||
|
const {
|
||||||
|
cartId,
|
||||||
|
form
|
||||||
|
} = window.pendingDelete;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`cart/${cartId}`, {
|
const response = await fetch(`cart/${cartId}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
|
||||||
|
'content'),
|
||||||
'Accept': 'application/json'
|
'Accept': 'application/json'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -836,6 +979,9 @@ async function deleteCartItem(event, form, cartId) {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const result = await response.json();
|
const result = await response.json();
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
|
// Hide modal first
|
||||||
|
hideDeleteItemModal();
|
||||||
|
|
||||||
// Remove the row from the table
|
// Remove the row from the table
|
||||||
const row = form.closest('tr');
|
const row = form.closest('tr');
|
||||||
row.remove();
|
row.remove();
|
||||||
|
|
@ -843,8 +989,11 @@ async function deleteCartItem(event, form, cartId) {
|
||||||
// Update cart count in header
|
// Update cart count in header
|
||||||
updateCartCount();
|
updateCartCount();
|
||||||
|
|
||||||
// Optionally reload the page to update cart summary
|
// Recalculate totals
|
||||||
// window.location.reload();
|
calculateCartTotals();
|
||||||
|
|
||||||
|
// Clear pending delete
|
||||||
|
window.pendingDelete = null;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
console.error('Error deleting cart item:', await response.json());
|
console.error('Error deleting cart item:', await response.json());
|
||||||
|
|
@ -853,8 +1002,6 @@ async function deleteCartItem(event, form, cartId) {
|
||||||
console.error('Network error:', error);
|
console.error('Network error:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to update cart count in header
|
|
||||||
async function updateCartCount() {
|
async function updateCartCount() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('cart/count', {
|
const response = await fetch('cart/count', {
|
||||||
|
|
@ -894,7 +1041,8 @@ function calculateCartTotals() {
|
||||||
const priceInput = document.getElementById(`price_${cartId}`);
|
const priceInput = document.getElementById(`price_${cartId}`);
|
||||||
const quantityInput = row.querySelector('input[type="number"]');
|
const quantityInput = row.querySelector('input[type="number"]');
|
||||||
|
|
||||||
console.log('Processing cart ID:', cartId, 'Price input:', priceInput, 'Quantity input:', quantityInput);
|
console.log('Processing cart ID:', cartId, 'Price input:', priceInput, 'Quantity input:',
|
||||||
|
quantityInput);
|
||||||
|
|
||||||
if (priceInput && quantityInput) {
|
if (priceInput && quantityInput) {
|
||||||
const price = parseFloat(priceInput.value);
|
const price = parseFloat(priceInput.value);
|
||||||
|
|
@ -949,6 +1097,18 @@ function calculateCartTotals() {
|
||||||
// Initialize cart totals on page load
|
// Initialize cart totals on page load
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
calculateCartTotals();
|
calculateCartTotals();
|
||||||
|
|
||||||
|
// Add event listener for clear cart confirm button
|
||||||
|
const confirmClearButton = document.getElementById('confirmClearCart');
|
||||||
|
if (confirmClearButton) {
|
||||||
|
confirmClearButton.addEventListener('click', executeClearCart);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listener for delete item confirm button
|
||||||
|
const confirmDeleteButton = document.getElementById('confirmDeleteItem');
|
||||||
|
if (confirmDeleteButton) {
|
||||||
|
confirmDeleteButton.addEventListener('click', executeDeleteItem);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update cart totals when cart items are updated
|
// Update cart totals when cart items are updated
|
||||||
|
|
@ -972,5 +1132,101 @@ window.deleteCartItem = async function(event, form, cartId) {
|
||||||
calculateCartTotals();
|
calculateCartTotals();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function to clear entire cart
|
||||||
|
function clearCart() {
|
||||||
|
// Show Bootstrap modal instead of native confirm
|
||||||
|
showModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to show the clear cart modal
|
||||||
|
function showModal() {
|
||||||
|
// Try to use Bootstrap Modal if available
|
||||||
|
if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
|
||||||
|
const modal = new bootstrap.Modal(document.getElementById('clearCartModal'));
|
||||||
|
modal.show();
|
||||||
|
} else {
|
||||||
|
// Fallback: manually show the modal
|
||||||
|
const modalElement = document.getElementById('clearCartModal');
|
||||||
|
if (modalElement) {
|
||||||
|
modalElement.style.display = 'block';
|
||||||
|
modalElement.classList.add('show');
|
||||||
|
modalElement.setAttribute('aria-modal', 'true');
|
||||||
|
modalElement.setAttribute('role', 'dialog');
|
||||||
|
|
||||||
|
// Add backdrop
|
||||||
|
const backdrop = document.createElement('div');
|
||||||
|
backdrop.className = 'modal-backdrop fade show';
|
||||||
|
backdrop.id = 'clearCartBackdrop';
|
||||||
|
document.body.appendChild(backdrop);
|
||||||
|
|
||||||
|
// Handle close buttons
|
||||||
|
const closeButtons = modalElement.querySelectorAll('[data-bs-dismiss="modal"]');
|
||||||
|
closeButtons.forEach(button => {
|
||||||
|
button.onclick = hideModal;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle backdrop click
|
||||||
|
backdrop.onclick = hideModal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to hide the clear cart modal
|
||||||
|
function hideModal() {
|
||||||
|
const modalElement = document.getElementById('clearCartModal');
|
||||||
|
const backdrop = document.getElementById('clearCartBackdrop');
|
||||||
|
|
||||||
|
if (modalElement) {
|
||||||
|
modalElement.style.display = 'none';
|
||||||
|
modalElement.classList.remove('show');
|
||||||
|
modalElement.removeAttribute('aria-modal');
|
||||||
|
modalElement.removeAttribute('role');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backdrop) {
|
||||||
|
backdrop.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to actually clear the cart (called when confirm button is clicked)
|
||||||
|
async function executeClearCart() {
|
||||||
|
try {
|
||||||
|
const response = await fetch('cart/clear', {
|
||||||
|
method: 'DELETE',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute(
|
||||||
|
'content'),
|
||||||
|
'Accept': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.ok) {
|
||||||
|
const result = await response.json();
|
||||||
|
if (result.success) {
|
||||||
|
// Hide modal first
|
||||||
|
hideModal();
|
||||||
|
|
||||||
|
// Remove all cart rows from the table
|
||||||
|
const cartRows = document.querySelectorAll('tbody tr[data-cart-id]');
|
||||||
|
cartRows.forEach(row => row.remove());
|
||||||
|
|
||||||
|
// Update cart count in header
|
||||||
|
updateCartCount();
|
||||||
|
|
||||||
|
// Recalculate totals (should be zero now)
|
||||||
|
calculateCartTotals();
|
||||||
|
|
||||||
|
// Optionally show a success message
|
||||||
|
console.log('Cart cleared successfully');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Error clearing cart:', await response.json());
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Network error:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
@endsection
|
@endsection
|
||||||
|
|
|
||||||
|
|
@ -258,13 +258,14 @@
|
||||||
style="--cz-badge-padding-y: .25em; --cz-badge-padding-x: .42em">{{ auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0 }}</span>
|
style="--cz-badge-padding-y: .25em; --cz-badge-padding-x: .42em">{{ auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0 }}</span>
|
||||||
<i class="ci-shopping-bag animate-target me-1"></i>
|
<i class="ci-shopping-bag animate-target me-1"></i>
|
||||||
</button> --}}
|
</button> --}}
|
||||||
<a type="button"
|
<a type="button" href="{{ route('cart.index') }}"
|
||||||
href="{{ route('cart.index') }}"
|
|
||||||
class="btn btn-icon btn-lg fs-xl btn-outline-secondary position-relative border-0 rounded-circle animate-scale"
|
class="btn btn-icon btn-lg fs-xl btn-outline-secondary position-relative border-0 rounded-circle animate-scale"
|
||||||
aria-label="Shopping cart">
|
aria-label="Shopping cart">
|
||||||
|
@if (auth()->check() && \App\Repositories\Member\Cart\MemberCartRepository::getCount() > 0)
|
||||||
<span
|
<span
|
||||||
class="position-absolute top-0 start-100 badge fs-xs text-bg-primary rounded-pill mt-1 ms-n4 z-2 cart-count"
|
class="position-absolute top-0 start-100 badge fs-xs text-bg-primary rounded-pill mt-1 ms-n4 z-2 cart-count"
|
||||||
style="--cz-badge-padding-y: .25em; --cz-badge-padding-x: .42em">{{ auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0 }}</span>
|
style="--cz-badge-padding-y: .25em; --cz-badge-padding-x: .42em">{{ auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0 }}</span>
|
||||||
|
@endif
|
||||||
<i class="ci-shopping-bag animate-target me-1"></i>
|
<i class="ci-shopping-bag animate-target me-1"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ Route::middleware(['auth'])->prefix('/cart')->group(function () {
|
||||||
Route::get('/', [CartController::class, 'index'])->name('cart.index');
|
Route::get('/', [CartController::class, 'index'])->name('cart.index');
|
||||||
Route::post('/', [CartController::class, 'add'])->name('cart.add');
|
Route::post('/', [CartController::class, 'add'])->name('cart.add');
|
||||||
Route::put('/{id}', [CartController::class, 'update'])->name('cart.update');
|
Route::put('/{id}', [CartController::class, 'update'])->name('cart.update');
|
||||||
|
Route::delete('/clear', [CartController::class, 'clear'])->name('cart.clear');
|
||||||
Route::delete('/{id}', [CartController::class, 'delete'])->name('cart.delete');
|
Route::delete('/{id}', [CartController::class, 'delete'])->name('cart.delete');
|
||||||
Route::get('/count', [CartController::class, 'count'])->name('cart.count');
|
Route::get('/count', [CartController::class, 'count'])->name('cart.count');
|
||||||
});
|
});
|
||||||
Loading…
Reference in New Issue