change price, image if variant click and show description

This commit is contained in:
Bayu Lukman Yusuf 2026-01-02 15:01:00 +07:00
parent c8c96556c0
commit 7173d2c117
5 changed files with 126 additions and 337 deletions

View File

@ -3,11 +3,12 @@
namespace App\Http\Controllers;
use App\Models\Items;
use App\Repositories\Catalog\ProductRepository;
use Illuminate\Http\Request;
class ProductController extends Controller
{
public function detail($slug, Request $request)
public function detail($slug, Request $request, ProductRepository $productRepository)
{
$product = Items::where('slug', $slug)->first();
@ -17,8 +18,19 @@ class ProductController extends Controller
}
$complete_look_products_data = $productRepository->getList([
'category_id' => $product->category1_id,
'limit' => 4,
]);
$complete_look_products = collect($complete_look_products_data->items())->chunk(2);
return view('shop.product-fashion',[
'product' => $product,
'complete_look_products' => $complete_look_products
]);
}
}

View File

@ -5,6 +5,8 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Awobaz\Compoships\Compoships;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class ItemVariant extends Model
@ -64,4 +66,56 @@ class ItemVariant extends Model
return $image ? Storage::disk('wms')->url($image) : null;
}
public function item()
{
return $this->belongsTo(Items::class, 'item_id');
}
public function conversion_value()
{
$item = $this->item;
$convertion = 1;
if (($item->display_unit != $item->unit) and ($item->display_unit)){
$convertions = DB::select("select to_qty / from_qty as conv
from item_convertions where from_unit = ? and to_unit = ?",
[$item->display_unit, $item->unit] );
$convertion = max((float) @$convertions[0]->conv,1);
}
return $convertion;
}
public function getDisplayPriceAttribute()
{
try {
$convertion = $this->conversion_value();
$price = $this->reference->price->price ?? null;
$price = $price ? $price : $this->item->net_price;
return (float) $price * $convertion;
} catch (\Exception $e) {
Log::info($e);
return 0;
}
}
public function getDisplayDiscountPriceAttribute()
{
try {
$convertion = $this->conversion_value();
$discountPrice = @$this->discount->price ?? 0;
return (float) $discountPrice * $convertion;
} catch (\Exception $e) {
return 0;
}
}
}

View File

@ -1,9 +1,12 @@
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
@if ($product->display_discount_price > 0)
<span
class="badge text-bg-danger position-absolute top-0 start-0 z-2 mt-2 mt-sm-3 ms-2 ms-sm-3">Sale</span>
<button type="button"
@endif
<button type="button"
class="btn btn-icon btn-secondary animate-pulse fs-base bg-transparent border-0 position-absolute top-0 end-0 z-2 mt-1 mt-sm-2 me-1 me-sm-2"
aria-label="Add to Wishlist">
<i class="ci-heart animate-target"></i>

View File

@ -18,6 +18,8 @@
@vite(['resources/js/theme.js'])
@yield('scripts')
</body>
</html>

View File

