product grid

This commit is contained in:
bayu 2025-12-30 16:08:16 +07:00
parent c384576119
commit b00378ba8f
11 changed files with 634 additions and 459 deletions

33
app/Models/Discount.php Normal file
View File

@ -0,0 +1,33 @@
<?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 Discount extends Model
{
use HasFactory;
use LogsActivity;
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults();
}
protected $fillable = ['name', 'valid_at', 'expired_at', 'customer_group_id', 'discount_percent','location_id', 'type', 'apply_point', 'apply_incentive'];
public function discountItems() {
return $this->hasMany(DiscountItem::class);
}
public function customerGroup() {
return $this->belongsTo(CustomerGroup::class);
}
public function location() {
return $this->belongsTo(Location::class);
}
}

View File

@ -0,0 +1,23 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class DiscountItem extends Model
{
use HasFactory;
protected $fillable = ['item_reference_id', 'price', 'discount_id', 'percent', 'original_price'];
public function itemReference()
{
return $this->belongsTo(ItemReference::class);
}
public function discount()
{
return $this->belongsTo(Discount::class);
}
}

13
app/Models/ItemImage.php Normal file
View File

@ -0,0 +1,13 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class ItemImage extends Model
{
use HasFactory;
protected $fillable = ["filename", "item_id", "item_reference_id", "item_variant_id", "is_main"];
}

View File

