checkout fix

This commit is contained in:
Bayu Lukman Yusuf 2026-03-02 09:24:10 +07:00
parent f78819c9b9
commit 0aec36908b
9 changed files with 217 additions and 132 deletions

View File

@ -68,4 +68,6 @@ return [
'shipping' => 'Shipping:', 'shipping' => 'Shipping:',
'estimated_total' => 'Estimated total:', 'estimated_total' => 'Estimated total:',
'proceed_to_checkout' => 'Proceed to checkout', 'proceed_to_checkout' => 'Proceed to checkout',
'order_summary' => 'Order summary',
'calculated_at_checkout' => 'Calculated at checkout',
]; ];

View File

@ -14,5 +14,8 @@ return [
'sign_up' => 'Sign Up', 'sign_up' => 'Sign Up',
'contact' => 'Contact', 'contact' => 'Contact',
'terms_conditions' => 'Terms & Conditions', 'terms_conditions' => 'Terms & Conditions',
'categories' => 'Categories' 'categories' => 'Categories',
'delivery' => 'Delivery',
'set_your_address' => 'Set your address',
'gender' => 'Gender',
]; ];

View File

@ -68,4 +68,6 @@ return [
'shipping' => 'Pengiriman:', 'shipping' => 'Pengiriman:',
'estimated_total' => 'Total estimasi:', 'estimated_total' => 'Total estimasi:',
'proceed_to_checkout' => 'Lanjut ke checkout', 'proceed_to_checkout' => 'Lanjut ke checkout',
'order_summary' => 'Ringkasan pesanan',
'calculated_at_checkout' => 'Dihitung di checkout',
]; ];

View File

@ -15,4 +15,7 @@ return [
'contact' => 'Kontak', 'contact' => 'Kontak',
'terms_conditions' => 'Syarat & Ketentuan', 'terms_conditions' => 'Syarat & Ketentuan',
'categories' => 'Kategori', 'categories' => 'Kategori',
'delivery' => 'Pengiriman',
'set_your_address' => 'Atur alamat Anda',
'gender' => 'Gender',
]; ];

View File

