fix cart
This commit is contained in:
parent
8c21d4dc7c
commit
156978e669
|
|
@ -16,7 +16,7 @@ class CartController extends Controller
|
|||
$count = $repository->getCount($request->input('location_id'));
|
||||
|
||||
return response()->json([
|
||||
'count' => $count
|
||||
'count' => $count,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,11 @@ class MemberCartRepository
|
|||
$location = $locationId ?? session('location_id', 22);
|
||||
return Cart::where('user_id', auth()->user()->id)
|
||||
->where('location_id', $location)
|
||||
->count();
|
||||
->sum('qty');
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function getList($request)
|
||||
{
|
||||
$location = (int) $request->input("location_id");
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
<tbody class="align-middle">
|
||||
|
||||
@foreach ($carts as $key => $cart)
|
||||
<tr>
|
||||
<tr data-cart-id="{{ $cart->id }}">
|
||||
<td class="py-3 ps-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<a class="flex-shrink-0"
|
||||
|
|
@ -137,7 +137,7 @@
|
|||
|
||||
<div class="nav position-relative z-2 mb-4 mb-lg-0">
|
||||
<a class="nav-link animate-underline px-0"
|
||||
href="{{ route('second', ['shop', 'catalog-electronics']) }}'">
|
||||
href="{{ route('home') }}">
|
||||
<i class="ci-chevron-left fs-lg me-1"></i>
|
||||
<span class="animate-target">Continue shopping</span>
|
||||
</a>
|
||||
|
|
@ -154,16 +154,16 @@
|
|||
<h5 class="border-bottom pb-4 mb-4">Order summary</h5>
|
||||
<ul class="list-unstyled fs-sm gap-3 mb-0">
|
||||
<li class="d-flex justify-content-between">
|
||||
Subtotal (3 items):
|
||||
<span class="text-dark-emphasis fw-medium">$2,427.00</span>
|
||||
<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>
|
||||
</li>
|
||||
<li class="d-flex justify-content-between">
|
||||
Saving:
|
||||
<span class="text-danger fw-medium">-$110.00</span>
|
||||
<span class="text-danger fw-medium">Rp 0</span>
|
||||
</li>
|
||||
<li class="d-flex justify-content-between">
|
||||
<li class="d-flex justify-content-between" id="tax-row" style="display: none;">
|
||||
Tax collected:
|
||||
<span class="text-dark-emphasis fw-medium">$73.40</span>
|
||||
<span class="text-dark-emphasis fw-medium">Rp 0</span>
|
||||
</li>
|
||||
<li class="d-flex justify-content-between">
|
||||
Shipping:
|
||||
|
|
@ -173,19 +173,19 @@
|
|||
<div class="border-top pt-4 mt-4">
|
||||
<div class="d-flex justify-content-between mb-3">
|
||||
<span class="fs-sm">Estimated total:</span>
|
||||
<span class="h5 mb-0">$2,390.40</span>
|
||||
<span class="h5 mb-0" id="cart-estimated-total">$0.00</span>
|
||||
</div>
|
||||
<a class="btn btn-lg btn-primary w-100"
|
||||
href="{{ route('second', ['checkout', 'v1-delivery-1']) }}">
|
||||
Proceed to checkout
|
||||
<i class="ci-chevron-right fs-lg ms-1 me-n1"></i>
|
||||
</a>
|
||||
<div class="nav justify-content-center fs-sm mt-3">
|
||||
{{-- <div class="nav justify-content-center fs-sm mt-3">
|
||||
<a class="nav-link text-decoration-underline p-0 me-1" href="#authForm"
|
||||
data-bs-toggle="offcanvas" role="button">Create an account</a>
|
||||
and get
|
||||
<span class="text-dark-emphasis fw-medium ms-1">239 bonuses</span>
|
||||
</div>
|
||||
</div> --}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -871,10 +871,106 @@ async function updateCartCount() {
|
|||
cartCountElements.forEach(element => {
|
||||
element.textContent = result.count;
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error updating cart count:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to calculate and update cart totals
|
||||
function calculateCartTotals() {
|
||||
let subtotal = 0;
|
||||
let itemCount = 0;
|
||||
|
||||
// Get all cart item rows
|
||||
const cartRows = document.querySelectorAll('tbody tr[data-cart-id]');
|
||||
|
||||
console.log('Found cart rows:', cartRows.length);
|
||||
|
||||
cartRows.forEach(row => {
|
||||
const cartId = row.dataset.cartId;
|
||||
const priceInput = document.getElementById(`price_${cartId}`);
|
||||
const quantityInput = row.querySelector('input[type="number"]');
|
||||
|
||||
console.log('Processing cart ID:', cartId, 'Price input:', priceInput, 'Quantity input:', quantityInput);
|
||||
|
||||
if (priceInput && quantityInput) {
|
||||
const price = parseFloat(priceInput.value);
|
||||
const quantity = parseInt(quantityInput.value);
|
||||
subtotal += price * quantity;
|
||||
itemCount += quantity;
|
||||
|
||||
console.log('Price:', price, 'Quantity:', quantity, 'Running subtotal:', subtotal);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Final subtotal:', subtotal, 'Item count:', itemCount);
|
||||
|
||||
// Update subtotal display
|
||||
const subtotalElement = document.getElementById('cart-subtotal');
|
||||
if (subtotalElement) {
|
||||
subtotalElement.textContent = `Rp ${number_format(subtotal, 0, ',', '.')}`;
|
||||
console.log('Updated subtotal element:', subtotalElement.textContent);
|
||||
}
|
||||
|
||||
// Calculate estimated total (subtotal - savings + tax)
|
||||
const savings = 0; // Fixed savings amount
|
||||
const tax = 0; // Fixed tax amount
|
||||
const estimatedTotal = subtotal - savings + tax;
|
||||
|
||||
// Show/hide tax row based on tax amount
|
||||
const taxRow = document.getElementById('tax-row');
|
||||
if (taxRow) {
|
||||
if (tax > 0) {
|
||||
taxRow.style.display = 'flex';
|
||||
taxRow.querySelector('span').textContent = `Rp ${number_format(tax, 0, ',', '.')}`;
|
||||
} else {
|
||||
taxRow.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Update estimated total display
|
||||
const estimatedTotalElement = document.getElementById('cart-estimated-total');
|
||||
if (estimatedTotalElement) {
|
||||
estimatedTotalElement.textContent = `Rp ${number_format(estimatedTotal, 0, ',', '.')}`;
|
||||
console.log('Updated estimated total element:', estimatedTotalElement.textContent);
|
||||
}
|
||||
|
||||
// Update items count
|
||||
const cartCalcElement = document.getElementById('cart-calc');
|
||||
if (cartCalcElement) {
|
||||
cartCalcElement.textContent = itemCount;
|
||||
console.log('Updated item count:', cartCalcElement.textContent);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize cart totals on page load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
calculateCartTotals();
|
||||
});
|
||||
|
||||
// Update cart totals when cart items are updated
|
||||
const originalUpdateCartItem = updateCartItem;
|
||||
window.updateCartItem = async function(cartId, action, button) {
|
||||
await originalUpdateCartItem(cartId, action, button);
|
||||
|
||||
// Recalculate totals after successful update
|
||||
setTimeout(() => {
|
||||
calculateCartTotals();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
// Update cart totals when cart items are deleted
|
||||
const originalDeleteCartItem = deleteCartItem;
|
||||
window.deleteCartItem = async function(event, form, cartId) {
|
||||
await originalDeleteCartItem(event, form, cartId);
|
||||
|
||||
// Recalculate totals after successful deletion
|
||||
setTimeout(() => {
|
||||
calculateCartTotals();
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -134,7 +134,8 @@
|
|||
<div class="offcanvas offcanvas-top" id="searchBox" data-bs-backdrop="static" tabindex="-1">
|
||||
<div class="offcanvas-header border-bottom p-0 py-lg-1">
|
||||
<form class="container d-flex align-items-center">
|
||||
<input type="search" id="searchInput" class="form-control form-control-lg fs-lg border-0 rounded-0 py-3 ps-0"
|
||||
<input type="search" id="searchInput"
|
||||
class="form-control form-control-lg fs-lg border-0 rounded-0 py-3 ps-0"
|
||||
placeholder="Search the products" data-autofocus="offcanvas">
|
||||
<button type="reset" class="btn-close fs-lg" data-bs-dismiss="offcanvas"
|
||||
aria-label="Close"></button>
|
||||
|
|
@ -248,7 +249,7 @@
|
|||
</a>
|
||||
|
||||
<!-- Cart button -->
|
||||
<button type="button"
|
||||
{{-- <button type="button"
|
||||
class="btn btn-icon btn-lg fs-xl btn-outline-secondary position-relative border-0 rounded-circle animate-scale"
|
||||
data-bs-toggle="offcanvas" data-bs-target="#shoppingCart" aria-controls="shoppingCart"
|
||||
aria-label="Shopping cart">
|
||||
|
|
@ -256,7 +257,16 @@
|
|||
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>
|
||||
<i class="ci-shopping-bag animate-target me-1"></i>
|
||||
</button>
|
||||
</button> --}}
|
||||
<a type="button"
|
||||
href="{{ route('cart.index') }}"
|
||||
class="btn btn-icon btn-lg fs-xl btn-outline-secondary position-relative border-0 rounded-circle animate-scale"
|
||||
aria-label="Shopping cart">
|
||||
<span
|
||||
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>
|
||||
<i class="ci-shopping-bag animate-target me-1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,33 @@
|
|||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Login Dialog Modal -->
|
||||
<div class="modal fade" id="loginDialogModal" tabindex="-1" aria-labelledby="loginDialogLabel" 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="loginDialogLabel">Login Required</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-user-circle text-primary" style="font-size: 3rem;"></i>
|
||||
</div>
|
||||
<h6 class="mb-3">Please login to add items to cart</h6>
|
||||
<p class="text-muted mb-4">You need to be logged in to add items to your shopping cart and proceed with checkout.</p>
|
||||
<div class="d-grid gap-2">
|
||||
<a href="{{ route('login') }}" class="btn btn-primary">
|
||||
<i class="ci-login me-2"></i>Login to Continue
|
||||
</a>
|
||||
<a href="{{ route('register') }}" class="btn btn-outline-primary">
|
||||
<i class="ci-user-plus me-2"></i>Create Account
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function incrementQuantity(button) {
|
||||
const input = button.parentElement.querySelector('input[type="number"]');
|
||||
|
|
@ -101,8 +128,13 @@
|
|||
} else {
|
||||
const error = await response.json();
|
||||
console.error('Error adding to cart:', error);
|
||||
// Check if error is due to unauthenticated user
|
||||
if (error.message && error.message.toLowerCase().includes('unauthenticated') || response.status === 401) {
|
||||
showLoginDialog();
|
||||
} else {
|
||||
// You could show an error message here
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Network error:', error);
|
||||
// You could show an error message here
|
||||
|
|
@ -136,4 +168,54 @@
|
|||
console.error('Error updating cart count:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to show login dialog
|
||||
function showLoginDialog() {
|
||||
// Try to use Bootstrap Modal if available
|
||||
if (typeof bootstrap !== 'undefined' && bootstrap.Modal) {
|
||||
const modal = new bootstrap.Modal(document.getElementById('loginDialogModal'));
|
||||
modal.show();
|
||||
} else {
|
||||
// Fallback: manually show the modal
|
||||
const modalElement = document.getElementById('loginDialogModal');
|
||||
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 = 'loginDialogBackdrop';
|
||||
document.body.appendChild(backdrop);
|
||||
|
||||
// Handle close buttons
|
||||
const closeButtons = modalElement.querySelectorAll('[data-bs-dismiss="modal"]');
|
||||
closeButtons.forEach(button => {
|
||||
button.onclick = hideLoginDialog;
|
||||
});
|
||||
|
||||
// Handle backdrop click
|
||||
backdrop.onclick = hideLoginDialog;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to hide login dialog
|
||||
function hideLoginDialog() {
|
||||
const modalElement = document.getElementById('loginDialogModal');
|
||||
const backdrop = document.getElementById('loginDialogBackdrop');
|
||||
|
||||
if (modalElement) {
|
||||
modalElement.style.display = 'none';
|
||||
modalElement.classList.remove('show');
|
||||
modalElement.removeAttribute('aria-modal');
|
||||
modalElement.removeAttribute('role');
|
||||
}
|
||||
|
||||
if (backdrop) {
|
||||
backdrop.remove();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue