diff --git a/app/Http/Controllers/CartController.php b/app/Http/Controllers/CartController.php index b2e0136..592c29a 100644 --- a/app/Http/Controllers/CartController.php +++ b/app/Http/Controllers/CartController.php @@ -35,7 +35,7 @@ class CartController extends Controller public function add(MemberCartRequest $request, MemberCartRepository $repository) { - Log::info($request->all()); + // Log::info($request->all()); $data = $request->validated(); $item = $repository->create($data); diff --git a/app/Http/Controllers/CheckoutController.php b/app/Http/Controllers/CheckoutController.php index 065cdce..80d9530 100644 --- a/app/Http/Controllers/CheckoutController.php +++ b/app/Http/Controllers/CheckoutController.php @@ -9,7 +9,6 @@ use App\Repositories\Member\ShippingRepository; use App\Repositories\Member\Transaction\TransactionRepository; use Illuminate\Http\Request; use Illuminate\Support\Facades\Log; - use Illuminate\Validation\ValidationException; class CheckoutController extends Controller @@ -22,22 +21,18 @@ class CheckoutController extends Controller $subtotal = $memberCartRepository->getSubtotal($request->input('location_id')); - $address_list = Address::where('user_id', auth()->user()->id)->orderBy('is_primary','desc')->get(); - + $address_list = Address::where('user_id', auth()->user()->id)->orderBy('is_primary', 'desc')->get(); $total = $subtotal; - - $carts = $memberCartRepository->getList($request); - return view('checkout.v1-delivery-1', [ 'carts' => $carts, 'subtotal' => $subtotal, 'total' => $total, 'store' => $store, - 'address_list' => $address_list, + 'address_list' => $address_list, ]); } @@ -46,33 +41,33 @@ class CheckoutController extends Controller $delivery_method = $request->input('delivery_method') ?? 'shipping'; $address_id = $request->input('address_id'); - if ($address_id == null) { - $address_list = Address::where('user_id', $request->user()->id)->orderBy('is_primary','desc')->get(); + $address_list = Address::where('user_id', $request->user()->id)->orderBy('is_primary', 'desc')->get(); $address_id = $address_list->first()->id; } if ($delivery_method == null || $address_id == null) { - + return redirect()->back()->with('error', 'Delivery method or address is required'); } if ($delivery_method == 'shipping') { session(['checkout_delivery_method' => $delivery_method]); session(['checkout_address_id' => $address_id]); + return redirect()->route('checkout.shipping'); } if ($delivery_method == 'pickup') { session(['checkout_delivery_method' => $delivery_method]); session(['checkout_address_id' => null]); + return redirect()->route('checkout.payment'); } return redirect()->back()->with('error', 'Delivery method is not valid'); } - public function chooseShipping(Request $request, MemberCartRepository $memberCartRepository, ShippingRepository $shippingRepository) { try { @@ -81,7 +76,6 @@ class CheckoutController extends Controller $location_id = session('location_id', 22); - if ($delivery_method == null || $address_id == null || $location_id == null) { return redirect()->route('checkout.delivery'); @@ -90,37 +84,43 @@ class CheckoutController extends Controller $subtotal = $memberCartRepository->getSubtotal($location_id); $total = $subtotal; - $request->merge(['location_id' => $location_id]); $carts = $memberCartRepository->getList($request); - - try{ + try { $shipping_list = collect($shippingRepository->getList([ - "location_id" => $location_id, - "address_id" => $address_id, - "items" => $carts, - ])['pricing'] ?? [])->map(function($row){ + 'location_id' => $location_id, + 'address_id' => $address_id, + 'items' => $carts, + ])['pricing'] ?? [])->map(function ($row) { return [ - 'courier' => $row['courier_code'], - 'service' => $row['courier_service_code'], - 'title' => $row['courier_name']." - ".$row['courier_service_name'], + 'courier' => $row['courier_code'], + 'service' => $row['courier_service_code'], + 'title' => $row['courier_name'].' - '.$row['courier_service_name'], 'description' => $row['duration'], - 'cost' => $row['shipping_fee'], + 'cost' => $row['shipping_fee'], ]; }); if (count($shipping_list) == 0) { throw ValidationException::withMessages([ - "message" => "Tidak dapat menghitung ongkir" + 'message' => 'Tidak dapat menghitung ongkir', ]); } - }catch(\Exception $e){ + } catch (\Exception $e) { + $message = $e->getMessage(); + + // if contain Failed due to invalid or missing postal code + if (str_contains($message, 'Failed due to invalid or missing postal code')) { + $message = 'Kode pos tidak valid atau tidak ditemukan'; + } else if (str_contains($message, 'support@biteship.com')) { + $message = 'Layanan pengiriman tidak tersedia untuk alamat ini'; + } throw ValidationException::withMessages([ - "message" => $e->getMessage() + 'message' => $message, ]); } - + return view('checkout.v1-delivery-1-shipping', [ 'carts' => $request->user()->carts, 'subtotal' => $subtotal, @@ -132,6 +132,7 @@ class CheckoutController extends Controller ]); } catch (\Exception $e) { Log::info($e); + return redirect()->route('checkout.delivery')->with('error', $e->getMessage() ?? 'Invalid checkout data'); } } @@ -164,6 +165,8 @@ class CheckoutController extends Controller $location_id = session('location_id', 22); + $use_point = session('use_point') ?? 0; + $items = []; $request->merge(['location_id' => $location_id]); @@ -172,25 +175,27 @@ class CheckoutController extends Controller if (count($carts) == 0) { return redirect()->route('checkout.delivery')->with('error', 'No items in cart'); } - + foreach ($carts as $cart) { $items[] = [ - "item_reference_id" => $cart->item_reference_id, - "qty" => $cart->qty + 'item_reference_id' => $cart->item_reference_id, + 'qty' => $cart->qty, ]; } $data = [ - "address_id" => $address_id, - "note" => "", - "courier_company" => $courier, - "courier_type" => $service, - "location_id" => $location_id, - "items" => $items, - "vouchers" => [], - "use_customer_points" => 0, + 'address_id' => $address_id, + 'note' => '', + 'courier_company' => $courier, + 'courier_type' => $service, + 'location_id' => $location_id, + 'items' => $items, + 'vouchers' => [], + 'use_customer_points' => $use_point ?? 0, ]; - + + dd($data); + $item = $repository->create($data); $notification = new \App\Notifications\Member\Transaction\OrderWaitPayment($item); @@ -201,19 +206,20 @@ class CheckoutController extends Controller // proses payment - - $payment = $item->payments()->where("method_type",'App\Models\XenditLink') - ->where("status",'PENDING') - ->first(); - $invoice_url = $payment ? @$payment->method->invoice_url: ""; - - return redirect()->to($invoice_url)->withHeaders([ - 'Cache-Control' => 'no-cache, no-store, must-revalidate', - 'Pragma' => 'no-cache', - 'Expires' => '0' - ]); + $payment = $item->payments()->where('method_type', 'App\Models\XenditLink') + ->where('status', 'PENDING') + ->first(); + $invoice_url = $payment ? @$payment->method->invoice_url : ''; + // reset state session + session()->forget(['checkout_delivery_method', 'checkout_address_id', 'checkout_courier', 'checkout_service', 'use_point']); + + return redirect()->to($invoice_url)->withHeaders([ + 'Cache-Control' => 'no-cache, no-store, must-revalidate', + 'Pragma' => 'no-cache', + 'Expires' => '0', + ]); } catch (\Exception $e) { @@ -222,4 +228,92 @@ class CheckoutController extends Controller return redirect()->route('checkout.delivery')->with('error', 'Invalid checkout data'); } } + + /** + * Apply points to session + */ + public function applyPoint(Request $request) + { + try { + $usePoint = $request->input('use_point'); + + // Validate input + if (!$usePoint || !is_numeric($usePoint) || $usePoint < 0) { + return response()->json([ + 'success' => false, + 'message' => 'Invalid points value' + ]); + } + + $usePoint = (int) $usePoint; + + // Get user's available points + $userPoints = auth()->user()->customer->point ?? 0; + + // Check if user has enough points + if ($usePoint > $userPoints) { + return response()->json([ + 'success' => false, + 'message' => 'You cannot use more points than available' + ]); + } + + // Set points in session + session(['use_point' => $usePoint]); + + return response()->json([ + 'success' => true, + 'message' => 'Points applied successfully', + 'points_applied' => $usePoint, + 'remaining_points' => $userPoints - $usePoint + ]); + + } catch (\Exception $e) { + Log::error('Error applying points: ' . $e->getMessage()); + + return response()->json([ + 'success' => false, + 'message' => 'An error occurred while applying points' + ]); + } + } + + /** + * Remove points from session + */ + public function removePoint(Request $request) + { + try { + // Check if points are currently applied + $currentPoints = session('use_point', 0); + + if ($currentPoints <= 0) { + return response()->json([ + 'success' => false, + 'message' => 'No points are currently applied' + ]); + } + + // Remove points from session + session()->forget('use_point'); + + // Get user's available points + $userPoints = auth()->user()->customer->point ?? 0; + + return response()->json([ + 'success' => true, + 'message' => 'Points removed successfully', + 'points_removed' => $currentPoints, + 'available_points' => $userPoints + ]); + + } catch (\Exception $e) { + Log::error('Error removing points: ' . $e->getMessage()); + + return response()->json([ + 'success' => false, + 'message' => 'An error occurred while removing points' + ]); + } + } } diff --git a/app/Http/Controllers/VoucherEventController.php b/app/Http/Controllers/VoucherEventController.php index 2dc23ce..02ea22d 100644 --- a/app/Http/Controllers/VoucherEventController.php +++ b/app/Http/Controllers/VoucherEventController.php @@ -39,7 +39,7 @@ class VoucherEventController extends Controller // Call the repository's redeem method $result = $this->voucherEventRepository->redeem($voucherEvent, $user); - if ($result['success']) { + if ($result) { return response()->json([ 'success' => true, 'message' => $result['message'] ?? 'Voucher redeemed successfully!', diff --git a/app/Http/Controllers/WishController.php b/app/Http/Controllers/WishController.php new file mode 100644 index 0000000..8295ddf --- /dev/null +++ b/app/Http/Controllers/WishController.php @@ -0,0 +1,84 @@ +wishlistRepository = $wishlistRepository; + } + + /** + * Display the wishlist page + */ + public function index(Request $request) + { + try { + $wishlists = $this->wishlistRepository->getList($request); + + return view('account.wishlist', [ + 'wishlists' => $wishlists, + 'user' => Auth::user() + ]); + } catch (\Exception $e) { + return redirect()->back()->with('error', 'Failed to load wishlist: ' . $e->getMessage()); + } + } + + /** + * Add item to wishlist + */ + public function store(Request $request): JsonResponse + { + $request->validate([ + 'item_id' => 'required|exists:items,id' + ]); + + try { + $wishlist = $this->wishlistRepository->create([ + 'item_id' => $request->item_id + ]); + + return response()->json([ + 'success' => true, + 'message' => 'Item added to wishlist successfully', + 'wishlist' => $wishlist + ]); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => 'Failed to add item to wishlist: ' . $e->getMessage() + ], 500); + } + } + + /** + * Remove item from wishlist + */ + public function destroy(Request $request, $id): JsonResponse + { + try { + + + $this->wishlistRepository->delete($id); + + return response()->json([ + 'success' => true, + 'message' => 'Item removed from wishlist successfully' + ]); + } catch (\Exception $e) { + return response()->json([ + 'success' => false, + 'message' => 'Failed to remove item from wishlist: ' . $e->getMessage() + ], 500); + } + } +} diff --git a/app/Models/ItemReference.php b/app/Models/ItemReference.php index 4853b09..5c2a1b6 100644 --- a/app/Models/ItemReference.php +++ b/app/Models/ItemReference.php @@ -199,4 +199,6 @@ class ItemReference extends Model return $result; } + + } diff --git a/app/Models/Items.php b/app/Models/Items.php index 06e3e2c..18b1be4 100644 --- a/app/Models/Items.php +++ b/app/Models/Items.php @@ -355,4 +355,10 @@ class Items extends Model return 0; } } + + + public function isWishlist() : bool + { + return $this->hasOne(Wishlist::class, 'item_id', 'id')->where('customer_id', auth()->user()->customer->id)->exists(); + } } diff --git a/app/Models/Wishlist.php b/app/Models/Wishlist.php new file mode 100644 index 0000000..56a69c2 --- /dev/null +++ b/app/Models/Wishlist.php @@ -0,0 +1,27 @@ +belongsTo(Customer::class); + } + + public function item(): BelongsTo + { + return $this->belongsTo(Items::class); + } +} diff --git a/app/Repositories/Member/WishlistRepository.php b/app/Repositories/Member/WishlistRepository.php new file mode 100644 index 0000000..83e48a2 --- /dev/null +++ b/app/Repositories/Member/WishlistRepository.php @@ -0,0 +1,75 @@ +user()->id)->first(); + + if (!$customer) { + throw new \Exception('Customer not found'); + } + $limit = 20; + + $wishlist = Wishlist::where('customer_id', $customer->id) + ->with([ + 'item.variants', + + ]) + ->orderBy('created_at', 'desc') + ->paginate($limit); + + return $wishlist; + } + + public function create($data) + { + $model = DB::transaction(function () use ($data) { + $customer = Customer::where('user_id', auth()->user()->id)->first(); + + // Check if item already exists in wishlist + $existing = Wishlist::where('customer_id', $customer->id) + ->where('item_id', $data['item_id']) + ->first(); + + if ($existing) { + return $existing; // Return existing item if already in wishlist + } + + $model = Wishlist::create([ + 'customer_id' => $customer->id, + 'item_id' => $data['item_id'], + ]); + + return $model; + }); + + + return $model; + } + + public function delete($item_id) + { + $wishlist = DB::transaction(function () use ($item_id) { + $wishlist = Wishlist::where('customer_id', auth()->user()->customer->id) + ->where('item_id', $item_id) + ->first(); + + if (!$wishlist) { + throw new \Exception('Wishlist not found'); + } + + $wishlist->delete(); + return $wishlist; + }); + + + return $wishlist; + } +} diff --git a/lang/en/checkout.php b/lang/en/checkout.php index fafb736..c943daf 100644 --- a/lang/en/checkout.php +++ b/lang/en/checkout.php @@ -56,4 +56,16 @@ return [ 'terms_and_conditions' => 'Terms and Conditions', 'close' => 'Close', 'redeem' => 'Redeem', + 'use_point' => 'Use Points', + 'your_points' => 'Your Points', + 'available_points' => 'Available Points', + 'input_point' => 'Enter points to use', + 'apply_point' => 'Apply Points', + 'remove_point' => 'Remove Points', + 'points_applied' => 'Points Applied', + 'points_used' => 'points used', + 'saving' => 'Discount:', + 'shipping' => 'Shipping:', + 'estimated_total' => 'Estimated total:', + 'proceed_to_checkout' => 'Proceed to checkout', ]; diff --git a/lang/id/checkout.php b/lang/id/checkout.php index 2020e48..04e4c3c 100644 --- a/lang/id/checkout.php +++ b/lang/id/checkout.php @@ -50,10 +50,22 @@ return [ 'enter_valid_promo_code' => 'Masukkan kode promo yang valid!', 'apply' => 'Gunakan', 'available_vouchers' => 'Voucher Tersedia', - 'available_voucher_events' => 'Event Voucher Tersedia', + 'available_voucher_events' => 'Tukar Poin', 'points_required' => 'Poin Diperlukan', 'valid_period' => 'Periode Berlaku', 'terms_and_conditions' => 'Syarat dan Ketentuan', 'close' => 'Tutup', 'redeem' => 'Tukar', + 'use_point' => 'Gunakan Poin', + 'your_points' => 'Poin Anda', + 'available_points' => 'Poin Tersedia', + 'input_point' => 'Masukkan poin yang akan digunakan', + 'apply_point' => 'Gunakan Poin', + 'remove_point' => 'Hapus Poin', + 'points_applied' => 'Poin Diterapkan', + 'points_used' => 'poin digunakan', + 'saving' => 'Diskon:', + 'shipping' => 'Pengiriman:', + 'estimated_total' => 'Total estimasi:', + 'proceed_to_checkout' => 'Lanjut ke checkout', ]; diff --git a/resources/views/account/wishlist.blade.php b/resources/views/account/wishlist.blade.php index 0531122..8761d6f 100644 --- a/resources/views/account/wishlist.blade.php +++ b/resources/views/account/wishlist.blade.php @@ -7,15 +7,15 @@

Wishlist

- --}}
-
+ {{--
Interesting offers
@@ -69,9 +69,9 @@
-
+
--}} - --}}
- -
-
-
-
-
- -
-
- - -21% -
- VR Glasses -
-
-
-
-
-
- - - - - -
- (123) -
-