@ -42,12 +42,12 @@
</div> --}} </div> --}}
<!-- Table of items --> <!-- Table of items -->
<table class="table position-relative z-2 mb-4"> <table class="table z-2 mb-4">
<thead> <thead>
<tr> <tr>
<th scope="col" class="fs-sm fw-normal py-3 ps-0"><span <th scope="col" class="fs-sm fw-normal py-3 ps-0"><span
class="text-body">Product</span></th> class="text-body">Product</span></th>
<th scope="col" class="text-body fs-sm fw-normal py-3 d-none d-md-table-cell"><span <th scope="col" class="text-body fs-sm fw-normal py-3 d-none d-md-table-cell"><span
class="text-body">Quantity</span></th> class="text-body">Quantity</span></th>
<th scope="col" class="text-body fs-sm fw-normal py-3 d-none d-md-table-cell"><span <th scope="col" class="text-body fs-sm fw-normal py-3 d-none d-md-table-cell"><span
@ -79,7 +79,9 @@
</tr> </tr>
@else @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"
@ -88,7 +90,7 @@
width="80" alt="{{ $cart->name ?? 'Product' }}"> width="80" 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"
@ -105,9 +107,10 @@
</li> </li>
</ul> --}} </ul> --}}
<input type="hidden" id="price_{{ $cart->id }}" <input type="hidden" id="price_{{ $cart->id }}"
value="{{ $cart->itemVariant->display_price ?? 0 }}"> value="{{ $cart->itemVariant->display_price ?? 0 }}">
Rp {{ number_format($cart->itemVariant->display_price ?? 0, 0, ',', '.') }} Rp
{{ number_format($cart->itemVariant->display_price ?? 0, 0, ',', '.') }}
<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" <button type="button" class="btn btn-sm btn-icon"
@ -124,7 +127,7 @@
</div> </div>
</div> </div>
</td> </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
@ -177,7 +180,7 @@
<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">
<div class="p-sm-2 p-lg-0 p-xl-2"> <div class="p-sm-2 p-lg-0 p-xl-2">
<h5 class="border-bottom pb-4 mb-4">Order summary</h5> <h5 class="border-bottom pb-4 mb-4">{{ __('checkout.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 <div>Subtotal (<span
@ -187,7 +190,8 @@
</li> </li>
<li class="d-flex justify-content-between"> <li class="d-flex justify-content-between">
{{ __('checkout.saving') }} {{ __('checkout.saving') }}
<span class="text-danger fw-medium">Rp {{ number_format(session('use_point') ?? 0,0,",",".") }}</span> <span class="text-danger fw-medium">Rp
{{ number_format(session('use_point') ?? 0, 0, ',', '.') }}</span>
</li> </li>
{{-- <li class="d-flex justify-content-between" id="tax-row" style="display: none;"> {{-- <li class="d-flex justify-content-between" id="tax-row" style="display: none;">
Tax collected: Tax collected:
@ -195,7 +199,7 @@
</li> --}} </li> --}}
<li class="d-flex justify-content-between"> <li class="d-flex justify-content-between">
{{ __('checkout.shipping') }} {{ __('checkout.shipping') }}
<span class="text-dark-emphasis fw-medium">Calculated at checkout</span> <span class="text-dark-emphasis fw-medium">{{ __('checkout.calculated_at_checkout') }}</span>
</li> </li>
</ul> </ul>
<div class="border-top pt-4 mt-4"> <div class="border-top pt-4 mt-4">
@ -203,8 +207,7 @@
<span class="fs-sm">{{ __('checkout.estimated_total') }}</span> <span class="fs-sm">{{ __('checkout.estimated_total') }}</span>
<span class="h5 mb-0" id="cart-estimated-total">$0.00</span> <span class="h5 mb-0" id="cart-estimated-total">$0.00</span>
</div> </div>
<a class="btn btn-lg btn-primary w-100" <a class="btn btn-lg btn-primary w-100" href="{{ route('checkout.delivery') }}">
href="{{ route('checkout.delivery') }}">
{{ __('checkout.proceed_to_checkout') }} {{ __('checkout.proceed_to_checkout') }}
<i class="ci-chevron-right fs-lg ms-1 me-n1"></i> <i class="ci-chevron-right fs-lg ms-1 me-n1"></i>
</a> </a>

View File

@ -1,5 +1,10 @@
@extends('layouts.landing', ['title' => 'Checkout']) @extends('layouts.landing', ['title' => 'Checkout'])
@push('styles')
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
@endpush
@section('content') @section('content')
<x-layout.header-grocery /> <x-layout.header-grocery />
@ -128,6 +133,12 @@
</div> </div>
<div class="mt-3">
<div id="address-map"
style="height: 300px; width: 100%; border-radius: 8px; overflow: hidden;">
</div>
</div>
@ -191,8 +202,7 @@
<!-- Order summary (sticky sidebar) --> <!-- Order summary (sticky sidebar) -->
<aside class="col-lg-4 offset-xl-1" style="margin-top: -100px"> <aside class="col-lg-4 offset-xl-1" style="margin-top: -100px">
<div class="position-sticky top-0" style="padding-top: 100px"> <div class="position-sticky top-0" style="padding-top: 100px">
<x-checkout.order-summary :subtotal="$subtotal" :total="$total" <x-checkout.order-summary :subtotal="$subtotal" :total="$total" :showEdit="true" :editUrl="route('cart.index')" />
:showEdit="true" :editUrl="route('cart.index')" />
</div> </div>
</aside> </aside>
</div> </div>
@ -203,6 +213,8 @@
@endsection @endsection
@section('scripts') @section('scripts')
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script> <script>
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
// Delivery method selection // Delivery method selection
@ -309,6 +321,9 @@
document.getElementById('longitude').textContent = selectedOption.dataset.longitude || ''; document.getElementById('longitude').textContent = selectedOption.dataset.longitude || '';
document.getElementById('zip').textContent = selectedOption.dataset.postcode || ''; document.getElementById('zip').textContent = selectedOption.dataset.postcode || '';
// Update map with coordinates
updateAddressMap(selectedOption.dataset.latitude, selectedOption.dataset.longitude);
// Update order summary with postcode // Update order summary with postcode
if (selectedOption.dataset.postcode) { if (selectedOption.dataset.postcode) {
updateOrderSummaryWithShipping(); updateOrderSummaryWithShipping();
@ -316,6 +331,69 @@
} }
} }
// Initialize map
let map = null;
let marker = null;
function initializeMap() {
if (typeof L !== 'undefined' && document.getElementById('address-map')) {
// Get initial coordinates from selected address or default to Jakarta
const addressSelect = document.getElementById('addressSelect');
let initialLat = -6.2088; // Default Jakarta latitude
let initialLng = 106.8456; // Default Jakarta longitude
let initialZoom = 13;
if (addressSelect && addressSelect.value && addressSelect.value !== 'new') {
const selectedOption = addressSelect.options[addressSelect.selectedIndex];
const lat = selectedOption.dataset.latitude;
const lng = selectedOption.dataset.longitude;
if (lat && lng) {
initialLat = parseFloat(lat);
initialLng = parseFloat(lng);
initialZoom = 15; // Zoom in closer for specific address
}
}
// Initialize map with address coordinates
map = L.map('address-map').setView([initialLat, initialLng], initialZoom);
// Add OpenStreetMap tiles
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: ' OpenStreetMap contributors'
}).addTo(map);
// Add initial marker if we have coordinates
if (initialLat !== -6.2088 || initialLng !== 106.8456) {
marker = L.marker([initialLat, initialLng]).addTo(map);
}
}
}
function updateAddressMap(lat, lng) {
if (!map || !lat || !lng) return;
const coordinates = [parseFloat(lat), parseFloat(lng)];
// Remove existing marker if any
if (marker) {
map.removeLayer(marker);
}
// Add new marker
marker = L.marker(coordinates).addTo(map);
// Center map on new coordinates
map.setView(coordinates, 15);
}
function clearAddressMap() {
if (marker && map) {
map.removeLayer(marker);
marker = null;
}
}
// Populate on page load // Populate on page load
populateAddressForm(); populateAddressForm();
// Set initial address ID // Set initial address ID
@ -338,33 +416,22 @@
document.getElementById('latitude').textContent = ''; document.getElementById('latitude').textContent = '';
document.getElementById('longitude').textContent = ''; document.getElementById('longitude').textContent = '';
document.getElementById('zip').textContent = ''; document.getElementById('zip').textContent = '';
// Clear map
clearAddressMap();
// Clear address ID input // Clear address ID input
document.getElementById('addressIdInput').value = ''; document.getElementById('addressIdInput').value = '';
} else { } else {
// Populate form fields with selected address // Populate form fields with selected address
document.getElementById('firstName').textContent = selectedOption.dataset populateAddressForm();
.firstName || '';
// document.getElementById('lastName').value = selectedOption.dataset.lastName || '';
document.getElementById('address').textContent = selectedOption.dataset.address ||
'';
document.getElementById('city').textContent = selectedOption.dataset.city || '';
document.getElementById('state').textContent = selectedOption.dataset.state || '';
document.getElementById('zip').textContent = selectedOption.dataset.postcode || '';
document.getElementById('phone').textContent = selectedOption.dataset.phone || '';
document.getElementById('latitude').textContent = selectedOption.dataset.latitude ||
'';
document.getElementById('longitude').textContent = selectedOption.dataset
.longitude || '';
document.getElementById('zip').textContent = selectedOption.dataset.postcode || '';
// Update address ID input // Update address ID input
document.getElementById('addressIdInput').value = this.value; document.getElementById('addressIdInput').value = this.value;
// Update order summary with postcode
if (selectedOption.dataset.postcode) {
updateOrderSummaryWithShipping();
}
} }
}); });
// Initialize map on page load
initializeMap();
} }
// Auto-update order summary when postcode changes // Auto-update order summary when postcode changes
@ -482,7 +549,7 @@
} }
function showShippingCost(cost, isFree = false) { function showShippingCost(cost, isFree = false) {
} }
function validateDeliveryForm() { function validateDeliveryForm() {

View File

@ -2,13 +2,13 @@
<button type="button" class="btn btn-lg btn-secondary w-100 border-0 rounded-pill" data-bs-toggle="dropdown" <button type="button" class="btn btn-lg btn-secondary w-100 border-0 rounded-pill" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false"> aria-haspopup="true" aria-expanded="false">
<i class="ci-grid fs-lg me-2 ms-n1"></i> <i class="ci-grid fs-lg me-2 ms-n1"></i>
Categories {{ __('navbar.categories') }}
<i class="ci-chevron-down fs-lg me-2 ms-auto me-n1"></i> <i class="ci-chevron-down fs-lg me-2 ms-auto me-n1"></i>
</button> </button>
<div class="dropdown-menu rounded-4 p-4" style="--cz-dropdown-spacer: .75rem; margin-left: -75px"> <div class="dropdown-menu rounded-4 p-4" style="--cz-dropdown-spacer: .75rem; margin-left: -75px">
<div class="d-flex gap-4"> <div class="d-flex gap-4">
<div style="min-width: 170px"> <div style="min-width: 170px">
<div class="h6">Kategori</div> <div class="h6">{{ __('navbar.categories') }}</div>
<ul class="nav flex-column gap-2 mt-n2"> <ul class="nav flex-column gap-2 mt-n2">
@foreach ($categories as $category) @foreach ($categories as $category)
@ -24,7 +24,7 @@
</div> </div>
<div style="min-width: 170px"> <div style="min-width: 170px">
<div class="h6">Gender</div> <div class="h6">{{ __('navbar.gender') }}</div>
<ul class="nav flex-column gap-2 mt-n2"> <ul class="nav flex-column gap-2 mt-n2">
@foreach ($genders as $gender) @foreach ($genders as $gender)
<li class="d-flex w-100 pt-1"> <li class="d-flex w-100 pt-1">

View File

@ -57,9 +57,9 @@
<div class="nav me-4 me-xxl-5 d-none d-xl-block"> <div class="nav me-4 me-xxl-5 d-none d-xl-block">
<a class="nav-link flex-column align-items-start animate-underline p-0" href="{{ route('addresses') }}"> <a class="nav-link flex-column align-items-start animate-underline p-0" href="{{ route('addresses') }}">
<div class="h6 fs-sm mb-0">Delivery</div> <div class="h6 fs-sm mb-0">{{ __('navbar.delivery') }}</div>
<div class="d-flex align-items-center fs-sm fw-normal text-body"> <div class="d-flex align-items-center fs-sm fw-normal text-body">
<span class="animate-target text-nowrap">{{ auth()->user()->primary_address->label ?? 'Set your address' }}</span> <span class="animate-target text-nowrap">{{ auth()->user()->primary_address->label ?? __('navbar.set_your_address') }}</span>
<i class="ci-chevron-down fs-base ms-1"></i> <i class="ci-chevron-down fs-base ms-1"></i>
</div> </div>
</a> </a>

View File

@ -99,15 +99,12 @@
<div class=" flex-1"> <div class=" flex-1">
<h1 class="h3">{{ $product->name }}</h1> <h1 class="h3">{{ $product->name }}</h1>
</div> </div>
{{-- wishlist/love button --}} {{-- wishlist/love button --}}
<button type="button" <button type="button" class="btn btn-outline-danger gap-2" style="height: 50px;"
class="btn btn-outline-danger gap-2" id="wishlist-btn" data-item-id="{{ $product->id }}"
style="height: 50px;" data-is-wishlist="{{ $product->isWishlist() ? 'true' : 'false' }}">
id="wishlist-btn"
data-item-id="{{ $product->id }}"
data-is-wishlist="{{ $product->isWishlist() ? 'true' : 'false' }}">
<i class="{{ $product->isWishlist() == true ? 'ci-heart-filled' : 'ci-heart' }}"></i> <i class="{{ $product->isWishlist() == true ? 'ci-heart-filled' : 'ci-heart' }}"></i>
</button> </button>
</div> </div>
@ -118,12 +115,14 @@
class="text-decoration-none text-body-emphasis animate-underline text-xs border border-secondary rounded-pill px-2 py-1" class="text-decoration-none text-body-emphasis animate-underline text-xs border border-secondary rounded-pill px-2 py-1"
style="font-size:10pt;">{{ $product->category->name }}</a> style="font-size:10pt;">{{ $product->category->name }}</a>
<a href="{{ route('product.index', ['filter[brand_id]' => $product->brand->id]) }}" @if ($product->brand?->id != null)
class="text-decoration-none text-body-emphasis animate-underline text-xs border border-secondary rounded-pill px-2 py-1" <a href="{{ route('product.index', ['filter[brand_id]' => $product->brand->id]) }}"
style="font-size:10pt;">{{ $product->brand->name }}</a> class="text-decoration-none text-body-emphasis animate-underline text-xs border border-secondary rounded-pill px-2 py-1"
style="font-size:10pt;">{{ $product->brand->name }}</a>
@endif
</div> </div>
<!-- Description --> <!-- Description -->
<p class="fs-sm mb-0">{!! nl2br(Str::limit($product->description, 500)) !!}</p> <p class="fs-sm mb-0">{!! nl2br(Str::limit($product->description, 500)) !!}</p>
@ -209,8 +208,9 @@
</div> --}} </div> --}}
<!-- Count input + Add to cart button --> <!-- Count input + Add to cart button -->
<x-shop.add-to-cart :item_reference_id="$product->variants->first()->id" /> @if ($product->variants->first()->reference)
<x-shop.add-to-cart :item_reference_id="$product->variants->first()->reference->id" />
@endif
<!-- Info list --> <!-- Info list -->
{{-- <ul class="list-unstyled gap-3 pb-3 pb-lg-4 mb-3"> {{-- <ul class="list-unstyled gap-3 pb-3 pb-lg-4 mb-3">
<li class="d-flex flex-wrap fs-sm"> <li class="d-flex flex-wrap fs-sm">
@ -1061,14 +1061,14 @@
discountSpan.style.display = 'none'; discountSpan.style.display = 'none';
} }
document.querySelector('.product-main-image').src = image; document.querySelector('.product-main-image').src = image;
document.querySelector('.variantOption').textContent = labelText; // document.querySelector('.variantOption').textContent = labelText;
// Update AddToCart component with new variant ID // Update AddToCart component with new variant ID
const addToCartBtn = document.querySelector('[data-item-id]'); const addToCartBtn = document.querySelector('[data-item-reference-id]');
if (addToCartBtn) { if (addToCartBtn) {
console.log(this.value); console.log(this.value);
var item_id = this.value; var item_id = this.value;
addToCartBtn.setAttribute('data-item-id', item_id); addToCartBtn.setAttribute('data-item-reference-id', item_id);
} }
}); });
}); });
@ -1088,95 +1088,100 @@
const isWishlist = this.getAttribute('data-is-wishlist') === 'true'; const isWishlist = this.getAttribute('data-is-wishlist') === 'true';
const icon = this.querySelector('i'); const icon = this.querySelector('i');
const text = this.querySelector('span'); const text = this.querySelector('span');
// Get CSRF token // Get CSRF token
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute(
'content');
if (isWishlist) { if (isWishlist) {
// Remove from wishlist // Remove from wishlist
fetch('/account/wishlist/' + itemId, { fetch('/account/wishlist/' + itemId, {
method: 'DELETE', method: 'DELETE',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-CSRF-TOKEN': token, 'X-CSRF-TOKEN': token,
'X-Requested-With': 'XMLHttpRequest' 'X-Requested-With': 'XMLHttpRequest'
} }
}) })
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
if (data.success) { if (data.success) {
// Update button state // Update button state
this.setAttribute('data-is-wishlist', 'false'); this.setAttribute('data-is-wishlist', 'false');
icon.className = 'ci-heart'; icon.className = 'ci-heart';
text.textContent = 'Add to Wishlist'; text.textContent = 'Add to Wishlist';
// Show success message // Show success message
const successAlert = document.createElement('div'); const successAlert = document.createElement('div');
successAlert.className = 'alert alert-success alert-dismissible fade show position-fixed'; successAlert.className =
successAlert.style.css = 'top: 20px; right: 20px; z-index: 9999; max-width: 300px;'; 'alert alert-success alert-dismissible fade show position-fixed';
successAlert.innerHTML = ` successAlert.style.css =
'top: 20px; right: 20px; z-index: 9999; max-width: 300px;';
successAlert.innerHTML = `
<button type="button" class="btn-close" data-bs-dismiss="alert">&times;</button> <button type="button" class="btn-close" data-bs-dismiss="alert">&times;</button>
Item removed from wishlist! Item removed from wishlist!
`; `;
document.body.appendChild(successAlert); document.body.appendChild(successAlert);
// Auto-hide after 3 seconds // Auto-hide after 3 seconds
setTimeout(() => { setTimeout(() => {
if (successAlert.parentNode) { if (successAlert.parentNode) {
successAlert.parentNode.removeChild(successAlert); successAlert.parentNode.removeChild(successAlert);
} }
}, 3000); }, 3000);
} else { } else {
console.error('Failed to remove from wishlist:', data.message); console.error('Failed to remove from wishlist:', data.message);
} }
}) })
.catch(error => { .catch(error => {
console.error('Error removing from wishlist:', error); console.error('Error removing from wishlist:', error);
}); });
} else { } else {
// Add to wishlist // Add to wishlist
fetch('/account/wishlist', { fetch('/account/wishlist', {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-CSRF-TOKEN': token, 'X-CSRF-TOKEN': token,
'X-Requested-With': 'XMLHttpRequest' 'X-Requested-With': 'XMLHttpRequest'
}, },
body: JSON.stringify({ body: JSON.stringify({
item_id: itemId item_id: itemId
})
}) })
}) .then(response => response.json())
.then(response => response.json()) .then(data => {
.then(data => { if (data.success) {
if (data.success) { // Update button state
// Update button state this.setAttribute('data-is-wishlist', 'true');
this.setAttribute('data-is-wishlist', 'true'); icon.className = 'ci-heart-filled';
icon.className = 'ci-heart-filled'; text.textContent = 'In Wishlist';
text.textContent = 'In Wishlist';
// Show success message
// Show success message const successAlert = document.createElement('div');
const successAlert = document.createElement('div'); successAlert.className =
successAlert.className = 'alert alert-success alert-dismissible fade show position-fixed'; 'alert alert-success alert-dismissible fade show position-fixed';
successAlert.style.css = 'top: 20px; right: 20px; z-index: 9999; max-width: 300px;'; successAlert.style.css =
successAlert.innerHTML = ` 'top: 20px; right: 20px; z-index: 9999; max-width: 300px;';
successAlert.innerHTML = `
<button type="button" class="btn-close" data-bs-dismiss="alert">&times;</button> <button type="button" class="btn-close" data-bs-dismiss="alert">&times;</button>
Item added to wishlist! Item added to wishlist!
`; `;
document.body.appendChild(successAlert); document.body.appendChild(successAlert);
// Auto-hide after 3 seconds // Auto-hide after 3 seconds
setTimeout(() => { setTimeout(() => {
if (successAlert.parentNode) { if (successAlert.parentNode) {
successAlert.parentNode.removeChild(successAlert); successAlert.parentNode.removeChild(successAlert);
} }
}, 3000); }, 3000);
} else { } else {
console.error('Failed to add to wishlist:', data.message); console.error('Failed to add to wishlist:', data.message);
} }
}) })
.catch(error => { .catch(error => {
console.error('Error adding to wishlist:', error); console.error('Error adding to wishlist:', error);
}); });
} }
}); });
} }