@ -0,0 +1,203 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Awobaz\Compoships\Compoships;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Cache;
class ItemReference extends Model
{
use HasFactory, Compoships;
protected $table = 'item_reference';
protected $primaryKey = 'id';
protected $fillable = ['item_id','item_variant_id','number','unit'];
public function images()
{
return $this->hasMany(ItemImage::class, 'item_id', 'item_id');
}
public function item()
{
return $this->belongsTo(Items::class)->with("brand", "gender", "category");
}
public function itemVariant()
{
return $this->belongsTo(ItemVariant::class);
}
public function variants()
{
$model = ItemVariant::where('item_id', $this->item_id)->get();
return $model;
}
public function location()
{
return $this->belongsTo(Location::class, "location_id");
}
public function stocks()
{
return $this->hasMany(Stock::class, ["item_id", "item_variant_id"], ["item_id", "item_variant_id"])
->with("location");
}
public function bucketStocks()
{
return $this->hasMany(BucketStock::class)->with("bucket");
// ->where("quantity",">",0);
}
public function promotion()
{
return $this->belongsToMany(Promotion::class, "promotion_item", "item_id", "promotion_id");
}
public function price()
{
$user = auth()->user();
[$location_id, $is_consignment] = Cache::remember(
"employee_user_" . optional($user)->id,
60,
function () use ($user) {
if (!$user) {
return [10, false];
}
$employee = $user->employee;
$location_id = $employee->location_id ?? 10;
$location = $employee->location;
$is_consignment = (bool) optional($location)->is_consignment
&& optional($location)->id != 9;
return [$location_id, $is_consignment];
}
);
return $this->hasOne(Discount::class, 'id', 'item_reference_id')
->leftJoin('discount_items', 'discount_items.discount_id', '=', 'discounts.id')
->where('discounts.type', 'price')
->where(function ($query) {
$query->where('valid_at', '<=', now())
->orWhereNull('valid_at');
})
->where(function ($query) {
$query->where('expired_at', '>', now())
->orWhereNull('expired_at');
})
->where(function ($query) use ($location_id, $is_consignment) {
if (!$is_consignment) {
$query->whereNull('discounts.location_id');
}
if ($location_id) {
$query->orWhere('discounts.location_id', $location_id);
}
})
->orderByDesc('discounts.created_at')
->select([
'discount_items.item_reference_id',
'discount_items.price',
]);
}
public function discount()
{
$user = auth()->user();
list($location_id, $is_consignment) = Cache::remember("employee_user_".$user->id, 60 * 60 * 24, function(){
$employee = @$user->employee;
$location_id = @$employee->location_id ?? 10;
$location = @$employee->location;
$is_consignment = (boolean) @$location->is_consignment && $location->id != 9;
return [$location_id, $is_consignment];
});
// Log::info([$location_id, $is_consignment]);
return $this->hasOne(Discount::class,DB::raw("discount_items.item_reference_id"))
->leftJoin("discount_items","discounts.id","=","discount_id")
->where("discounts.type","discount")
->orderBy("discounts.created_at","desc")
->where(function($query){
$query->where("valid_at", "<=", Carbon::now())
->orWhereNull("valid_at");
})
->where(function($query){
$query->where("expired_at", ">", Carbon::now())
->orWhereNull("expired_at");
})
->where(function($query) use ($location_id, $is_consignment){
if (!$is_consignment)
$query->whereNull("discounts.location_id");
if ($location_id)
$query->orWhere("discounts.location_id", $location_id);
})
->select("item_reference_id","price");
}
public function point()
{
return $this->hasOne(CustomerPointRule::class);
}
public function promotion3()
{
$now = Carbon::now()->format('Y-m-d');
$promotions = "select DISTINCT ON (item_id) item_id as item_reference_id, name, note from
promotions left join promotion_item on promotions.id = promotion_id
where (valid_date is null or valid_date::date <= '$now')
and (expired_date is null or expired_date::date >= '$now')
and type <> 'POINT'";
$points = "select item_reference_id, array_agg((case when qty is null then '' else (qty || ': ') end) || point || ' Point' order by point asc) as name
from customer_point_rules
group by item_reference_id";
return $this->hasOne(ItemReference::class,"id")
->select('item_reference.id as item_reference_id',DB::raw("(case when points.name is null then promotions.name else array_to_string(points.name,', ') end) as promotion"),'promotions.note as promotion_note')
->leftJoin(DB::raw("(" . $promotions . ") as promotions"), "promotions.item_reference_id", "=", "item_reference.id")
->leftJoin(DB::raw("(" . $points . ") as points"), "points.item_reference_id", "=", "item_reference.id");
}
public function promotion2()
{
$now = Carbon::now()->format('Y-m-d');
$promotions = "select DISTINCT ON (item_id) item_id, name, note from
promotions left join promotion_item on promotions.id = promotion_id
where (valid_date is null or valid_date::date <= '$now')
and (expired_date is null or expired_date::date >= '$now')
and item_id = $this->id
and type <> 'POINT'";
$points = "select item_reference_id, array_agg((case when qty is null then '' else (qty || ': ') end) || point || ' Point' order by point asc) as name
from customer_point_rules
where item_reference_id = $this->id
group by item_reference_id";
$result = DB::table('item_reference')
->select(DB::raw("(case when points.name is null then promotions.name else array_to_string(points.name,', ') end) as promotion"),
'promotions.note as promotion_note')
->leftJoin(DB::raw("(" . $promotions . ") as promotions"), "promotions.item_id", "=", "item_reference.id")
->leftJoin(DB::raw("(" . $points . ") as points"), "points.item_reference_id", "=", "item_reference.id")
->where('item_reference.id', $this->id)
->first();
return $result;
}
}

View File

@ -0,0 +1,53 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Awobaz\Compoships\Compoships;
class ItemVariant extends Model
{
use HasFactory;
use Compoships;
protected $table = 'item_variants';
protected $primaryKey = 'id';
protected $fillable = [
'id',
'code',
'description',
'item_id',
'display_name',
'is_publish',
'barcode',
'variant_name',
];
public function reference()
{
return $this->belongsTo(ItemReference::class, ["item_id", "id"], ["item_id", "item_variant_id"]);
}
public function variables()
{
return $this->belongsToMany(Variant::class, "variant_value")->select("id", "name", "value");
}
public function image()
{
return $this->hasOne(ItemImage::class)->where('item_id', $this->item_id);
}
public function images()
{
return $this->hasMany(ItemImage::class)->where('item_id', $this->item_id);
}
public function variantValue()
{
return $this->hasMany(\App\Models\VariantValue::class, 'item_variant_id');
}
}

View File

@ -8,15 +8,17 @@ use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Database\Eloquent\SoftDeletes;
use Carbon\Carbon; use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use DB; use Illuminate\Support\Facades\Cache;
// use Awobaz\Compoships\Compoships; use Illuminate\Support\Facades\DB;
use Awobaz\Compoships\Compoships;
use Spatie\Activitylog\LogOptions; use Spatie\Activitylog\LogOptions;
use Cache;
use Illuminate\Support\Facades\Storage;
class Items extends Model class Items extends Model
{ {
use HasFactory, SoftDeletes; use HasFactory, SoftDeletes;
// use Compoships; use Compoships;
public function getActivitylogOptions(): LogOptions public function getActivitylogOptions(): LogOptions
{ {
@ -95,7 +97,7 @@ class Items extends Model
{ {
return $this->hasMany(ItemVariant::class,"item_id")->leftJoin("stocks","item_variant_id","=","item_variants.id") return $this->hasMany(ItemVariant::class,"item_id")->leftJoin("stocks","item_variant_id","=","item_variants.id")
->select("item_variants.id","item_variants.code","item_variants.display_name","item_variants.is_publish", DB::raw("SUM(quantity) as stock"),"description","item_variants.item_id") ->select("item_variants.id","item_variants.code","item_variants.display_name","item_variants.is_publish", DB::raw("SUM(quantity) as stock"),"description","item_variants.item_id")
->groupBy("item_variants.id","item_variants.code","description","item_variants.item_id"); ->groupBy("item_variants.id","item_variants.code","description","item_variants.item_id","item_variants.display_name","item_variants.is_publish");
} }
public function images() public function images()
@ -141,45 +143,89 @@ class Items extends Model
public function discount() public function discount()
{ {
$user = auth()->user(); $user = auth()->user();
list($location_id, $is_consignment) = Cache::remember("employee_user_".$user->id, 60 * 60 * 24, function() use ($user){
if ($user == null)
return [10, false];
$employee = @$user->employee; [$location_id, $is_consignment] = Cache::remember(
$location_id = @$employee->location_id; 'employee_user_' . optional($user)->id,
$location = @$employee->location; 60 * 60 * 24,
$is_consignment = (boolean) @$location->is_consignment; function () use ($user) {
return [$location_id, $is_consignment]; if (!$user) {
return [10, false];
}
}); $employee = $user->employee;
$location = $employee?->location;
return [
$employee?->location_id,
(bool) optional($location)->is_consignment,
];
}
);
// return $this->hasOne(Discount::class,DB::raw("item_reference.item_id"))
// ->leftJoin('discount_items', 'discount_items.discount_id', '=', 'discounts.id')
// ->leftJoin('item_reference', 'item_reference.id', '=', 'discount_items.item_reference_id')
// ->where('discounts.type', 'discount')
// ->where(function ($query) {
// $query->whereNull('valid_at')
// ->orWhere('valid_at', '<=', now());
// })
// ->where(function ($query) {
// $query->whereNull('expired_at')
// ->orWhere('expired_at', '>=', now());
// })
// ->where(function ($query) use ($location_id, $is_consignment) {
// if (!$is_consignment) {
// $query->whereNull('discounts.location_id');
// }
// if ($location_id) {
// $query->orWhere('discounts.location_id', $location_id);
// }
// })
// ->orderByDesc('discounts.created_at')
// ->select([
// 'item_reference.item_id',
// 'discount_items.price',
// ]);
return $this->hasOne(DiscountItem::class, 'item_reference_id', 'id')
->leftJoin('discounts', 'discounts.id', '=', 'discount_items.discount_id')
->leftJoin('item_reference', 'item_reference.id', '=', 'discount_items.item_reference_id')
->where('discounts.type', 'discount')
->where(function ($q) {
$q->whereNull('discounts.valid_at')
->orWhere('discounts.valid_at', '<=', now());
})
->where(function ($q) {
$q->whereNull('discounts.expired_at')
->orWhere('discounts.expired_at', '>=', now());
})
->where(function ($q) use ($location_id, $is_consignment) {
if (!$is_consignment) {
$q->whereNull('discounts.location_id');
}
if ($location_id) {
$q->orWhere('discounts.location_id', $location_id);
}
})
->orderByDesc('discounts.created_at')
->select([
'item_reference.item_id',
'discount_items.price',
]);
return $this->hasOne(Discount::class,DB::raw("item_reference.item_id"))
->leftJoin("discount_items","discounts.id","=","discount_id")
->leftJoin("item_reference","item_reference.id","=","item_reference_id")
->where("discounts.type","discount")
->orderBy("discounts.created_at","desc")
->where(function ($query) {
$query->whereNull("valid_at")
->orWhereDate("valid_at", "<=", Carbon::now());
})
->where(function ($query) {
$query->whereNull("expired_at")
->orWhereDate("expired_at", ">=", Carbon::now());
})
->where(function($query) use ($location_id, $is_consignment){
if (!$is_consignment)
$query->whereNull("discounts.location_id");
if ($location_id)
$query->orWhere("discounts.location_id", $location_id);
})
->select("item_id","price");
} }
public function price() public function price()
{ {
$user = auth()->user(); $user = auth()->user();
list($location_id, $is_consignment) = Cache::remember("employee_user_".$user->id, 60 * 60 * 24, function() use ($user){ $userId = $user ? $user->id : 0;
list($location_id, $is_consignment) = Cache::remember("employee_user_".$userId, 60 * 60 * 24, function() use ($user){
if ($user == null) if ($user == null)
return [10, false]; return [10, false];
@ -229,4 +275,50 @@ class Items extends Model
{ {
return $this->hasMany(ItemAttribute::class, 'item_id'); return $this->hasMany(ItemAttribute::class, 'item_id');
} }
public function getImageUrlAttribute()
{
$image = $this->images->first()->filename ?? null;
if (str_contains($image,"http")) {
return $image;
}
return $image ? Storage::disk('wms')->url($image) : null;
}
public function conversion_value()
{
$convertion = 1;
if (($this->display_unit != $this->unit) and ($this->display_unit)){
$convertions = DB::select("select to_qty / from_qty as conv
from item_convertions where from_unit = ? and to_unit = ?",
[$this->display_unit, $this->unit] );
$convertion = max((float) @$convertions[0]->conv,1);
}
return $convertion;
}
public function getDisplayPriceAttribute()
{
$convertion = $this->conversion_value();
$price = @$this->variants->first()->reference->price->price ?? null;
$price = $price ? $price : $this->net_price;
return (float) $price * $convertion;
}
public function getDisplayDiscountPriceAttribute()
{
$convertion = $this->conversion_value();
$discountPrice = @$this->discount->price ?? 0;
return (float) $discountPrice * $convertion;
}
} }

View File

@ -0,0 +1,29 @@
<?php
namespace App\View\Components\Home;
use App\Repositories\Catalog\ProductRepository;
use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;
class ProductHighlight extends Component
{
public $products;
public function __construct(ProductRepository $productRepository)
{
$params = [
'sort' => 'new',
];
$this->products = $productRepository->getList($params);
}
/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return view('components.home.product-highlight');
}
}

View File

@ -10,6 +10,7 @@
"license": "MIT", "license": "MIT",
"require": { "require": {
"php": "^8.2", "php": "^8.2",
"awobaz/compoships": "^2.5",
"laravel/framework": "^12.0", "laravel/framework": "^12.0",
"laravel/tinker": "^2.10.1", "laravel/tinker": "^2.10.1",
"spatie/laravel-activitylog": "^4.10" "spatie/laravel-activitylog": "^4.10"

64
composer.lock generated
View File

@ -4,8 +4,70 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "040332991bd2bf1daab2e1f01063d4a5", "content-hash": "39a129e1371f7351b7cd6beab65a522a",
"packages": [ "packages": [
{
"name": "awobaz/compoships",
"version": "2.5.4",
"source": {
"type": "git",
"url": "https://github.com/topclaudy/compoships.git",
"reference": "dcae8012a8704fc2acd8dce2d8a1b35ce292adbe"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/topclaudy/compoships/zipball/dcae8012a8704fc2acd8dce2d8a1b35ce292adbe",
"reference": "dcae8012a8704fc2acd8dce2d8a1b35ce292adbe",
"shasum": ""
},
"require": {
"illuminate/database": ">=5.6 <13.0"
},
"require-dev": {
"ext-sqlite3": "*",
"fakerphp/faker": "^1.18",
"phpunit/phpunit": "^6.0|^8.0|^9.0|^10.0|^11.0|^12.0"
},
"suggest": {
"awobaz/blade-active": "Blade directives for the Laravel 'Active' package",
"awobaz/eloquent-auto-append": "Automatically append accessors to model serialization",
"awobaz/eloquent-mutators": "Reusable mutators (getters/setters) for Laravel 5's Eloquent",
"awobaz/syntactic": "Syntactic sugar for named and indexed parameters call."
},
"type": "library",
"autoload": {
"psr-4": {
"Awobaz\\Compoships\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Claudin J. Daniel",
"email": "cdaniel@awobaz.com"
}
],
"description": "Laravel relationships with support for composite/multiple keys",
"keywords": [
"laravel",
"laravel composite keys",
"laravel relationships"
],
"support": {
"issues": "https://github.com/topclaudy/compoships/issues",
"source": "https://github.com/topclaudy/compoships/tree/2.5.4"
},
"funding": [
{
"url": "https://paypal.me/awobaz",
"type": "custom"
}
],
"time": "2025-12-23T18:33:46+00:00"
},
{ {
"name": "brick/math", "name": "brick/math",
"version": "0.13.1", "version": "0.13.1",

View File

@ -0,0 +1,88 @@
<section class="container pb-5 mb-2 mb-sm-3 mb-lg-4 mb-xl-5">
<h2 class="text-center pb-2 pb-sm-3">This week's highlights</h2>
<!-- Nav pills -->
<div class="row g-0 overflow-x-auto pb-2 pb-sm-3 mb-3">
<div class="col-auto pb-1 pb-sm-0 mx-auto">
<ul class="nav nav-pills flex-nowrap text-nowrap">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#!">Best sellers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!">New arrivals</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!">Sale items</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!">Top rated</a>
</li>
</ul>
</div>
</div>
<!-- Products grid -->
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-4 gy-4 gy-md-5 pb-xxl-3">
<!-- Item -->
@foreach ($products as $key => $product)
<div class="col mb-2 mb-sm-3 mb-md-0">
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
<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"
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="{{ route('second', ['shop', 'product-fashion']) }}">
<div class="ratio" style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="{{ $product->image_url }}" loading="lazy" class="w-100 h-100 object-cover">
</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="{{ route('second', ['shop', 'product-fashion']) }}">+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="{{ route('second', ['shop', 'product-fashion']) }}">
<span class="text-truncate">{{ $product->name ?? '' }}</span>
</a>
</div>
<div class="h6 mb-2">Rp {{ number_format($product->display_price,0,",",".") }} @if ($product->display_discount_price > 0)<del class="fs-sm fw-normal text-body-tertiary">Rp {{ number_format($product->display_discount_price,0,",",".") }}</del>@endif</div>
<div class="position-relative">
@if ($product->variants->count() > 1)
<div class=" fs-xs text-body-secondary opacity-100">+{{ $product->variants->count() - 1 }} Varian</div>
@endif
{{-- <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-1" id="color-1-1" checked>
<label for="color-1-1" class="btn btn-color fs-base" style="color: #284971">
<span class="visually-hidden">Dark denim</span>
</label>
<input type="radio" class="btn-check" name="colors-1" id="color-1-2">
<label for="color-1-2" class="btn btn-color fs-base" style="color: #8b9bc4">
<span class="visually-hidden">Light denim</span>
</label>
</div> --}}
</div>
</div>
</div>
@endforeach
</div>
</section>

View File

@ -1345,429 +1345,7 @@
<!-- Featured products --> <!-- Featured products -->
<section class="container pb-5 mb-2 mb-sm-3 mb-lg-4 mb-xl-5"> <x-home.product-highlight />
<h2 class="text-center pb-2 pb-sm-3">This week's highlights</h2>
<!-- Nav pills -->
<div class="row g-0 overflow-x-auto pb-2 pb-sm-3 mb-3">
<div class="col-auto pb-1 pb-sm-0 mx-auto">
<ul class="nav nav-pills flex-nowrap text-nowrap">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="#!">Best sellers</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!">New arrivals</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!">Sale items</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#!">Top rated</a>
</li>
</ul>
</div>
</div>
<!-- Products grid -->
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-4 gy-4 gy-md-5 pb-xxl-3">
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
<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"
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="{{ route('second', ['shop', 'product-fashion']) }}">
<div class="ratio" style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/01.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="{{ route('second', ['shop', 'product-fashion']) }}">+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="{{ route('second', ['shop', 'product-fashion']) }}">
<span class="text-truncate">Denim midi skirt with pockets</span>
</a>
</div>
<div class="h6 mb-2">$126.50 <del class="fs-sm fw-normal text-body-tertiary">$156.00</del></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-1" id="color-1-1" checked>
<label for="color-1-1" class="btn btn-color fs-base" style="color: #284971">
<span class="visually-hidden">Dark denim</span>
</label>
<input type="radio" class="btn-check" name="colors-1" id="color-1-2">
<label for="color-1-2" class="btn btn-color fs-base" style="color: #8b9bc4">
<span class="visually-hidden">Light denim</span>
</label>
</div>
</div>
</div>
</div>
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<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="{{ route('second', ['shop', 'product-fashion']) }}">
<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="{{ route('second', ['shop', 'product-fashion']) }}">+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="{{ route('second', ['shop', 'product-fashion']) }}">
<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>
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<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/11.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">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>
<span class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">XL</span>
<div class="nav">
<a class="nav-link fs-xs text-body-tertiary py-1 px-2" href="#!">+1</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">Warm sweatshirts without a hoodie</span>
</a>
</div>
<div class="h6 mb-2">$32.99</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-11" id="color-11-1" checked>
<label for="color-11-1" class="btn btn-color fs-base" style="color: #42675f">
<span class="visually-hidden">Green</span>
</label>
<input type="radio" class="btn-check" name="colors-11" id="color-11-2">
<label for="color-11-2" class="btn btn-color fs-base" style="color: #476585">
<span class="visually-hidden">Blue</span>
</label>
<input type="radio" class="btn-check" name="colors-11" id="color-11-3">
<label for="color-11-3" class="btn btn-color fs-base" style="color: #724c74">
<span class="visually-hidden">Purple</span>
</label>
</div>
</div>
</div>
</div>
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<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="{{ route('second', ['shop', 'product-fashion']) }}">
<div class="ratio" style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/04.png" alt="Image">
</div>
</a>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="{{ route('second', ['shop', 'product-fashion']) }}">
<span class="text-truncate">Knitted bag with a wooden handle</span>
</a>
</div>
<div class="h6 mb-2">$105.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-4" id="color-4-1" checked>
<label for="color-4-1" class="btn btn-color fs-base" style="color: #e7ddb4">
<span class="visually-hidden">Beige</span>
</label>
<input type="radio" class="btn-check" name="colors-4" id="color-4-2">
<label for="color-4-2" class="btn btn-color fs-base" style="color: #8b9bc4">
<span class="visually-hidden">Blue</span>
</label>
</div>
</div>
</div>
</div>
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<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="{{ route('second', ['shop', 'product-fashion']) }}">
<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="{{ route('second', ['shop', 'product-fashion']) }}">+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="{{ route('second', ['shop', 'product-fashion']) }}">
<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 mb-2 mb-sm-3 mb-md-0">
<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="{{ route('second', ['shop', 'product-fashion']) }}">
<div class="ratio" style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/10.png" alt="Image">
</div>
</a>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="{{ route('second', ['shop', 'product-fashion']) }}">
<span class="text-truncate">Leather handbag for women</span>
</a>
</div>
<div class="h6 mb-2">$140.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-10" id="color-10-1" checked>
<label for="color-10-1" class="btn btn-color fs-base" style="color: #869286">
<span class="visually-hidden">Olive</span>
</label>
<input type="radio" class="btn-check" name="colors-10" id="color-10-2">
<label for="color-10-2" class="btn btn-color fs-base" style="color: #364254">
<span class="visually-hidden">Black</span>
</label>
<input type="radio" class="btn-check" name="colors-10" id="color-10-3">
<label for="color-10-3" class="btn btn-color fs-base" style="color: #526f99">
<span class="visually-hidden">Blue</span>
</label>
</div>
</div>
</div>
</div>
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<div class="animate-underline hover-effect-opacity">
<div class="position-relative mb-3">
<span
class="badge text-bg-danger position-absolute top-0 start-0 z-2 mt-2 mt-sm-3 ms-2 ms-sm-3">-17%</span>
<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="{{ route('second', ['shop', 'product-fashion']) }}">
<div class="ratio" style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/05.png" alt="Image">
</div>
</a>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="{{ route('second', ['shop', 'product-fashion']) }}">
<span class="text-truncate">Polarized sunglasses for men</span>
</a>
</div>
<div class="h6 mb-2">$96.00 <del class="fs-sm fw-normal text-body-tertiary">$112.00</del></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-5" id="color-5-1" checked>
<label for="color-5-1" class="btn btn-color fs-base" style="color: #8cc4ac">
<span class="visually-hidden">Green</span>
</label>
<input type="radio" class="btn-check" name="colors-5" id="color-5-2">
<label for="color-5-2" class="btn btn-color fs-base" style="color: #8cb7c4">
<span class="visually-hidden">Blue</span>
</label>
<input type="radio" class="btn-check" name="colors-5" id="color-5-3">
<label for="color-5-3" class="btn btn-color fs-base" style="color: #ccb782">
<span class="visually-hidden">Brown</span>
</label>
</div>
</div>
</div>
</div>
<!-- Item -->
<div class="col mb-2 mb-sm-3 mb-md-0">
<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="{{ route('second', ['shop', 'product-fashion']) }}">
<div class="ratio" style="--cz-aspect-ratio: calc(308 / 274 * 100%)">
<img src="/img/shop/fashion/06.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">M</span>
<span class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">L</span>
<span class="fs-xs fw-medium text-secondary-emphasis py-1 px-sm-2">XL</span>
</div>
</div>
</div>
<div class="nav mb-2">
<a class="nav-link animate-target min-w-0 text-dark-emphasis p-0"
href="{{ route('second', ['shop', 'product-fashion']) }}">
<span class="text-truncate">Classic cotton men's shirt</span>
</a>
</div>
<div class="h6 mb-2">$27.00</div>
<div class="position-relative">
<div class="hover-effect-target fs-xs text-body-secondary opacity-100">+3 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-6" id="color-6-1" checked>
<label for="color-6-1" class="btn btn-color fs-base" style="color: #c1cde7">
<span class="visually-hidden">Blue</span>
</label>
<input type="radio" class="btn-check" name="colors-6" id="color-6-2">
<label for="color-6-2" class="btn btn-color fs-base" style="color: #526f99">
<span class="visually-hidden">Dark blue</span>
</label>
<input type="radio" class="btn-check" name="colors-6" id="color-6-3">
<label for="color-6-3" class="btn btn-color fs-base" style="color: #e0e5eb">
<span class="visually-hidden">White</span>
</label>
<input type="radio" class="btn-check" name="colors-6" id="color-6-4">
<label for="color-6-4" class="btn btn-color fs-base" style="color: #364254">
<span class="visually-hidden">Black</span>
</label>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Special collection carousel --> <!-- Special collection carousel -->
<section class="container pb-5 mb-2 mb-sm-3 mb-lg-4 mb-xl-5"> <section class="container pb-5 mb-2 mb-sm-3 mb-lg-4 mb-xl-5">