@ -605,60 +605,19 @@
</button>
<!-- Country slect visible on screens > 768px wide (md breakpoint) -->
<div class="dropdown d-none d-md-block nav">
<a class="nav-link dropdown-toggle py-1 px-0" href="#" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" aria-label="Country select: USA">
<div class="ratio ratio-1x1" style="width: 20px">
<img src="/img/flags/en-us.png" alt="USA">
</div>
</a>
<ul class="dropdown-menu fs-sm" style="--cz-dropdown-spacer: .5rem">
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/en-uk.png" class="flex-shrink-0 me-2" width="20"
alt="United Kingdom">
United Kingdom
</a>
</li>
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/fr.png" class="flex-shrink-0 me-2" width="20" alt="France">
France
</a>
</li>
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/de.png" class="flex-shrink-0 me-2" width="20"
alt="Deutschland">
Deutschland
</a>
</li>
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/it.png" class="flex-shrink-0 me-2" width="20" alt="Italia">
Italia
</a>
</li>
</ul>
</div>
<x-language-selector />
<!-- City slect visible on screens > 768px wide (md breakpoint) -->
<div class="dropdown d-none d-md-block nav">
<a class="nav-link animate-underline dropdown-toggle fw-normal py-1 px-0" href="#"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="animate-target">Washington</span>
</a>
<ul class="dropdown-menu fs-sm" style="--cz-dropdown-spacer: .5rem">
<li><a class="dropdown-item" href="#!">Chicago</a></li>
<li><a class="dropdown-item" href="#!">Los Angeles</a></li>
<li><a class="dropdown-item" href="#!">New York</a></li>
<li><a class="dropdown-item" href="#!">Philadelphia</a></li>
</ul>
</div>
<x-location-selector />
</div>
<!-- Navbar brand (Logo) -->
<a class="navbar-brand fs-2 py-0 m-0 me-auto me-sm-n5" href="{{ route('second', ['home', 'fashion-v1']) }}">Cartzilla</a>
<a class="navbar-brand fs-2 py-0 m-0 me-auto me-sm-n5" href="/">
<img src="{{ asset('logo/logo-colored.png') }}" class="d-none d-lg-block" style="height:32px;"/>
<img src="{{ asset('logo/logo-app.png') }}" class="d-lg-none" style="height:42px;"/>
</a>
<!-- Button group -->
<div class="d-flex align-items-center">
@ -757,56 +716,8 @@
<!-- Country and City slects visible on screens < 768px wide (md breakpoint) -->
<div class="offcanvas-header gap-3 d-md-none pt-0 pb-3">
<div class="dropdown nav">
<a class="nav-link dropdown-toggle py-1 px-0" href="#" data-bs-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" aria-label="Country select: USA">
<div class="ratio ratio-1x1" style="width: 20px">
<img src="/img/flags/en-us.png" alt="USA">
</div>
</a>
<ul class="dropdown-menu fs-sm" style="--cz-dropdown-spacer: .5rem">
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/en-uk.png" class="flex-shrink-0 me-2" width="20"
alt="United Kingdom">
United Kingdom
</a>
</li>
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/fr.png" class="flex-shrink-0 me-2" width="20"
alt="France">
France
</a>
</li>
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/de.png" class="flex-shrink-0 me-2" width="20"
alt="Deutschland">
Deutschland
</a>
</li>
<li>
<a class="dropdown-item" href="#!">
<img src="/img/flags/it.png" class="flex-shrink-0 me-2" width="20"
alt="Italia">
Italia
</a>
</li>
</ul>
</div>
<div class="dropdown nav">
<a class="nav-link animate-underline dropdown-toggle fw-normal py-1 px-0" href="#"
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="animate-target">Washington</span>
</a>
<ul class="dropdown-menu fs-sm" style="--cz-dropdown-spacer: .5rem">
<li><a class="dropdown-item" href="#!">Chicago</a></li>
<li><a class="dropdown-item" href="#!">Los Angeles</a></li>
<li><a class="dropdown-item" href="#!">New York</a></li>
<li><a class="dropdown-item" href="#!">Philadelphia</a></li>
</ul>
</div>
<x-language-selector-sidebar />
<x-location-selector-sidebar />
</div>
<div class="offcanvas-body pt-1 pb-3 py-lg-0">
<div class="container pb-lg-2 px-0 px-lg-3">
@ -1788,9 +1699,9 @@
<!-- Breadcrumb -->
<nav class="container pt-2 pt-xxl-3 my-3 my-md-4" aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{{ route('second', ['home', 'fashion-v1']) }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('second', ['shop', 'catalog-fashion']) }}">Shop</a></li>
<li class="breadcrumb-item active" aria-current="page">Product page</li>
<li class="breadcrumb-item"><a href="{{ route('home') }}">Home</a></li>
<li class="breadcrumb-item"><a href="{{ route('home') }}">Product</a></li>
<li class="breadcrumb-item active" aria-current="page">Detail</li>
</ol>
</nav>
@ -1801,10 +1712,14 @@
<!-- Gallery -->
<div class="col-md-6 pb-4 pb-md-0 mb-2 mb-sm-3 mb-md-0">
<div class="position-relative">
@if ($product->display_discount_price > 0)
<span
class="badge text-bg-danger position-absolute top-0 start-0 z-2 mt-3 mt-sm-4 ms-3 ms-sm-4">Sale</span>
<button type="button"
@endif
<button type="button"
class="btn btn-icon btn-secondary animate-pulse fs-lg bg-transparent border-0 position-absolute top-0 end-0 z-2 mt-2 mt-sm-3 me-2 me-sm-3"
data-bs-toggle="tooltip" data-bs-placement="top" data-bs-custom-class="tooltip-sm"
data-bs-title="Add to Wishlist" aria-label="Add to Wishlist">
@ -1895,9 +1810,7 @@
<div class="h4 d-flex align-items-center my-4">
<span class="display_price">Rp {{ number_format($product->display_price, 0, ',', '.') }}</span>
@if ($product->discount_display_price)
<del class="display_discount_price fs-sm fw-normal text-body-tertiary ms-2"> Rp {{ number_format($product->discount_display_price, 0, ',', '.') }}</del>
@endif
<del class="display_discount_price fs-sm fw-normal text-body-tertiary ms-2" style="display: {{ $product->discount_display_price ? 'inline' : 'none' }};">{{ $product->discount_display_price ? ' Rp ' . number_format($product->discount_display_price, 0, ',', '.') : '' }}</del>
</div>
<!-- Color options -->
@ -1910,7 +1823,8 @@
<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($variant->display_price, 0, ",",".") }}"
data-image="{{ $variant->image_url }}"
data-discount-price="{{ $variant->discount_display_price ? 'Rp ' . number_format($variant->discount_display_price, 0, ',', '.') : '' }}"
data-image="{{ $variant->image_url ?? $product->image_url }}"
>
<img src="{{ $variant->image_url ?? $product->image_url }}" width="56"
alt="{{ $variant->name }}">
@ -1968,7 +1882,7 @@
</div>
<!-- Info list -->
<ul class="list-unstyled gap-3 pb-3 pb-lg-4 mb-3">
{{-- <ul class="list-unstyled gap-3 pb-3 pb-lg-4 mb-3">
<li class="d-flex flex-wrap fs-sm">
<span class="d-flex align-items-center fw-medium text-dark-emphasis me-2">
<i class="ci-clock fs-base me-2"></i>
@ -1983,10 +1897,10 @@
</span>
On all orders over $100.00
</li>
</ul>
</ul> --}}
<!-- Stock status -->
<div class="d-flex flex-wrap justify-content-between fs-sm mb-3">
{{-- <div class="d-flex flex-wrap justify-content-between fs-sm mb-3">
<span class="fw-medium text-dark-emphasis me-2">🔥 Hurry up! The sale is coming to an
end</span>
<span><span class="fw-medium text-dark-emphasis">6</span> items in stock!</span>
@ -1994,7 +1908,7 @@
<div class="progress" role="progressbar" aria-label="Left in stock" aria-valuenow="25"
aria-valuemin="0" aria-valuemax="100" style="height: 4px">
<div class="progress-bar rounded-pill" style="width: 25%"></div>
</div>
</div> --}}
</div>
</div>
</div>
@ -2077,23 +1991,7 @@
aria-labelledby="description-tab">
<div class="row">
<div class="col-lg-6 fs-sm">
<ul class="list-unstyled">
<li>Model's height: <span class="text-dark-emphasis fw-semibold">176 cm</span></li>
<li>The model is wearing size: <span class="text-dark-emphasis fw-semibold">S/36</span>
</li>
</ul>
<p>This skirt is designed to fall just below the knee, offering a flattering length that is
suitable for various occasions. It is made from a soft and lightweight fabric that drapes
beautifully, ensuring comfort and ease of movement. The blue color adds a vibrant touch,
making it a standout piece in your wardrobe.</p>
<ul>
<li>fitted waistband</li>
<li>fastened with a hidden zipper</li>
<li>midi length</li>
</ul>
<p class="mb-0">The blue color of the skirt allows for easy pairing with a variety of tops.
You can opt for a crisp white blouse for a classic and polished outfit, or choose a
patterned or contrasting-colored top for a more vibrant and fashion-forward look.</p>
{!! nl2br($product->description) !!}
</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">
@ -2496,224 +2394,30 @@
}'>
<div class="swiper-wrapper">
<!-- Slide -->
<div class="swiper-slide">
<div class="row row-cols-2">
@foreach ($complete_look_products as $key => $value)
<div class="swiper-slide">
<div class="row row-cols-2">
<!-- Item -->
{{-- <div class="col">
<x-home.product-card :product="$product" />
</div> --}}
@foreach ($value as $key2 => $value2)
<div class="col">
<x-home.product-card :product="$value2" />
<!-- Item -->
<div class="col">
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
<button type="button"
class="btn btn-icon btn-secondary animate-pulse fs-base bg-transparent border-0 position-absolute top-0 end-0 z-2 mt-1 mt-sm-2 me-1 me-sm-2"
aria-label="Add to Wishlist">
<i class="ci-heart animate-target"></i>
</button>
<a class="d-flex bg-body-tertiary rounded p-3" href="#!">
<div class="ratio"
style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/07.png" alt="Image">
</div>
</a>
<div
class="hover-effect-target position-absolute start-0 bottom-0 w-100 z-2 opacity-0 pb-2 pb-sm-3 px-2 px-sm-3">
<div
class="d-flex align-items-center justify-content-center gap-2 gap-xl-3 bg-body rounded-2 p-2">
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">6</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">6.5</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">7</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">7.5</span>
<div class="nav">
<a class="nav-link fs-xs text-body-tertiary py-1 px-2"
href="#!">+4</a>
</div>
</div>
</div>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="#!">
<span class="text-truncate">Black massive women's boots</span>
</a>
</div>
<div class="h6 mb-2">$160.00</div>
<div class="position-relative">
<div class="hover-effect-target fs-xs text-body-secondary opacity-100">+1
color</div>
<div
class="hover-effect-target d-flex gap-2 position-absolute top-0 start-0 opacity-0">
<input type="radio" class="btn-check" name="colors-7"
id="color-7-1" checked>
<label for="color-7-1" class="btn btn-color fs-base"
style="color: #364254">
<span class="visually-hidden">Black</span>
</label>
<input type="radio" class="btn-check" name="colors-7"
id="color-7-2">
<label for="color-7-2" class="btn btn-color fs-base"
style="color: #e0e5eb">
<span class="visually-hidden">White</span>
</label>
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
<!-- Slide -->
<div class="swiper-slide">
<div class="row row-cols-2">
@endforeach
<!-- Item -->
<div class="col">
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
<button type="button"
class="btn btn-icon btn-secondary animate-pulse fs-base bg-transparent border-0 position-absolute top-0 end-0 z-2 mt-1 mt-sm-2 me-1 me-sm-2"
aria-label="Add to Wishlist">
<i class="ci-heart animate-target"></i>
</button>
<a class="d-flex bg-body-tertiary rounded p-3" href="#!">
<div class="ratio"
style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/09.png" alt="Image">
</div>
</a>
<div
class="hover-effect-target position-absolute start-0 bottom-0 w-100 z-2 opacity-0 pb-2 pb-sm-3 px-2 px-sm-3">
<div
class="d-flex align-items-center justify-content-center gap-2 gap-xl-3 bg-body rounded-2 p-2">
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">XS</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">S</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">M</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">L</span>
<div class="nav">
<a class="nav-link fs-xs text-body-tertiary py-1 px-2"
href="#!">+3</a>
</div>
</div>
</div>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="#!">
<span class="text-truncate">White cotton blouse with necklace</span>
</a>
</div>
<div class="h6 mb-2">$38.50</div>
<div class="position-relative">
<div class="hover-effect-target fs-xs text-body-secondary opacity-100">+1
color</div>
<div
class="hover-effect-target d-flex gap-2 position-absolute top-0 start-0 opacity-0">
<input type="radio" class="btn-check" name="colors-9"
id="color-9-1" checked>
<label for="color-9-1" class="btn btn-color fs-base"
style="color: #e0e5eb">
<span class="visually-hidden">White</span>
</label>
<input type="radio" class="btn-check" name="colors-9"
id="color-9-2">
<label for="color-9-2" class="btn btn-color fs-base"
style="color: #364254">
<span class="visually-hidden">Black</span>
</label>
</div>
</div>
</div>
</div>
<!-- Item -->
<div class="col">
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
<button type="button"
class="btn btn-icon btn-secondary animate-pulse fs-base bg-transparent border-0 position-absolute top-0 end-0 z-2 mt-1 mt-sm-2 me-1 me-sm-2"
aria-label="Add to Wishlist">
<i class="ci-heart animate-target"></i>
</button>
<a class="d-flex bg-body-tertiary rounded p-3" href="#!">
<div class="ratio"
style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/08.png" alt="Image">
</div>
</a>
<div
class="hover-effect-target position-absolute start-0 bottom-0 w-100 z-2 opacity-0 pb-2 pb-sm-3 px-2 px-sm-3">
<div
class="d-flex align-items-center justify-content-center gap-2 gap-xl-3 bg-body rounded-2 p-2">
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">6.5</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">7</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">7.5</span>
<span
class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">8</span>
<div class="nav">
<a class="nav-link fs-xs text-body-tertiary py-1 px-2"
href="#!">+3</a>
</div>
</div>
</div>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="#!">
<span class="text-truncate">Leather sneakers with golden laces</span>
</a>
</div>
<div class="h6 mb-2">$74.00</div>
<div class="position-relative">
<div class="hover-effect-target fs-xs text-body-secondary opacity-100">+2
colors</div>
<div
class="hover-effect-target d-flex gap-2 position-absolute top-0 start-0 opacity-0">
<input type="radio" class="btn-check" name="colors-8"
id="color-8-1" checked>
<label for="color-8-1" class="btn btn-color fs-base"
style="color: #b1aa9b">
<span class="visually-hidden">Cream</span>
</label>
<input type="radio" class="btn-check" name="colors-8"
id="color-8-2">
<label for="color-8-2" class="btn btn-color fs-base"
style="color: #496c33">
<span class="visually-hidden">Dark green</span>
</label>
<input type="radio" class="btn-check" name="colors-8"
id="color-8-3">
<label for="color-8-3" class="btn btn-color fs-base"
style="color: #364254">
<span class="visually-hidden">Black</span>
</label>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Product image -->
<div class="col-md-6 order-md-1">
<img src="/img/shop/fashion/product/01.png" class="d-block bg-body-tertiary rounded"
<img src="{{ $product->image_url ?? '' }}" class="d-block bg-body-tertiary rounded"
alt="Image">
</div>
</div>
@ -3306,14 +3010,28 @@ document.addEventListener('DOMContentLoaded', function() {
radio.addEventListener('change', function() {
const label = document.querySelector(`label[for="${this.id}"]`);
const price = label.getAttribute('data-price');
const discountPrice = label.getAttribute('data-discount-price');
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) {
discountSpan.textContent = ' ' + discountPrice;
discountSpan.style.display = 'inline';
} else {
discountSpan.style.display = 'none';
}
document.querySelector('.product-main-image').src = image;
document.querySelector('#colorOption').textContent = labelText;
});
});
// Trigger change for the initially checked radio
const checkedRadio = document.querySelector('input[name="colors"]:checked');
if (checkedRadio) {
checkedRadio.dispatchEvent(new Event('change'));
}
});
</script>
@endsection