cart
This commit is contained in:
parent
a86ba91db7
commit
8c21d4dc7c
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\Member\Cart\MemberCartRequest;
|
||||
use App\Http\Requests\Member\Cart\UpdateMemberCartRequest;
|
||||
use App\Models\Cart;
|
||||
use App\Repositories\Member\Cart\MemberCartRepository;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class CartController extends Controller
|
||||
{
|
||||
public function count(Request $request, MemberCartRepository $repository)
|
||||
{
|
||||
$count = $repository->getCount($request->input('location_id'));
|
||||
|
||||
return response()->json([
|
||||
'count' => $count
|
||||
]);
|
||||
}
|
||||
|
||||
public function index(Request $request, MemberCartRepository $repository)
|
||||
{
|
||||
|
||||
$request->merge(['location_id' => $request->input('location_id', session('location_id', 22))]);
|
||||
|
||||
$carts = $repository->getList($request);
|
||||
|
||||
// Log::info($items);
|
||||
return view('checkout.v1-cart',[
|
||||
'carts' => $carts
|
||||
]);
|
||||
}
|
||||
|
||||
public function add(MemberCartRequest $request, MemberCartRepository $repository)
|
||||
{
|
||||
Log::info($request->all());
|
||||
$data = $request->validated();
|
||||
$item = $repository->create($data);
|
||||
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Item added to cart successfully',
|
||||
'item' => $item
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route('cart.index');
|
||||
}
|
||||
|
||||
public function update($cart_id, UpdateMemberCartRequest $request, MemberCartRepository $repository)
|
||||
{
|
||||
$data = $request->validated();
|
||||
$item = $repository->update($cart_id, $data);
|
||||
|
||||
if ($request->expectsJson()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Cart updated successfully',
|
||||
'item' => $item
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route('cart.index');
|
||||
}
|
||||
|
||||
public function delete($cart_id, MemberCartRepository $repository)
|
||||
{
|
||||
$repository->delete($cart_id);
|
||||
|
||||
if (request()->expectsJson()) {
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Item removed from cart successfully'
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route('cart.index');
|
||||
}
|
||||
}
|
||||
|
|
@ -24,15 +24,15 @@ class ProductController extends Controller
|
|||
foreach ($genders as $gender) {
|
||||
$isActive = $currentGenderId == $gender->id;
|
||||
$genderHtml .= '<li class="nav-item mb-1">';
|
||||
$genderHtml .= '<a class="nav-link d-block fw-normal p-0 ' . ($isActive ? 'active text-primary' : '') . '" ';
|
||||
$genderHtml .= 'href="#" data-gender-id="' . $gender->id . '">';
|
||||
$genderHtml .= '<a class="nav-link d-block fw-normal p-0 '.($isActive ? 'active text-primary' : '').'" ';
|
||||
$genderHtml .= 'href="#" data-gender-id="'.$gender->id.'">';
|
||||
$genderHtml .= $gender->name;
|
||||
$genderHtml .= '</a></li>';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'genders' => $genderHtml
|
||||
'genders' => $genderHtml,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -48,15 +48,15 @@ class ProductController extends Controller
|
|||
foreach ($categories as $category) {
|
||||
$isActive = $currentCategoryId == $category->id;
|
||||
$categoryHtml .= '<li class="nav-item mb-1">';
|
||||
$categoryHtml .= '<a class="nav-link d-block fw-normal p-0 ' . ($isActive ? 'active text-primary' : '') . '" ';
|
||||
$categoryHtml .= 'href="#" data-category-id="' . $category->id . '">';
|
||||
$categoryHtml .= '<a class="nav-link d-block fw-normal p-0 '.($isActive ? 'active text-primary' : '').'" ';
|
||||
$categoryHtml .= 'href="#" data-category-id="'.$category->id.'">';
|
||||
$categoryHtml .= $category->name;
|
||||
$categoryHtml .= '</a></li>';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'categories' => $categoryHtml
|
||||
'categories' => $categoryHtml,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -123,7 +123,7 @@ class ProductController extends Controller
|
|||
|
||||
// filter
|
||||
$filter = $request->filter ?? [];
|
||||
if (isset($filter['category']) && $filter['category']){
|
||||
if (isset($filter['category']) && $filter['category']) {
|
||||
$category = StoreCategory::find($filter['category']);
|
||||
|
||||
if ($category) {
|
||||
|
|
@ -161,7 +161,7 @@ class ProductController extends Controller
|
|||
'products' => $productHtml,
|
||||
'count' => count($products),
|
||||
'has_more' => $hasMore,
|
||||
'current_page' => $page
|
||||
'current_page' => $page,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -170,16 +170,12 @@ class ProductController extends Controller
|
|||
$productRepository = new ProductRepository;
|
||||
$products = [];
|
||||
|
||||
|
||||
|
||||
$filters = [];
|
||||
|
||||
$min_max_price = $productRepository->getMinMaxPrice();
|
||||
|
||||
|
||||
return view('shop.catalog-fashion', [
|
||||
|
||||
|
||||
'products' => $products,
|
||||
'min_max_price' => $min_max_price,
|
||||
]);
|
||||
|
|
@ -197,15 +193,15 @@ class ProductController extends Controller
|
|||
foreach ($brands as $brand) {
|
||||
$isActive = $currentBrandId == $brand->id;
|
||||
$brandHtml .= '<li class="nav-item mb-1">';
|
||||
$brandHtml .= '<a class="nav-link d-block fw-normal p-0 ' . ($isActive ? 'active text-primary' : '') . '" ';
|
||||
$brandHtml .= 'href="#" data-brand-id="' . $brand->id . '">';
|
||||
$brandHtml .= '<a class="nav-link d-block fw-normal p-0 '.($isActive ? 'active text-primary' : '').'" ';
|
||||
$brandHtml .= 'href="#" data-brand-id="'.$brand->id.'">';
|
||||
$brandHtml .= $brand->name;
|
||||
$brandHtml .= '</a></li>';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'brands' => $brandHtml
|
||||
'brands' => $brandHtml,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -216,31 +212,31 @@ class ProductController extends Controller
|
|||
[
|
||||
'icon' => '🎉',
|
||||
'message' => 'Free Shipping on orders over $250',
|
||||
'detail' => "Don't miss a discount!"
|
||||
'detail' => "Don't miss a discount!",
|
||||
],
|
||||
[
|
||||
'icon' => '💰',
|
||||
'message' => 'Money back guarantee',
|
||||
'detail' => 'We return money within 30 days'
|
||||
'detail' => 'We return money within 30 days',
|
||||
],
|
||||
[
|
||||
'icon' => '💪',
|
||||
'message' => 'Friendly 24/7 customer support',
|
||||
'detail' => "We've got you covered!"
|
||||
]
|
||||
'detail' => "We've got you covered!",
|
||||
],
|
||||
];
|
||||
|
||||
// Render announcement slides HTML
|
||||
$announcementHtml = '';
|
||||
foreach ($announcements as $announcement) {
|
||||
$announcementHtml .= '<div class="swiper-slide text-truncate text-center">';
|
||||
$announcementHtml .= $announcement['icon'] . ' ' . $announcement['message'] . ' <span class="d-none d-sm-inline">' . $announcement['detail'] . '</span>';
|
||||
$announcementHtml .= $announcement['icon'].' '.$announcement['message'].' <span class="d-none d-sm-inline">'.$announcement['detail'].'</span>';
|
||||
$announcementHtml .= '</div>';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'announcements' => $announcementHtml
|
||||
'announcements' => $announcementHtml,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +309,7 @@ class ProductController extends Controller
|
|||
'success' => true,
|
||||
'products' => $productHtml,
|
||||
'count' => count($products),
|
||||
'type' => $type
|
||||
'type' => $type,
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Member\Cart;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class MemberCartRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'item_reference_id' => 'required|integer|exists:item_reference,id',
|
||||
'qty' => 'required|numeric|min:0',
|
||||
'location_id' => 'required|numeric',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests\Member\Cart;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UpdateMemberCartRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'qty' => 'required|numeric|min:0'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Cart extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
protected $fillable = ['item_id', 'price','is_checked', 'item_variant_id', 'item_reference_id', 'user_id', 'qty','location_id'];
|
||||
|
||||
public function item()
|
||||
{
|
||||
return $this->belongsTo(Items::class,"item_id");
|
||||
}
|
||||
|
||||
public function itemVariant()
|
||||
{
|
||||
return $this->belongsTo(ItemVariant::class, 'item_variant_id', 'id');
|
||||
}
|
||||
|
||||
public function itemReference()
|
||||
{
|
||||
return $this->belongsTo(ItemReference::class, 'item_reference_id', 'id');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'user_id', 'id');
|
||||
}
|
||||
|
||||
|
||||
public function getDisplayPriceAttribute()
|
||||
{
|
||||
return $this->itemVariant->reference->item->display_price;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
|
||||
class Categories extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use LogsActivity;
|
||||
|
||||
public function getActivitylogOptions(): LogOptions
|
||||
{
|
||||
return LogOptions::defaults();
|
||||
}
|
||||
|
||||
protected $table = 'categories';
|
||||
protected $primaryKey = 'id';
|
||||
|
||||
protected $fillable = [
|
||||
'code',
|
||||
'name',
|
||||
'image',
|
||||
'is_publish'
|
||||
];
|
||||
}
|
||||
|
|
@ -72,7 +72,10 @@ class ItemVariant extends Model
|
|||
return $this->belongsTo(Items::class, 'item_id');
|
||||
}
|
||||
|
||||
|
||||
public function getDisplayPriceAttribute()
|
||||
{
|
||||
return $this->reference->item->display_price;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace App\Repositories\Member\Cart;
|
||||
|
||||
use App\Models\Cart;
|
||||
use App\Models\ItemReference;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class MemberCartRepository
|
||||
{
|
||||
static public function getCount($locationId = null)
|
||||
{
|
||||
$location = $locationId ?? session('location_id', 22);
|
||||
return Cart::where('user_id', auth()->user()->id)
|
||||
->where('location_id', $location)
|
||||
->count();
|
||||
}
|
||||
|
||||
public function getList($request)
|
||||
{
|
||||
$location = (int) $request->input("location_id");
|
||||
$cart = Cart::where('user_id', auth()->user()->id)
|
||||
->where("location_id", $location)
|
||||
->orderBy('created_at','desc')
|
||||
->paginate($request->limit ?? 1000);
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
||||
public function create($data)
|
||||
{
|
||||
$model = DB::transaction(function () use ($data) {
|
||||
$location = (int) @$data["location_id"];
|
||||
$itemreference = ItemReference::findOrfail($data['item_reference_id']);
|
||||
|
||||
$model = Cart::where('item_reference_id', $data['item_reference_id'])
|
||||
->where('location_id', $location)
|
||||
->where('user_id', auth()->user()->id)->first();
|
||||
if ($model) {
|
||||
$model->qty = $model->qty + $data['qty'];
|
||||
$model->save();
|
||||
} else {
|
||||
$model = Cart::create([
|
||||
'item_id' => $itemreference->item_id,
|
||||
'item_variant_id' => $itemreference->item_variant_id,
|
||||
'location_id' => $data['location_id'],
|
||||
'item_reference_id' => $data['item_reference_id'],
|
||||
'user_id' => auth()->user()->id,
|
||||
'qty' => $data['qty']
|
||||
]);
|
||||
}
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function update($cartId, $data)
|
||||
{
|
||||
$cart = DB::transaction(function () use ($cartId, $data) {
|
||||
$cart = Cart::find($cartId);
|
||||
|
||||
if (!$cart) {
|
||||
throw new \Exception('Cart item not found');
|
||||
}
|
||||
|
||||
$cart->qty = $data['qty'] ?? $cart->qty;
|
||||
$cart->save();
|
||||
|
||||
return $cart;
|
||||
});
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
||||
public function delete($cartId)
|
||||
{
|
||||
$cart = DB::transaction(function () use ($cartId) {
|
||||
$cart = Cart::find($cartId);
|
||||
$cart->delete();
|
||||
return $cart;
|
||||
});
|
||||
|
||||
return $cart;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -2,151 +2,10 @@
|
|||
|
||||
@section('content')
|
||||
<!-- Authentication offcanvas -->
|
||||
<div class="offcanvas offcanvas-end pb-sm-2 px-sm-2" id="authForm" tabindex="-1" aria-labelledby="authFormLabel"
|
||||
style="width: 500px">
|
||||
<div class="offcanvas-header flex-column align-items-start py-3 pt-lg-4">
|
||||
<div class="d-flex align-items-center justify-content-between w-100 mb-3 mb-lg-4">
|
||||
<h4 class="offcanvas-title" id="authFormLabel">Login to continue</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<ul class="nav nav-underline" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button type="button" class="nav-link" id="login-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#login-tab-pane" role="tab" aria-controls="login-tab-pane"
|
||||
aria-selected="false">
|
||||
Login
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button type="button" class="nav-link active" id="register-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#register-tab-pane" role="tab" aria-controls="register-tab-pane"
|
||||
aria-selected="true">
|
||||
Register
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="offcanvas-body tab-content pt-2">
|
||||
|
||||
<!-- Login form -->
|
||||
<div class="tab-pane fade" id="login-tab-pane" role="tabpanel" aria-labelledby="login-tab">
|
||||
<form class="needs-validation" novalidate>
|
||||
<div class="position-relative mb-4">
|
||||
<label for="login-email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control form-control-lg" id="login-email" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Enter a valid email address!</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="login-password" class="form-label">Password</label>
|
||||
<div class="password-toggle">
|
||||
<input type="password" class="form-control form-control-lg" id="login-password" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Password is incorrect!</div>
|
||||
<label class="password-toggle-button fs-lg" aria-label="Show/hide password">
|
||||
<input type="checkbox" class="btn-check">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<div class="form-check me-2">
|
||||
<input type="checkbox" class="form-check-input" id="remember-30">
|
||||
<label for="remember-30" class="form-check-label">Remember for 30 days</label>
|
||||
</div>
|
||||
<div class="nav">
|
||||
<a class="nav-link animate-underline p-0" href="{{ route('second', ['account', 'password-recovery']) }}">
|
||||
<span class="animate-target">Forgot password?</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg btn-primary w-100">
|
||||
Login to your account
|
||||
<i class="ci-chevron-right fs-lg ms-1 me-n1"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Register form -->
|
||||
<div class="tab-pane fade show active" id="register-tab-pane" role="tabpanel" aria-labelledby="register-tab">
|
||||
<form class="needs-validation" novalidate>
|
||||
<div class="position-relative mb-4">
|
||||
<label for="register-email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control form-control-lg" id="register-email" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Enter a valid email address!</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="register-password" class="form-label">Password</label>
|
||||
<div class="password-toggle">
|
||||
<input type="password" class="form-control form-control-lg" id="register-password"
|
||||
minlength="8" placeholder="Minimum 8 characters" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Password does not meet the required criteria!
|
||||
</div>
|
||||
<label class="password-toggle-button fs-lg" aria-label="Show/hide password">
|
||||
<input type="checkbox" class="btn-check">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-column gap-2 mb-4">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="save-pass">
|
||||
<label for="save-pass" class="form-check-label">Save the password</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="privacy" required>
|
||||
<label for="privacy" class="form-check-label">I have read and accept the <a
|
||||
class="text-dark-emphasis" href="#!">Privacy Policy</a></label>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg btn-primary w-100">
|
||||
Create an account
|
||||
<i class="ci-chevron-right fs-lg ms-1 me-n1"></i>
|
||||
</button>
|
||||
<div class="pt-5">
|
||||
<h6>AsiaGolf account benefits</h6>
|
||||
<ul class="list-unstyled d-flex flex-column gap-2 fs-sm mb-0">
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-mail fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Subscribe to your favorite products</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-settings fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">View and manage your orders and withlist</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-gift fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Earn rewards for future purchases</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-percent fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Receive exclusive offers and discounts</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-heart fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Create multiple wishlists</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('layouts.partials/offcanvas')
|
||||
|
||||
@include('layouts.partials/navbar', ['wishlist' => true])
|
||||
<x-layout.header />
|
||||
|
||||
<main class="content-wrapper">
|
||||
|
||||
|
|
@ -168,7 +27,7 @@
|
|||
<!-- Items list -->
|
||||
<div class="col-lg-8">
|
||||
<div class="pe-lg-2 pe-xl-3 me-xl-3">
|
||||
<p class="fs-sm">Buy <span class="text-dark-emphasis fw-semibold">$183</span> more to get <span
|
||||
{{-- <p class="fs-sm">Buy <span class="text-dark-emphasis fw-semibold">$183</span> more to get <span
|
||||
class="text-dark-emphasis fw-semibold">Free Shipping</span></p>
|
||||
<div class="progress w-100 overflow-visible mb-4" role="progressbar"
|
||||
aria-label="Free shipping progress" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"
|
||||
|
|
@ -180,7 +39,7 @@
|
|||
<i class="ci-star-filled text-warning"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<!-- Table of items -->
|
||||
<table class="table position-relative z-2 mb-4">
|
||||
|
|
@ -205,99 +64,37 @@
|
|||
</thead>
|
||||
<tbody class="align-middle">
|
||||
|
||||
<!-- Item -->
|
||||
@foreach ($carts as $key => $cart)
|
||||
<tr>
|
||||
<td class="py-3 ps-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<a class="flex-shrink-0" href="{{ route('second', ['shop', 'product-general-electronics']) }}">
|
||||
<img src="/img/shop/electronics/thumbs/08.png" width="110"
|
||||
alt="iPhone 14">
|
||||
</a>
|
||||
<div class="w-100 min-w-0 ps-2 ps-xl-3">
|
||||
<h5 class="d-flex animate-underline mb-2">
|
||||
<a class="d-block fs-sm fw-medium text-truncate animate-target"
|
||||
href="{{ route('second', ['shop', 'product-general-electronics']) }}">Apple iPhone 14
|
||||
128GB</a>
|
||||
</h5>
|
||||
<ul class="list-unstyled gap-1 fs-xs mb-0">
|
||||
<li><span class="text-body-secondary">Color:</span> <span
|
||||
class="text-dark-emphasis fw-medium">White</span></li>
|
||||
<li><span class="text-body-secondary">Model:</span> <span
|
||||
class="text-dark-emphasis fw-medium">128GB</span></li>
|
||||
<li class="d-xl-none"><span class="text-body-secondary">Price:</span>
|
||||
<span class="text-dark-emphasis fw-medium">$899.00</span></li>
|
||||
</ul>
|
||||
<div class="count-input rounded-2 d-md-none mt-3">
|
||||
<button type="button" class="btn btn-sm btn-icon" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control form-control-sm"
|
||||
value="1" readonly>
|
||||
<button type="button" class="btn btn-sm btn-icon" data-increment
|
||||
aria-label="Increment quantity">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="h6 py-3 d-none d-xl-table-cell">$899.00</td>
|
||||
<td class="py-3 d-none d-md-table-cell">
|
||||
<div class="count-input">
|
||||
<button type="button" class="btn btn-icon" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control" value="1" readonly>
|
||||
<button type="button" class="btn btn-icon" data-increment
|
||||
aria-label="Increment quantity">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="h6 py-3 d-none d-md-table-cell">$899.00</td>
|
||||
<td class="text-end py-3 px-0">
|
||||
<button type="button" class="btn-close fs-sm" data-bs-toggle="tooltip"
|
||||
data-bs-custom-class="tooltip-sm" data-bs-title="Remove"
|
||||
aria-label="Remove from cart"></button>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Item -->
|
||||
<tr>
|
||||
<td class="py-3 ps-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<a class="position-relative flex-shrink-0"
|
||||
<a class="flex-shrink-0"
|
||||
href="{{ route('second', ['shop', 'product-general-electronics']) }}">
|
||||
<span
|
||||
class="badge text-bg-danger position-absolute top-0 start-0">-10%</span>
|
||||
<img src="/img/shop/electronics/thumbs/09.png" width="110"
|
||||
alt="iPad Pro">
|
||||
<img src="{{ $cart->itemReference->item->image_url ?? '' }}" width="110"
|
||||
alt="{{ $cart->name ?? 'Product' }}">
|
||||
</a>
|
||||
<div class="w-100 min-w-0 ps-2 ps-xl-3">
|
||||
<h5 class="d-flex animate-underline mb-2">
|
||||
<a class="d-block fs-sm fw-medium text-truncate animate-target"
|
||||
href="{{ route('second', ['shop', 'product-general-electronics']) }}">Tablet Apple iPad Pro
|
||||
M2</a>
|
||||
href="{{ $cart->itemVariant->item->slug != null ? route('product.detail', [$cart->item->slug]) : '#' }}">{{ $cart->itemVariant->display_name ?? $cart->itemVariant->description ?? 'Product Name' }}</a>
|
||||
</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
|
||||
class="text-dark-emphasis fw-medium">Black</span></li>
|
||||
class="text-dark-emphasis fw-medium">{{ $cart->color ?? 'N/A' }}</span></li>
|
||||
<li><span class="text-body-secondary">Model:</span> <span
|
||||
class="text-dark-emphasis fw-medium">256GB</span></li>
|
||||
<li class="d-xl-none"><span class="text-body-secondary">Price:</span>
|
||||
<span class="text-dark-emphasis fw-medium">$989.00 <del
|
||||
class="text-body-tertiary fw-normal">$1,099.00</del></span>
|
||||
class="text-dark-emphasis fw-medium">{{ $cart->model ?? 'N/A' }}</span></li>
|
||||
<li class="d-xl-none"><span
|
||||
class="text-body-secondary">Price:</span>
|
||||
<span class="text-dark-emphasis fw-medium">${{ number_format($cart->itemReference->display_price ?? 0, 2) }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</ul> --}}
|
||||
<div class="count-input rounded-2 d-md-none mt-3">
|
||||
<button type="button" class="btn btn-sm btn-icon" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control form-control-sm"
|
||||
value="1" readonly>
|
||||
value="{{ $cart->qty ?? 1 }}" readonly>
|
||||
<button type="button" class="btn btn-sm btn-icon" data-increment
|
||||
aria-label="Increment quantity">
|
||||
<i class="ci-plus"></i>
|
||||
|
|
@ -306,92 +103,41 @@
|
|||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="h6 py-3 d-none d-xl-table-cell">$989.00 <del
|
||||
class="text-body-tertiary fs-xs fw-normal">$1,099.00</del></td>
|
||||
<td class="h6 py-3 d-none d-xl-table-cell" >
|
||||
<input type="hidden" id="price_{{ $cart->id }}" 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">
|
||||
<div class="count-input">
|
||||
<button type="button" class="btn btn-icon" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
aria-label="Decrement quantity" onclick="updateCartItem({{ $cart->id }}, 'decrement', this)">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control" value="1" readonly>
|
||||
<input type="number" class="form-control" value="{{ $cart->qty ?? 1 }}" readonly>
|
||||
<button type="button" class="btn btn-icon" data-increment
|
||||
aria-label="Increment quantity">
|
||||
aria-label="Increment quantity" onclick="updateCartItem({{ $cart->id }}, 'increment', this)">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="h6 py-3 d-none d-md-table-cell">$989.00</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">
|
||||
<button type="button" class="btn-close fs-sm" data-bs-toggle="tooltip"
|
||||
<form action="{{ route('cart.delete', $cart->id) }}" method="POST" onsubmit="deleteCartItem(event, this, {{ $cart->id }})">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit" class="btn-close fs-sm" data-bs-toggle="tooltip"
|
||||
data-bs-custom-class="tooltip-sm" data-bs-title="Remove"
|
||||
aria-label="Remove from cart"></button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
<!-- Item -->
|
||||
<tr>
|
||||
<td class="py-3 ps-0">
|
||||
<div class="d-flex align-items-center">
|
||||
<a class="flex-shrink-0" href="{{ route('second', ['shop', 'product-general-electronics']) }}">
|
||||
<img src="/img/shop/electronics/thumbs/01.png" width="110"
|
||||
alt="Smart Watch">
|
||||
</a>
|
||||
<div class="w-100 min-w-0 ps-2 ps-xl-3">
|
||||
<h5 class="d-flex animate-underline mb-2">
|
||||
<a class="d-block fs-sm fw-medium text-truncate animate-target"
|
||||
href="{{ route('second', ['shop', 'product-general-electronics']) }}">Smart Watch Series
|
||||
7</a>
|
||||
</h5>
|
||||
<ul class="list-unstyled gap-1 fs-xs mb-0">
|
||||
<li><span class="text-body-secondary">Color:</span> <span
|
||||
class="text-dark-emphasis fw-medium">White</span></li>
|
||||
<li><span class="text-body-secondary">Model:</span> <span
|
||||
class="text-dark-emphasis fw-medium">44 mm</span></li>
|
||||
<li class="d-xl-none"><span class="text-body-secondary">Price:</span>
|
||||
<span class="text-dark-emphasis fw-medium">$429.00</span></li>
|
||||
</ul>
|
||||
<div class="count-input rounded-2 d-md-none mt-3">
|
||||
<button type="button" class="btn btn-sm btn-icon" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control form-control-sm"
|
||||
value="1" readonly>
|
||||
<button type="button" class="btn btn-sm btn-icon" data-increment
|
||||
aria-label="Increment quantity">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="h6 py-3 d-none d-xl-table-cell">$429.00</td>
|
||||
<td class="py-3 d-none d-md-table-cell">
|
||||
<div class="count-input">
|
||||
<button type="button" class="btn btn-icon" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control" value="1" readonly>
|
||||
<button type="button" class="btn btn-icon" data-increment
|
||||
aria-label="Increment quantity">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
<td class="h6 py-3 d-none d-md-table-cell">$429.00</td>
|
||||
<td class="text-end py-3 px-0">
|
||||
<button type="button" class="btn-close fs-sm" data-bs-toggle="tooltip"
|
||||
data-bs-custom-class="tooltip-sm" data-bs-title="Remove"
|
||||
aria-label="Remove from cart"></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<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']) }}'">
|
||||
<a class="nav-link animate-underline px-0"
|
||||
href="{{ route('second', ['shop', 'catalog-electronics']) }}'">
|
||||
<i class="ci-chevron-left fs-lg me-1"></i>
|
||||
<span class="animate-target">Continue shopping</span>
|
||||
</a>
|
||||
|
|
@ -429,7 +175,8 @@
|
|||
<span class="fs-sm">Estimated total:</span>
|
||||
<span class="h5 mb-0">$2,390.40</span>
|
||||
</div>
|
||||
<a class="btn btn-lg btn-primary w-100" href="{{ route('second', ['checkout', 'v1-delivery-1']) }}">
|
||||
<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>
|
||||
|
|
@ -985,4 +732,149 @@
|
|||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
// JavaScript number formatting function
|
||||
function number_format(number, decimals, dec_point, thousands_sep) {
|
||||
number = (number + '').replace(/[^0-9+\-Ee.]/g, '');
|
||||
var n = !isFinite(+number) ? 0 : +number;
|
||||
var prec = !isFinite(+decimals) ? 0 : Math.abs(decimals);
|
||||
var sep = (typeof thousands_sep === 'undefined') ? ',' : thousands_sep;
|
||||
var dec = (typeof dec_point === 'undefined') ? '.' : dec_point;
|
||||
|
||||
var s = '';
|
||||
var toFixedFix = function (n, prec) {
|
||||
var k = Math.pow(10, prec);
|
||||
return '' + Math.round(n * k) / k;
|
||||
};
|
||||
|
||||
s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
|
||||
if (thousands_sep) {
|
||||
var re = /(-?\d+)(\d{3})/;
|
||||
while (re.test(s[0])) {
|
||||
s[0] = s[0].replace(re, '$1' + sep + '$2');
|
||||
}
|
||||
}
|
||||
|
||||
if ((s[1] || '').length < prec) {
|
||||
s[1] = s[1] || '';
|
||||
s[1] += new Array(prec - s[1].length + 1).join('0');
|
||||
}
|
||||
|
||||
return s.join(dec);
|
||||
}
|
||||
|
||||
async function updateCartItem(cartId, action, button) {
|
||||
const container = button.closest('.count-input');
|
||||
const input = container.querySelector('input[type="number"]');
|
||||
let currentQty = parseInt(input.value);
|
||||
|
||||
if (action === 'increment') {
|
||||
currentQty++;
|
||||
} else if (action === 'decrement' && currentQty > 1) {
|
||||
currentQty--;
|
||||
}
|
||||
|
||||
// input.value = currentQty;
|
||||
|
||||
try {
|
||||
const response = await fetch(`cart/${cartId}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').getAttribute('content'),
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
qty: currentQty
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
// Update total price display
|
||||
const row = button.closest('tr');
|
||||
const totalCell = row.querySelector('.total-row');
|
||||
const priceInput = document.getElementById(`price_${cartId}`);
|
||||
const price = parseFloat(priceInput.value);
|
||||
totalCell.innerHTML = `Rp ${number_format(price * currentQty, 0, ',', '.')}`;
|
||||
|
||||
// Update mobile quantity input
|
||||
const mobileInput = row.querySelector('td:first-child .count-input input');
|
||||
if (mobileInput) {
|
||||
mobileInput.value = currentQty;
|
||||
}
|
||||
|
||||
// Update cart count in header
|
||||
updateCartCount();
|
||||
}
|
||||
} else {
|
||||
console.error('Error updating cart:', await response.json());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Network error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteCartItem(event, form, cartId) {
|
||||
event.preventDefault();
|
||||
|
||||
if (!confirm('Are you sure you want to remove this item from cart?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`cart/${cartId}`, {
|
||||
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) {
|
||||
// Remove the row from the table
|
||||
const row = form.closest('tr');
|
||||
row.remove();
|
||||
|
||||
// Update cart count in header
|
||||
updateCartCount();
|
||||
|
||||
// Optionally reload the page to update cart summary
|
||||
// window.location.reload();
|
||||
}
|
||||
} else {
|
||||
console.error('Error deleting cart item:', await response.json());
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Network error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to update cart count in header
|
||||
async function updateCartCount() {
|
||||
try {
|
||||
const response = await fetch('cart/count', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
const cartCountElements = document.querySelectorAll('.cart-count');
|
||||
cartCountElements.forEach(element => {
|
||||
element.textContent = result.count;
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error updating cart count:', error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -0,0 +1,151 @@
|
|||
<div>
|
||||
|
||||
<div class="offcanvas offcanvas-end pb-sm-2 px-sm-2" id="authForm" tabindex="-1" aria-labelledby="authFormLabel"
|
||||
style="width: 500px">
|
||||
<div class="offcanvas-header flex-column align-items-start py-3 pt-lg-4">
|
||||
<div class="d-flex align-items-center justify-content-between w-100 mb-3 mb-lg-4">
|
||||
<h4 class="offcanvas-title" id="authFormLabel">Login to continue</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
<ul class="nav nav-underline" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button type="button" class="nav-link" id="login-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#login-tab-pane" role="tab" aria-controls="login-tab-pane"
|
||||
aria-selected="false">
|
||||
Login
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button type="button" class="nav-link active" id="register-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#register-tab-pane" role="tab" aria-controls="register-tab-pane"
|
||||
aria-selected="true">
|
||||
Register
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="offcanvas-body tab-content pt-2">
|
||||
|
||||
<!-- Login form -->
|
||||
<div class="tab-pane fade" id="login-tab-pane" role="tabpanel" aria-labelledby="login-tab">
|
||||
<form class="needs-validation" novalidate>
|
||||
<div class="position-relative mb-4">
|
||||
<label for="login-email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control form-control-lg" id="login-email" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Enter a valid email address!</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="login-password" class="form-label">Password</label>
|
||||
<div class="password-toggle">
|
||||
<input type="password" class="form-control form-control-lg" id="login-password" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Password is incorrect!</div>
|
||||
<label class="password-toggle-button fs-lg" aria-label="Show/hide password">
|
||||
<input type="checkbox" class="btn-check">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex align-items-center justify-content-between mb-4">
|
||||
<div class="form-check me-2">
|
||||
<input type="checkbox" class="form-check-input" id="remember-30">
|
||||
<label for="remember-30" class="form-check-label">Remember for 30 days</label>
|
||||
</div>
|
||||
<div class="nav">
|
||||
<a class="nav-link animate-underline p-0"
|
||||
href="{{ route('second', ['account', 'password-recovery']) }}">
|
||||
<span class="animate-target">Forgot password?</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg btn-primary w-100">
|
||||
Login to your account
|
||||
<i class="ci-chevron-right fs-lg ms-1 me-n1"></i>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Register form -->
|
||||
<div class="tab-pane fade show active" id="register-tab-pane" role="tabpanel"
|
||||
aria-labelledby="register-tab">
|
||||
<form class="needs-validation" novalidate>
|
||||
<div class="position-relative mb-4">
|
||||
<label for="register-email" class="form-label">Email</label>
|
||||
<input type="email" class="form-control form-control-lg" id="register-email" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Enter a valid email address!</div>
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="register-password" class="form-label">Password</label>
|
||||
<div class="password-toggle">
|
||||
<input type="password" class="form-control form-control-lg" id="register-password"
|
||||
minlength="8" placeholder="Minimum 8 characters" required>
|
||||
<div class="invalid-tooltip bg-transparent py-0">Password does not meet the required
|
||||
criteria!
|
||||
</div>
|
||||
<label class="password-toggle-button fs-lg" aria-label="Show/hide password">
|
||||
<input type="checkbox" class="btn-check">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="d-flex flex-column gap-2 mb-4">
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="save-pass">
|
||||
<label for="save-pass" class="form-check-label">Save the password</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="privacy" required>
|
||||
<label for="privacy" class="form-check-label">I have read and accept the <a
|
||||
class="text-dark-emphasis" href="#!">Privacy Policy</a></label>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg btn-primary w-100">
|
||||
Create an account
|
||||
<i class="ci-chevron-right fs-lg ms-1 me-n1"></i>
|
||||
</button>
|
||||
<div class="pt-5">
|
||||
<h6>AsiaGolf account benefits</h6>
|
||||
<ul class="list-unstyled d-flex flex-column gap-2 fs-sm mb-0">
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-mail fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Subscribe to your favorite products</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-settings fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">View and manage your orders and withlist</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-gift fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Earn rewards for future purchases</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-percent fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Receive exclusive offers and discounts</div>
|
||||
</li>
|
||||
<li class="d-flex align-items-center pb-1">
|
||||
<div
|
||||
class="d-flex align-items-center justify-content-center bg-body-tertiary rounded-circle p-2">
|
||||
<i class="ci-heart fs-base text-dark-emphasis m-1"></i>
|
||||
</div>
|
||||
<div class="ps-2 ms-1">Create multiple wishlists</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@include('layouts.partials/offcanvas')
|
||||
|
||||
@include('layouts.partials/navbar', ['wishlist' => true])
|
||||
</div>
|
||||
|
|
@ -124,7 +124,7 @@
|
|||
<span class="h6 mb-0">$197.00</span>
|
||||
</div>
|
||||
<div class="d-flex w-100 gap-3">
|
||||
<a class="btn btn-lg btn-secondary w-100" href="#!">View cart</a>
|
||||
<a class="btn btn-lg btn-secondary w-100" href="{{ route('cart.index') }}">View cart</a>
|
||||
<a class="btn btn-lg btn-dark w-100" href="#!">Checkout</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -253,8 +253,8 @@
|
|||
data-bs-toggle="offcanvas" data-bs-target="#shoppingCart" aria-controls="shoppingCart"
|
||||
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"
|
||||
style="--cz-badge-padding-y: .25em; --cz-badge-padding-x: .42em">3</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>
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
@props([
|
||||
'quantity' => 1,
|
||||
'item_reference_id' => null,
|
||||
'locationId' => session('location_id', 22),
|
||||
'buttonText' => 'Add to cart',
|
||||
'buttonClass' => 'btn-dark',
|
||||
])
|
||||
|
||||
<div class="d-flex gap-3 pb-3 pb-lg-4 mb-3">
|
||||
<div class="count-input flex-shrink-0">
|
||||
<button type="button" class="btn btn-icon btn-lg" data-decrement aria-label="Decrement quantity"
|
||||
onclick="decrementQuantity(this)">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control form-control-lg" min="1" value="{{ $quantity }}" readonly>
|
||||
<button type="button" class="btn btn-icon btn-lg" data-increment aria-label="Increment quantity"
|
||||
onclick="incrementQuantity(this)">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-lg {{ $buttonClass }} w-100" onclick="addToCartItem(this)"
|
||||
data-item-reference-id="{{ $item_reference_id }}" data-location-id="{{ $locationId }}"
|
||||
data-quantity="{{ $quantity }}">
|
||||
<span class="button-text">{{ $buttonText }}</span>
|
||||
<span class="loading-text" style="display: none;">
|
||||
<i class="ci-loading animate-spin"></i> Adding...
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function incrementQuantity(button) {
|
||||
const input = button.parentElement.querySelector('input[type="number"]');
|
||||
input.value = parseInt(input.value);
|
||||
updateAddToCartButton(button);
|
||||
}
|
||||
|
||||
function decrementQuantity(button) {
|
||||
const input = button.parentElement.querySelector('input[type="number"]');
|
||||
const currentValue = parseInt(input.value);
|
||||
if (currentValue > 1) {
|
||||
input.value = currentValue;
|
||||
}
|
||||
updateAddToCartButton(button);
|
||||
}
|
||||
|
||||
function updateAddToCartButton(button) {
|
||||
const container = button.closest('.d-flex');
|
||||
const addToCartBtn = container.querySelector('button[onclick="addToCartItem(this)"]');
|
||||
const input = container.querySelector('input[type="number"]');
|
||||
|
||||
if (addToCartBtn && input) {
|
||||
addToCartBtn.dataset.quantity = input.value;
|
||||
}
|
||||
}
|
||||
|
||||
async function addToCartItem(button) {
|
||||
const itemReferenceId = button.dataset.itemReferenceId;
|
||||
const locationId = button.dataset.locationId;
|
||||
const quantity = button.dataset.quantity || button.parentElement.querySelector('input[type="number"]')
|
||||
.value;
|
||||
|
||||
if (!itemReferenceId) {
|
||||
console.error('Item Reference ID is required');
|
||||
return;
|
||||
}
|
||||
|
||||
const buttonText = button.querySelector('.button-text');
|
||||
const loadingText = button.querySelector('.loading-text');
|
||||
|
||||
// Show loading state
|
||||
button.disabled = true;
|
||||
if (buttonText) buttonText.style.display = 'none';
|
||||
if (loadingText) loadingText.style.display = 'inline';
|
||||
|
||||
try {
|
||||
const token = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
||||
const response = await fetch('{{ route('cart.add') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': token,
|
||||
'Accept': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
item_reference_id: itemReferenceId,
|
||||
location_id: locationId,
|
||||
qty: quantity
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
if (result.success) {
|
||||
// Update cart count in header
|
||||
updateCartCount();
|
||||
|
||||
// Redirect to cart page on success
|
||||
window.location.href = '{{ route('cart.index') }}';
|
||||
}
|
||||
} else {
|
||||
const error = await response.json();
|
||||
console.error('Error adding to cart:', error);
|
||||
// You could show an error message here
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Network error:', error);
|
||||
// You could show an error message here
|
||||
} finally {
|
||||
// Restore button state
|
||||
button.disabled = false;
|
||||
if (buttonText) buttonText.style.display = 'inline';
|
||||
if (loadingText) loadingText.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// Function to update cart count in header
|
||||
async function updateCartCount() {
|
||||
try {
|
||||
const response = await fetch('{{ route('cart.count') }}', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const result = await response.json();
|
||||
const cartCountElements = document.querySelectorAll('.cart-count');
|
||||
cartCountElements.forEach(element => {
|
||||
element.textContent = result.count;
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error updating cart count:', error);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
@ -454,14 +454,12 @@
|
|||
<div class="row row-cols-2 g-3 g-sm-4 g-md-3 g-lg-4 pb-3 pb-sm-4 pb-md-0">
|
||||
|
||||
@foreach ($product->image_urls as $key => $url)
|
||||
|
||||
@if ($key == 0)
|
||||
@continue
|
||||
@endif
|
||||
<div class="col">
|
||||
<a class="hover-effect-scale hover-effect-opacity position-relative d-flex rounded overflow-hidden"
|
||||
href="{{ $url }}" data-glightbox
|
||||
data-gallery="product-gallery">
|
||||
href="{{ $url }}" data-glightbox data-gallery="product-gallery">
|
||||
<i
|
||||
class="ci-zoom-in hover-effect-target fs-3 text-white position-absolute top-50 start-50 translate-middle opacity-0 z-2"></i>
|
||||
<div class="ratio hover-effect-target bg-body-tertiary rounded"
|
||||
|
|
@ -507,14 +505,14 @@
|
|||
<p class="fs-sm mb-0">{!! nl2br(Str::limit($product->description, 500)) !!}</p>
|
||||
<div class="collapse" id="moreDescription">
|
||||
<div class="fs-sm pt-3">
|
||||
@if(strlen($product->description) > 500)
|
||||
@if (strlen($product->description) > 500)
|
||||
<p>{!! nl2br(substr($product->description, 500)) !!}</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Price -->
|
||||
@if(strlen($product->description) > 500)
|
||||
@if (strlen($product->description) > 500)
|
||||
<a class="d-inline-block fs-sm fw-medium text-dark-emphasis collapsed mt-1"
|
||||
href="#moreDescription" data-bs-toggle="collapse" aria-expanded="false"
|
||||
aria-controls="moreDescription" data-label-collapsed="Read more"
|
||||
|
|
@ -525,7 +523,8 @@
|
|||
|
||||
|
||||
|
||||
<del class="display_discount_price fs-sm fw-normal text-body-tertiary ms-2" style="display: {{ $product->display_discount_price ? 'inline' : 'none' }};">{{ $product->display_discount_price ? ' Rp ' . number_format($product->display_discount_price, 0, ',', '.') : '' }}</del>
|
||||
<del class="display_discount_price fs-sm fw-normal text-body-tertiary ms-2"
|
||||
style="display: {{ $product->display_discount_price ? 'inline' : 'none' }};">{{ $product->display_discount_price ? ' Rp ' . number_format($product->display_discount_price, 0, ',', '.') : '' }}</del>
|
||||
</div>
|
||||
|
||||
<!-- Color options -->
|
||||
|
|
@ -535,12 +534,14 @@
|
|||
<div class="d-flex flex-wrap gap-2" data-binded-label="#variantOption">
|
||||
|
||||
@foreach ($product->variants as $key => $variant)
|
||||
<input type="radio" class="btn-check" name="colors" id="variant-id-{{ $variant->id }}" {{ $key == 0 ? 'checked' : '' }}>
|
||||
<label for="variant-id-{{ $variant->id }}" class="btn btn-image p-0" data-label="{{ $variant->description }}"
|
||||
data-price="Rp {{ number_format($product->display_price, 0, ",",".") }}"
|
||||
<input type="radio" class="btn-check" name="colors"
|
||||
value="{{ $variant->reference->id }}"
|
||||
id="variant-id-{{ $variant->id }}" {{ $key == 0 ? 'checked' : '' }}>
|
||||
<label for="variant-id-{{ $variant->id }}" class="btn btn-image p-0"
|
||||
data-label="{{ $variant->description }}"
|
||||
data-price="Rp {{ number_format($product->display_price, 0, ',', '.') }}"
|
||||
data-discount-price="{{ $product->display_discount_price ? 'Rp ' . number_format($product->display_discount_price, 0, ',', '.') : '' }}"
|
||||
data-image="{{ $variant->image_url ?? $product->image_url }}"
|
||||
>
|
||||
data-image="{{ $variant->image_url ?? $product->image_url }}">
|
||||
<img src="{{ $variant->image_url ?? $product->image_url }}" width="56"
|
||||
alt="{{ $variant->name }}">
|
||||
<span class="visually-hidden">{{ $variant->name }}</span>
|
||||
|
|
@ -580,21 +581,7 @@
|
|||
</div> --}}
|
||||
|
||||
<!-- Count input + Add to cart button -->
|
||||
<div class="d-flex gap-3 pb-3 pb-lg-4 mb-3">
|
||||
<div class="count-input flex-shrink-0">
|
||||
<button type="button" class="btn btn-icon btn-lg" data-decrement
|
||||
aria-label="Decrement quantity">
|
||||
<i class="ci-minus"></i>
|
||||
</button>
|
||||
<input type="number" class="form-control form-control-lg" min="1"
|
||||
value="1" readonly>
|
||||
<button type="button" class="btn btn-icon btn-lg" data-increment
|
||||
aria-label="Increment quantity">
|
||||
<i class="ci-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
<button type="button" class="btn btn-lg btn-dark w-100">Add to cart</button>
|
||||
</div>
|
||||
<x-shop.add-to-cart :item_reference_id="$product->variants->first()->id" />
|
||||
|
||||
<!-- Info list -->
|
||||
{{-- <ul class="list-unstyled gap-3 pb-3 pb-lg-4 mb-3">
|
||||
|
|
@ -645,8 +632,11 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="h4 d-none d-lg-block mb-0 ms-auto me-4 display_price">Rp {{ number_format($product->display_price,0,",",".") }} <del
|
||||
class="fs-sm fw-normal text-body-tertiary display_discount_price" style="display: {{ $product->display_discount_price ? 'inline' : 'none' }};">Rp {{ number_format($product->display_discount_price,0,",",".") }}</del></div>
|
||||
<div class="h4 d-none d-lg-block mb-0 ms-auto me-4 display_price">Rp
|
||||
{{ number_format($product->display_price, 0, ',', '.') }} <del
|
||||
class="fs-sm fw-normal text-body-tertiary display_discount_price"
|
||||
style="display: {{ $product->display_discount_price ? 'inline' : 'none' }};">Rp
|
||||
{{ number_format($product->display_discount_price, 0, ',', '.') }}</del></div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-icon btn-secondary animate-pulse"
|
||||
aria-label="Add to Wishlist">
|
||||
|
|
@ -687,7 +677,8 @@
|
|||
<button type="button" class="nav-link" id="delivery-tab" data-bs-toggle="tab"
|
||||
data-bs-target="#delivery-tab-pane" role="tab" aria-controls="delivery-tab-pane"
|
||||
aria-selected="false">
|
||||
{{ __('product_fashion.delivery') }}<span class="d-none d-md-inline"> {{ __('product_fashion.and_returns') }}</span>
|
||||
{{ __('product_fashion.delivery') }}<span
|
||||
class="d-none d-md-inline"> {{ __('product_fashion.and_returns') }}</span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
|
|
@ -709,17 +700,22 @@
|
|||
Pastikan apakah stock tersedia dengan terlebih dahulu KIRIM PESAN - TANYA kepada kami,
|
||||
<br>
|
||||
<br>
|
||||
Segera lakukan pembayaran saat melakukan checkout produk agar system order bisa langusung terima dan proses kemas,
|
||||
Segera lakukan pembayaran saat melakukan checkout produk agar system order bisa langusung terima
|
||||
dan proses kemas,
|
||||
<br>
|
||||
<br>
|
||||
- Layanan Pengiriman "Instant" tersedia (Prioritas) kami upayakan proses langsung,
|
||||
<br>
|
||||
- Layanan Pengiriman "Sameday" Maksimal order masuk pukul 15.00 Wib karna maksimal Request pick up yang di tentukan oleh tokopedia pukul 16.00 Wib,.
|
||||
<br>
|
||||
- Layanan pengiriman "Regullar - Yes - Cargo" Kami pastikan produk terkirim status berubah terkirim pada Sore menjelang petan karna kami hanya tersedia 1x pengiriman ke jasa pengiriman dalam 1 hari
|
||||
<br>
|
||||
<br>
|
||||
Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan ikut pengiriman ke jasa pengiriman ke esokan harinya,.
|
||||
- Layanan Pengiriman "Instant" tersedia (Prioritas) kami upayakan proses langsung,
|
||||
<br>
|
||||
- Layanan Pengiriman "Sameday" Maksimal order masuk pukul 15.00 Wib karna maksimal Request pick
|
||||
up yang di tentukan oleh tokopedia pukul 16.00 Wib,.
|
||||
<br>
|
||||
- Layanan pengiriman "Regullar - Yes - Cargo" Kami pastikan produk terkirim status berubah
|
||||
terkirim pada Sore menjelang petan karna kami hanya tersedia 1x pengiriman ke jasa pengiriman
|
||||
dalam 1 hari
|
||||
<br>
|
||||
<br>
|
||||
Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan ikut pengiriman ke
|
||||
jasa pengiriman ke esokan harinya,.
|
||||
</div>
|
||||
{{-- <div class="col-lg-6 col-xl-5 offset-xl-1">
|
||||
<div class="row row-cols-2 g-4 my-0 my-lg-n2">
|
||||
|
|
@ -760,8 +756,7 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
</div>
|
||||
|
||||
<!-- Washing instructions tab -->
|
||||
<div class="tab-pane fade fs-sm" id="washing-tab-pane" role="tabpanel"
|
||||
aria-labelledby="washing-tab">
|
||||
<div class="tab-pane fade fs-sm" id="washing-tab-pane" role="tabpanel" aria-labelledby="washing-tab">
|
||||
<p>Following below washing instructions can help prolong the life of your denim skirt and keep it
|
||||
looking its best for longer.</p>
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
|
|
@ -802,46 +797,61 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
</div>
|
||||
|
||||
<!-- Delivery and returns tab -->
|
||||
<div class="tab-pane fade fs-sm" id="delivery-tab-pane" role="tabpanel"
|
||||
aria-labelledby="delivery-tab">
|
||||
<div class="tab-pane fade fs-sm" id="delivery-tab-pane" role="tabpanel" aria-labelledby="delivery-tab">
|
||||
<div class="row row-cols-1 row-cols-md-2">
|
||||
<div class="col mb-3 mb-md-0">
|
||||
<div class="pe-lg-2 pe-xl-3">
|
||||
<h6>Pengiriman</h6>
|
||||
<p>Kami bekerja sama dengan berbagai penyedia jasa pengiriman terpercaya untuk memastikan proses pengiriman pesanan berjalan dengan aman dan efisien.
|
||||
<p>Kami bekerja sama dengan berbagai penyedia jasa pengiriman terpercaya untuk memastikan
|
||||
proses pengiriman pesanan berjalan dengan aman dan efisien.
|
||||
<br>
|
||||
<br>
|
||||
Pelanggan diberikan kebebasan untuk memilih layanan pengiriman yang paling sesuai dengan kebutuhan, baik dari segi kecepatan maupun biaya.
|
||||
Pelanggan diberikan kebebasan untuk memilih layanan pengiriman yang paling sesuai dengan
|
||||
kebutuhan, baik dari segi kecepatan maupun biaya.
|
||||
<br>
|
||||
<br>
|
||||
Estimasi waktu pengiriman dapat berbeda-beda tergantung pada jenis layanan yang dipilih, lokasi tujuan, serta kebijakan dan kondisi operasional dari masing-masing penyedia jasa pengiriman.
|
||||
Estimasi waktu pengiriman dapat berbeda-beda tergantung pada jenis layanan yang dipilih,
|
||||
lokasi tujuan, serta kebijakan dan kondisi operasional dari masing-masing penyedia jasa
|
||||
pengiriman.
|
||||
<br>
|
||||
<br>
|
||||
Perlu diperhatikan bahwa keterlambatan yang disebabkan oleh faktor di luar kendali kami merupakan tanggung jawab penyedia jasa terkait.
|
||||
Perlu diperhatikan bahwa keterlambatan yang disebabkan oleh faktor di luar kendali kami
|
||||
merupakan tanggung jawab penyedia jasa terkait.
|
||||
<br>
|
||||
<br>
|
||||
Meskipun demikian, kami akan senantiasa membantu memantau status pengiriman guna memastikan pesanan sampai ke tangan pelanggan dengan baik.</p>
|
||||
Meskipun demikian, kami akan senantiasa membantu memantau status pengiriman guna
|
||||
memastikan pesanan sampai ke tangan pelanggan dengan baik.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="ps-lg-2 ps-xl-3">
|
||||
<h6>Return Barang</h6>
|
||||
<p>Kami memberikan kesempatan kepada pelanggan untuk mengajukan permohonan retur atas produk yang diterima apabila terdapat ketidaksesuaian atau kendala tertentu. Proses pengajuan retur dapat dilakukan dengan menghubungi customer service resmi kami melalui WhatsApp.
|
||||
<p>Kami memberikan kesempatan kepada pelanggan untuk mengajukan permohonan retur atas produk
|
||||
yang diterima apabila terdapat ketidaksesuaian atau kendala tertentu. Proses pengajuan
|
||||
retur dapat dilakukan dengan menghubungi customer service resmi kami melalui WhatsApp.
|
||||
<br>
|
||||
<br>
|
||||
Untuk keperluan verifikasi, pelanggan diwajibkan mengirimkan informasi detail transaksi pembelian, foto produk yang diterima, serta bukti video unboxing yang jelas dan tidak terputus.
|
||||
Untuk keperluan verifikasi, pelanggan diwajibkan mengirimkan informasi detail transaksi
|
||||
pembelian, foto produk yang diterima, serta bukti video unboxing yang jelas dan tidak
|
||||
terputus.
|
||||
<br>
|
||||
<br>
|
||||
Permohonan retur akan ditinjau sesuai dengan ketentuan dan kebijakan yang berlaku.
|
||||
<br>
|
||||
<br>
|
||||
Setelah proses verifikasi selesai dan disetujui, kami akan memberikan informasi lebih lanjut terkait tahapan pengembalian barang maupun solusi yang dapat diberikan kepada pelanggan.
|
||||
Setelah proses verifikasi selesai dan disetujui, kami akan memberikan informasi lebih
|
||||
lanjut terkait tahapan pengembalian barang maupun solusi yang dapat diberikan kepada
|
||||
pelanggan.
|
||||
<br>
|
||||
<br>
|
||||
Kami berkomitmen untuk menyelesaikan setiap permohonan retur dengan cepat dan profesional sesuai dengan standar pelayanan kami.
|
||||
Kami berkomitmen untuk menyelesaikan setiap permohonan retur dengan cepat dan
|
||||
profesional sesuai dengan standar pelayanan kami.
|
||||
<br>
|
||||
<br>
|
||||
Untuk informasi lebih lanjut, pelanggan dapat menghubungi customer service kami melalui WhatsApp.</p>
|
||||
Untuk informasi lebih lanjut, pelanggan dapat menghubungi customer service kami melalui
|
||||
WhatsApp.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1103,8 +1113,8 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
<!-- Slider prev/next buttons -->
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button"
|
||||
class="btn btn-icon btn-outline-secondary animate-slide-start rounded-circle me-1"
|
||||
id="lookPrev" aria-label="Prev">
|
||||
class="btn btn-icon btn-outline-secondary animate-slide-start rounded-circle me-1" id="lookPrev"
|
||||
aria-label="Prev">
|
||||
<i class="ci-chevron-left fs-lg animate-target"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-icon btn-outline-secondary animate-slide-end rounded-circle"
|
||||
|
|
@ -1143,7 +1153,6 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endforeach
|
||||
|
||||
|
||||
|
|
@ -1153,8 +1162,7 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
|
||||
<!-- Product image -->
|
||||
<div class="col-md-6 order-md-1">
|
||||
<img src="{{ $product->image_url ?? '' }}" class="d-block bg-body-tertiary rounded"
|
||||
alt="Image">
|
||||
<img src="{{ $product->image_url ?? '' }}" class="d-block bg-body-tertiary rounded" alt="Image">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -1242,8 +1250,8 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
<h6 class="accordion-header" id="categoriesHeading">
|
||||
<span class="text-dark-emphasis d-none d-sm-block">Categories</span>
|
||||
<button type="button" class="accordion-button collapsed py-3 d-sm-none"
|
||||
data-bs-toggle="collapse" data-bs-target="#categoriesLinks"
|
||||
aria-expanded="false" aria-controls="categoriesLinks">Categories</button>
|
||||
data-bs-toggle="collapse" data-bs-target="#categoriesLinks" aria-expanded="false"
|
||||
aria-controls="categoriesLinks">Categories</button>
|
||||
</h6>
|
||||
<div class="accordion-collapse collapse d-sm-block" id="categoriesLinks"
|
||||
aria-labelledby="categoriesHeading" data-bs-parent="#footerLinks">
|
||||
|
|
@ -1314,8 +1322,8 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
<h6 class="accordion-header" id="customerHeading">
|
||||
<span class="text-dark-emphasis d-none d-sm-block">Customer service</span>
|
||||
<button type="button" class="accordion-button collapsed py-3 d-sm-none"
|
||||
data-bs-toggle="collapse" data-bs-target="#customerLinks"
|
||||
aria-expanded="false" aria-controls="customerLinks">Customer service</button>
|
||||
data-bs-toggle="collapse" data-bs-target="#customerLinks" aria-expanded="false"
|
||||
aria-controls="customerLinks">Customer service</button>
|
||||
</h6>
|
||||
<div class="accordion-collapse collapse d-sm-block" id="customerLinks"
|
||||
aria-labelledby="customerHeading" data-bs-parent="#footerLinks">
|
||||
|
|
@ -1420,15 +1428,13 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
</div>
|
||||
<div>
|
||||
<img src="/img/payment-methods/paypal-light-mode.svg" class="d-none-dark" alt="PayPal">
|
||||
<img src="/img/payment-methods/paypal-dark-mode.svg" class="d-none d-block-dark"
|
||||
alt="PayPal">
|
||||
<img src="/img/payment-methods/paypal-dark-mode.svg" class="d-none d-block-dark" alt="PayPal">
|
||||
</div>
|
||||
<div>
|
||||
<img src="/img/payment-methods/mastercard.svg" alt="Mastercard">
|
||||
</div>
|
||||
<div>
|
||||
<img src="/img/payment-methods/google-pay-light-mode.svg" class="d-none-dark"
|
||||
alt="Google Pay">
|
||||
<img src="/img/payment-methods/google-pay-light-mode.svg" class="d-none-dark" alt="Google Pay">
|
||||
<img src="/img/payment-methods/google-pay-dark-mode.svg" class="d-none d-block-dark"
|
||||
alt="Google Pay">
|
||||
</div>
|
||||
|
|
@ -1461,12 +1467,11 @@ Pesanan masuk pukul 18.00 Wib ke atas kemungkinan akan kami proses kirim dan iku
|
|||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
@endsection
|
||||
|
||||
@section('scripts')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const radios = document.querySelectorAll('input[name="colors"]');
|
||||
radios.forEach(radio => {
|
||||
radio.addEventListener('change', function() {
|
||||
|
|
@ -1476,7 +1481,6 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
const image = label.getAttribute('data-image');
|
||||
const labelText = label.getAttribute('data-label');
|
||||
|
||||
|
||||
document.querySelector('.display_price').textContent = price;
|
||||
const discountSpan = document.querySelector('.display_discount_price');
|
||||
if (discountPrice) {
|
||||
|
|
@ -1487,13 +1491,21 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
}
|
||||
document.querySelector('.product-main-image').src = image;
|
||||
document.querySelector('.variantOption').textContent = labelText;
|
||||
|
||||
// Update AddToCart component with new variant ID
|
||||
const addToCartBtn = document.querySelector('[data-item-reference-id]');
|
||||
if (addToCartBtn) {
|
||||
console.log(this.value);
|
||||
var item_reference_id = this.value;
|
||||
addToCartBtn.setAttribute('data-item-reference-id', item_reference_id);
|
||||
}
|
||||
});
|
||||
});
|
||||
// Trigger change for the initially checked radio
|
||||
// Trigger change for initially checked radio
|
||||
const checkedRadio = document.querySelector('input[name="colors"]:checked');
|
||||
if (checkedRadio) {
|
||||
checkedRadio.dispatchEvent(new Event('change'));
|
||||
}
|
||||
});
|
||||
</script>
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ use App\Http\Controllers\ProductController;
|
|||
use App\Http\Controllers\SearchController;
|
||||
use App\Http\Controllers\ComponentController;
|
||||
use App\Http\Controllers\Auth\ProfileController;
|
||||
use App\Http\Controllers\CartController;
|
||||
|
||||
Route::group(['prefix' => '/dummy'], function () {
|
||||
Route::get('', [RoutingController::class, 'index'])->name('root');
|
||||
|
|
@ -74,11 +75,22 @@ Route::post('/profile', [ProfileController::class, 'update'])->name('profile.upd
|
|||
Route::put('/profile/password', [ProfileController::class, 'updatePassword'])->name('profile.password.update');
|
||||
|
||||
|
||||
Route::get('/addresses', [AddressController::class, 'index'])->name('addresses');
|
||||
Route::post('/addresses', [AddressController::class, 'store'])->name('addresses.store');
|
||||
Route::put('/addresses/{id}', [AddressController::class, 'update'])->name('addresses.update');
|
||||
Route::delete('/addresses/{id}', [AddressController::class, 'destroy'])->name('addresses.destroy');
|
||||
Route::get('/addresses/provinces', [AddressController::class, 'provinces'])->name('addresses.provinces');
|
||||
Route::get('/addresses/cities/{provinceId}', [AddressController::class, 'cities'])->name('addresses.cities');
|
||||
Route::get('/addresses/districts/{provinceId}', [AddressController::class, 'districts'])->name('addresses.districts');
|
||||
Route::get('/addresses/villages/{districtId}', [AddressController::class, 'villages'])->name('addresses.villages');
|
||||
Route::middleware(['auth'])->prefix('/addresses')->group(function () {
|
||||
Route::get('/', [AddressController::class, 'index'])->name('addresses');
|
||||
Route::post('/', [AddressController::class, 'store'])->name('addresses.store');
|
||||
Route::put('/{id}', [AddressController::class, 'update'])->name('addresses.update');
|
||||
Route::delete('/{id}', [AddressController::class, 'destroy'])->name('addresses.destroy');
|
||||
Route::get('/provinces', [AddressController::class, 'provinces'])->name('addresses.provinces');
|
||||
Route::get('/cities/{provinceId}', [AddressController::class, 'cities'])->name('addresses.cities');
|
||||
Route::get('/districts/{provinceId}', [AddressController::class, 'districts'])->name('addresses.districts');
|
||||
Route::get('/villages/{districtId}', [AddressController::class, 'villages'])->name('addresses.villages');
|
||||
});
|
||||
|
||||
|
||||
Route::middleware(['auth'])->prefix('/cart')->group(function () {
|
||||
Route::get('/', [CartController::class, 'index'])->name('cart.index');
|
||||
Route::post('/', [CartController::class, 'add'])->name('cart.add');
|
||||
Route::put('/{id}', [CartController::class, 'update'])->name('cart.update');
|
||||
Route::delete('/{id}', [CartController::class, 'delete'])->name('cart.delete');
|
||||
Route::get('/count', [CartController::class, 'count'])->name('cart.count');
|
||||
});
|
||||
Loading…
Reference in New Issue