- - VRB01 Virtual Reality Glasses - -

-
-
$340.99 $430.00
- -
-
-
-
- -
-
-
-
-
- -
-
- -
- iPhone 14 -
-
-
-
-
-
- - - - - -
- (142) -
-

- - Apple iPhone 14 128GB White - -

-
-
$899.00
- -
-
-
-
- -
-
-
-
-
- -
-
- -
- Smart Watch -
-
-
-
-
-
- - - - - -
- (67) -
-

- - Smart Watch Series 7, White - -

-
-
$429.00
- -
-
-
-
- -
-
-
-
-
- -
-
- -
- iPad Air -
-
-
-
-
-
- - - - - -
- (12) -
-

- - Tablet Apple iPad Air M1 - -

-
-
$540.00
- -
-
-
-
- -
-
-
-
-
- -
-
- -
- AirPods 2 -
-
-
-
-
-
- - - - - -
- (78) -
-

- - Headphones Apple AirPods 2 Pro - -

-
-
$224.00
- -
-
-
-
+ + @foreach ($wishlists as $key => $value) + @include('components.home.product-card', ['product' => $value->item]) + @endforeach +
diff --git a/resources/views/checkout/v1-cart.blade.php b/resources/views/checkout/v1-cart.blade.php index 3aee0c1..8a2a074 100644 --- a/resources/views/checkout/v1-cart.blade.php +++ b/resources/views/checkout/v1-cart.blade.php @@ -186,26 +186,26 @@ Rp 0
  • - Saving: - Rp 0 + {{ __('checkout.saving') }} + Rp {{ number_format(session('use_point') ?? 0,0,",",".") }}
  • {{-- --}}
  • - Shipping: + {{ __('checkout.shipping') }} Calculated at checkout
  • - Estimated total: + {{ __('checkout.estimated_total') }} $0.00
    - Proceed to checkout + {{ __('checkout.proceed_to_checkout') }} {{--
    - + {{-- --}} + @endif @@ -1039,7 +1040,7 @@ } // Calculate estimated total (subtotal - savings + tax) - const savings = 0; // Fixed savings amount + const savings = {{ session('use_point') ?? 0 }}; // Fixed savings amount const tax = 0; // Fixed tax amount const estimatedTotal = subtotal - savings + tax; diff --git a/resources/views/checkout/v1-delivery-1-shipping.blade.php b/resources/views/checkout/v1-delivery-1-shipping.blade.php index beec72c..881f742 100644 --- a/resources/views/checkout/v1-delivery-1-shipping.blade.php +++ b/resources/views/checkout/v1-delivery-1-shipping.blade.php @@ -84,7 +84,7 @@ @@ -113,6 +113,7 @@ }); function updateOrderSummaryWithShippingCost(shippingValue) { + const saving = {{ session('use_point') ?? 0 }}; console.log('updateOrderSummaryWithShippingCost called with:', shippingValue); // Parse the shipping value: courier|service|cost @@ -138,7 +139,7 @@ const currentSubtotal = parseFloat(subtotalElement.textContent.replace(/[^\d]/g, '')); console.log('Current subtotal:', currentSubtotal); - const newTotal = currentSubtotal + cost; + const newTotal = currentSubtotal + cost - saving; console.log('New total:', newTotal); // Store original total diff --git a/resources/views/checkout/v1-delivery-1.blade.php b/resources/views/checkout/v1-delivery-1.blade.php index 4d856ad..6ebed3d 100644 --- a/resources/views/checkout/v1-delivery-1.blade.php +++ b/resources/views/checkout/v1-delivery-1.blade.php @@ -191,7 +191,7 @@ @@ -428,11 +428,12 @@ function updateOrderSummaryWithShipping() { // Simulate shipping cost calculation based on postcode const shippingCost = calculateShippingCost(document.getElementById('zip').value); + const saving = {{ session('use_point') ?? 0 }}; // Update order summary const subtotalElement = document.getElementById('cart-subtotal'); const currentSubtotal = parseFloat(subtotalElement.textContent.replace(/[^\d]/g, '')); - const newTotal = currentSubtotal + shippingCost; + const newTotal = currentSubtotal + 0 - saving; // Store original total if (!window.originalTotal) { @@ -481,40 +482,15 @@ } function showShippingCost(cost, isFree = false) { - // Find or create shipping cost element in order summary - let shippingElement = document.querySelector('[data-shipping-cost]'); - - if (!shippingElement) { - const orderSummary = document.querySelector('.list-unstyled'); - const shippingLi = document.createElement('li'); - shippingLi.className = 'd-flex justify-content-between'; - shippingLi.setAttribute('data-shipping-cost', ''); - shippingLi.innerHTML = ` - {{ __('checkout.shipping') }}: - Rp 0 - `; - orderSummary.appendChild(shippingLi); - shippingElement = shippingLi; - } - - const costElement = document.getElementById('shipping-cost'); - if (isFree) { - costElement.textContent = '{{ __('checkout.free') }}'; - costElement.className = 'text-success fw-medium'; - } else { - costElement.textContent = `Rp ${number_format(cost, 0, ',', '.')}`; - costElement.className = 'text-dark-emphasis fw-medium'; - } - - shippingElement.style.display = 'flex'; + } function validateDeliveryForm() { - const postcode = document.getElementById('zip').value; - const firstName = document.getElementById('firstName').value; - const address = document.getElementById('address').value; - const city = document.getElementById('city').value; - const phone = document.getElementById('phone').value; + const postcode = document.getElementById('zip').textContent; + const firstName = document.getElementById('firstName').textContent; + const address = document.getElementById('address').textContent; + const city = document.getElementById('city').textContent; + const phone = document.getElementById('phone').textContent; if (!postcode) { alert('{{ __('checkout.enter_postcode') }}'); diff --git a/resources/views/components/checkout/order-summary.blade.php b/resources/views/components/checkout/order-summary.blade.php index 7839e5d..3eb2579 100644 --- a/resources/views/components/checkout/order-summary.blade.php +++ b/resources/views/components/checkout/order-summary.blade.php @@ -1,7 +1,7 @@ @props([ 'subtotal' => 0, 'total' => 0, - 'savings' => 0, + 'savings' => session('use_point'), 'tax' => 0, 'showEdit' => false, 'editUrl' => null, @@ -36,9 +36,7 @@
    • -
      {{ __('cart_summary.subtotal') }} ( - {{ __('cart_summary.items_count', ['count' => auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0]) }}): -
      +
      {{ __('cart_summary.subtotal') }} ({{ __('cart_summary.items_count', ['count' => auth()->check() ? \App\Repositories\Member\Cart\MemberCartRepository::getCount() : 0]) }})
      Rp {{ number_format($subtotal, 0, ',', '.') }}
    • diff --git a/resources/views/components/checkout/promo-code.blade.php b/resources/views/components/checkout/promo-code.blade.php index 0f9abd4..35d8389 100644 --- a/resources/views/components/checkout/promo-code.blade.php +++ b/resources/views/components/checkout/promo-code.blade.php @@ -48,8 +48,13 @@
      @foreach($vouchers as $voucher) - - {{ $voucher->code }} + + {{ $voucher->description }} @endforeach
      @@ -187,6 +192,84 @@ document.addEventListener('DOMContentLoaded', function () { }); + // Handle promo code form submission + document.addEventListener('submit', function(e) { + const form = e.target; + + // Check if this is the promo code form + if (!form || !form.classList.contains('needs-validation')) { + return; + } + + e.preventDefault(); + + const promoInput = form.querySelector('input[placeholder="{{ __('checkout.enter_promo_code') }}"]'); + const submitBtn = form.querySelector('button[type="submit"]'); + const originalText = submitBtn.textContent; + + if (!promoInput || !promoInput.value.trim()) { + alert('Please enter a promo code'); + return; + } + + // Show loading state + submitBtn.disabled = true; + submitBtn.textContent = 'Applying...'; + + // Get CSRF token + const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content'); + + // Submit voucher code to server + fetch('/apply-voucher', { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'X-CSRF-TOKEN': token, + 'X-Requested-With': 'XMLHttpRequest' + }, + body: new URLSearchParams({ + 'promo_code': promoInput.value.trim() + }).toString() + }) + .then(response => response.json()) + .then(data => { + if (data.success) { + // Show success message + alert('Voucher applied successfully!'); + + // Clear input + promoInput.value = ''; + + // Add visual feedback + promoInput.style.backgroundColor = '#d4edda'; + promoInput.style.borderColor = '#28a745'; + + // Remove visual feedback after 2 seconds + setTimeout(() => { + promoInput.style.backgroundColor = ''; + promoInput.style.borderColor = ''; + }, 2000); + + // Reload page to show updated cart + setTimeout(() => { + window.location.reload(); + }, 1000); + } else { + // Show error message + alert(data.message || 'Failed to apply voucher'); + } + }) + .catch(error => { + console.error('Error applying voucher:', error); + alert('An error occurred while applying the voucher'); + }) + .finally(() => { + // Restore button state + submitBtn.disabled = false; + submitBtn.textContent = originalText; + }); + }); + // Handle redeem button click document.getElementById('redeemVoucherBtn').addEventListener('click', function() { const voucherEventId = this.getAttribute('data-voucher-event-id'); @@ -215,14 +298,7 @@ document.addEventListener('DOMContentLoaded', function () { // Show success message alert('Voucher redeemed successfully!'); - // Close modal - const modal = bootstrap.Modal.getInstance(document.getElementById('voucherEventModal')); - modal.hide(); - - // Reload page to update cart - setTimeout(() => { - window.location.reload(); - }, 1000); + window.location.reload(); } else { // Show error message alert(data.message || 'Failed to redeem voucher'); @@ -259,6 +335,34 @@ document.addEventListener('DOMContentLoaded', function () { }); }); + // Function to apply voucher code when badge is clicked + function applyVoucher(voucherCode) { + // Find the promo code input + const promoInput = document.querySelector('input[placeholder="{{ __('checkout.enter_promo_code') }}"]'); + + if (promoInput) { + // Set the voucher code + promoInput.value = voucherCode; + + // Add visual feedback + promoInput.style.backgroundColor = '#d4edda'; + promoInput.style.borderColor = '#28a745'; + + // Remove visual feedback after 2 seconds + setTimeout(() => { + promoInput.style.backgroundColor = ''; + promoInput.style.borderColor = ''; + }, 2000); + + // Focus on the input + promoInput.focus(); + + // Optionally submit the form automatically + // Uncomment the next line if you want auto-submission + // promoInput.closest('form').requestSubmit(); + } + } + }); \ No newline at end of file diff --git a/resources/views/components/checkout/use-point.blade.php b/resources/views/components/checkout/use-point.blade.php new file mode 100644 index 0000000..39c439e --- /dev/null +++ b/resources/views/components/checkout/use-point.blade.php @@ -0,0 +1,451 @@ +
      +
      +

      + +

      + +
      + +
      + + {{-- Your Points --}} +
      + +
      +
      +

      {{ number_format(auth()->user()->customer->point, 0, ",",".") }}

      + {{ __('checkout.available_points') }} +
      + +
      +
      + + {{-- Points Form --}} + @if(session('use_point')) + {{-- Points Applied Display --}} +
      +
      +
      {{ __('checkout.points_applied') }}
      +

      + {{ number_format(session('use_point'), 0, ",", ".") }} {{ __('checkout.points_used') }} +

      +
      + +
      + @else + {{-- Apply Points Form --}} +
      +
      + +
      + +
      + @endif + + + +
      +
      +
      +
      + + + +{{-- SINGLE REUSABLE MODAL --}} + + + + + \ No newline at end of file diff --git a/resources/views/components/home/product-card.blade.php b/resources/views/components/home/product-card.blade.php index dee9213..c765aa5 100644 --- a/resources/views/components/home/product-card.blade.php +++ b/resources/views/components/home/product-card.blade.php @@ -33,8 +33,8 @@ @endif
      - @if ($product->variants->count() > 1) -
      +{{ $product->variants->count() - 1 }} Varian
      + @if (($product->variants?->count() ?? 0) > 1) +
      +{{ ($product->variants->count() ?? 0) - 1 }} Varian
      @endif {{--
      +1 color
      --}} {{--
      diff --git a/resources/views/components/layout/header-grocery.blade.php b/resources/views/components/layout/header-grocery.blade.php index 86b3d56..136283b 100644 --- a/resources/views/components/layout/header-grocery.blade.php +++ b/resources/views/components/layout/header-grocery.blade.php @@ -27,13 +27,19 @@
      - - +
      + + +
      @@ -159,9 +165,15 @@ @@ -169,3 +181,46 @@ + + diff --git a/resources/views/components/shop/add-to-cart.blade.php b/resources/views/components/shop/add-to-cart.blade.php index 1266610..3dd5437 100644 --- a/resources/views/components/shop/add-to-cart.blade.php +++ b/resources/views/components/shop/add-to-cart.blade.php @@ -133,6 +133,7 @@ showLoginDialog(); } else { // You could show an error message here + alert(error.message); } } } catch (error) { diff --git a/resources/views/layouts/partials/account-sidebar.blade.php b/resources/views/layouts/partials/account-sidebar.blade.php index ad3e980..3de21cb 100644 --- a/resources/views/layouts/partials/account-sidebar.blade.php +++ b/resources/views/layouts/partials/account-sidebar.blade.php @@ -51,7 +51,7 @@ {{-- 1 --}} + href="{{ route('wishlist.index') }}"> {{ __('account_sidebar.wishlist') }} diff --git a/resources/views/shop/product-fashion.blade.php b/resources/views/shop/product-fashion.blade.php index a373ea9..7d15262 100644 --- a/resources/views/shop/product-fashion.blade.php +++ b/resources/views/shop/product-fashion.blade.php @@ -1,9 +1,6 @@ @extends('layouts.landing', ['title' => $product->name ?? 'Detail']) @section('content') - - -
      @@ -73,9 +70,9 @@
      @@ -98,17 +95,35 @@ --}} -

      {{ $product->name }}

      +
      +
      +

      {{ $product->name }}

      +
      + + {{-- wishlist/love button --}} + +
      {{-- add category --}} + {{ $product->category->name }} + + {{ $product->brand->name }} + + +

      {!! nl2br(Str::limit($product->description, 500)) !!}

      @@ -144,8 +159,8 @@ @foreach ($product->variants as $key => $variant) + value="{{ $variant->reference->id }}" id="variant-id-{{ $variant->id }}" + {{ $key == 0 ? 'checked' : '' }}>