popular product, brand
This commit is contained in:
parent
6117a3580a
commit
3b91c813da
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ComponentController extends Controller
|
||||
{
|
||||
public function load(Request $request, $component)
|
||||
{
|
||||
$template = $request->get('template');
|
||||
|
||||
// Map component names to their blade views
|
||||
$componentMap = [
|
||||
'home-popular-products' => 'components.home.home-popular-products',
|
||||
'product-highlight' => 'components.home.product-highlight',
|
||||
'new-arrivals' => 'components.home.new-arrivals',
|
||||
'brand-home' => 'components.home.brand-home-' . ($template ?? 'fashion-v1'),
|
||||
];
|
||||
|
||||
$view = $componentMap[$component] ?? null;
|
||||
|
||||
if (!$view) {
|
||||
return response()->json(['error' => 'Component not found'], 404);
|
||||
}
|
||||
|
||||
// For brand-home component, we need to pass the template parameter
|
||||
if ($component === 'brand-home') {
|
||||
return view($view, ['template' => $template]);
|
||||
}
|
||||
|
||||
return view($view);
|
||||
}
|
||||
}
|
||||
|
|
@ -174,6 +174,98 @@ class ProductController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function brands(Request $request)
|
||||
{
|
||||
$brandRepository = new \App\Repositories\Catalog\BrandRepository;
|
||||
$brands = $brandRepository->getList([]);
|
||||
|
||||
// Render brand HTML
|
||||
$brandHtml = '';
|
||||
foreach ($brands as $brand) {
|
||||
$brandHtml .= '<a class="swiper-slide text-body" href="' . route('product.index', ['brand' => $brand->slug]) . '" aria-label="' . $brand->name . '">';
|
||||
$brandHtml .= '<img src="' . $brand->image_url . '" alt="' . $brand->name . '" class="object-fit-contain">';
|
||||
$brandHtml .= '</a>';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'brands' => $brandHtml
|
||||
]);
|
||||
}
|
||||
|
||||
public function highlights(Request $request)
|
||||
{
|
||||
$type = $request->input('type', 'new');
|
||||
$limit = 8;
|
||||
|
||||
$user = auth()->user();
|
||||
$userId = $user ? $user->id : 0;
|
||||
[$location_id, $is_consignment] = Cache::remember('employee_user_'.$userId, 60 * 60 * 24, function () use ($user) {
|
||||
|
||||
if ($user == null) {
|
||||
return [10, false];
|
||||
}
|
||||
|
||||
$employee = @$user->employee;
|
||||
$location_id = @$employee->location_id;
|
||||
$location = @$employee->location;
|
||||
$is_consignment = (bool) @$location->is_consignment;
|
||||
|
||||
return [$location_id, $is_consignment];
|
||||
|
||||
});
|
||||
|
||||
$productRepository = new ProductRepository;
|
||||
|
||||
// Set parameters based on type
|
||||
$params = [
|
||||
'limit' => $limit,
|
||||
'location_id' => $location_id,
|
||||
'is_consignment' => $is_consignment,
|
||||
];
|
||||
|
||||
switch ($type) {
|
||||
case 'best_sellers':
|
||||
$params['sort'] = 'random';
|
||||
break;
|
||||
case 'new_arrivals':
|
||||
$params['sort'] = 'new';
|
||||
break;
|
||||
case 'sale_items':
|
||||
$params['event'] = 'special-offer';
|
||||
break;
|
||||
case 'top_rated':
|
||||
$params['sort'] = 'random';
|
||||
break;
|
||||
default:
|
||||
$params['sort'] = 'new';
|
||||
break;
|
||||
}
|
||||
|
||||
$products = $productRepository->getList($params);
|
||||
|
||||
// Render product cards HTML
|
||||
$productHtml = '';
|
||||
if (count($products) == 0) {
|
||||
$productHtml = '<div class="col-12 text-center py-4">';
|
||||
$productHtml .= 'No products found';
|
||||
$productHtml .= '</div>';
|
||||
} else {
|
||||
foreach ($products as $product) {
|
||||
$productHtml .= '<div class="col mb-2 mb-sm-3 mb-md-0">';
|
||||
$productHtml .= view('components.home.product-card', ['product' => $product])->render();
|
||||
$productHtml .= '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'products' => $productHtml,
|
||||
'count' => count($products),
|
||||
'type' => $type
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail($slug, Request $request, ProductRepository $productRepository)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -9,24 +9,16 @@ use Illuminate\View\Component;
|
|||
|
||||
class BrandHome extends Component
|
||||
{
|
||||
public $brands;
|
||||
|
||||
|
||||
public $template = 'fashion-v1';
|
||||
|
||||
/**
|
||||
* Create a new component instance.
|
||||
*/
|
||||
public function __construct(BrandRepository $brandRepository)
|
||||
public function __construct()
|
||||
{
|
||||
$this->brands = $brandRepository->getList([]);
|
||||
|
||||
if ($this->brands->count() < 9) {
|
||||
// Ensure we have at least 9 brands by duplicating if necessary
|
||||
while ($this->brands->count() < 9) {
|
||||
$this->brands = $this->brands->concat($this->brands);
|
||||
}
|
||||
$this->brands = $this->brands->take(9);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components\Home;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class HomePopularProducts extends Component
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.home.home-popular-products');
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
|
||||
namespace App\View\Components\Home;
|
||||
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\View\Component;
|
||||
|
||||
class HomeSlider extends Component
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the view / contents that represent the component.
|
||||
*/
|
||||
public function render(): View|Closure|string
|
||||
{
|
||||
return view('components.home.home-slider');
|
||||
}
|
||||
}
|
||||
|
|
@ -9,14 +9,11 @@ use Illuminate\View\Component;
|
|||
|
||||
class ProductHighlight extends Component
|
||||
{
|
||||
public $products;
|
||||
|
||||
public function __construct(ProductRepository $productRepository)
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$params = [
|
||||
'sort' => 'new',
|
||||
];
|
||||
$this->products = $productRepository->getList($params);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -34,4 +34,4 @@ import './components/binded-label'
|
|||
import './components/image-zoom'
|
||||
import './components/code-highlight'
|
||||
import './components/copy-text'
|
||||
import './components/chart'
|
||||
import './components/chart'
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<section class="container pb-5 mb-1 mb-sm-3 mb-lg-4 mb-xl-5">
|
||||
<div class="swiper my-md-3"
|
||||
data-swiper='{
|
||||
<section class="container pb-5 mb-1 mb-sm-3 mb-lg-4 mb-xl-5" id="brand-home-section">
|
||||
<div class="swiper my-md-3"
|
||||
data-swiper='{
|
||||
"slidesPerView": 2,
|
||||
"pagination": {
|
||||
"el": ".swiper-pagination",
|
||||
|
|
@ -24,21 +24,80 @@
|
|||
}
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-wrapper" id="brand-container">
|
||||
<!-- Brands will be loaded via AJAX -->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Pagination (Bullets) -->
|
||||
<div class="swiper-pagination position-static mt-3"></div>
|
||||
</div>
|
||||
|
||||
<!-- Item -->
|
||||
@foreach($brands as $brand)
|
||||
<a class="swiper-slide text-body" href="#!" aria-label="{{ $brand->name }}">
|
||||
<img src="{{ $brand->image_url }}" alt="{{ $brand->name }}" class="object-fit-contain">
|
||||
</a>
|
||||
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Pagination (Bullets) -->
|
||||
<div class="swiper-pagination position-static mt-3"></div>
|
||||
<!-- Loading state -->
|
||||
<div class="text-center py-5 d-none" id="brand-loading">
|
||||
<div class="swiper my-md-3">
|
||||
<div class="swiper-wrapper">
|
||||
@for ($i = 1; $i <= 6; $i++)
|
||||
<div class="swiper-slide text-body">
|
||||
<div class="shimmer-wrapper">
|
||||
<div class="shimmer">
|
||||
<div class="shimmer-content rounded">
|
||||
<div class="shimmer-line shimmer-image rounded"
|
||||
style="height: 60px; width: 100%; background-color: rgba(0, 0, 0, 0.1);">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endfor
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const brandContainer = document.getElementById('brand-container');
|
||||
const loadingSpinner = document.getElementById('brand-loading');
|
||||
const section = document.getElementById('brand-home-section');
|
||||
|
||||
if (!brandContainer || !loadingSpinner) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load brands on page load
|
||||
loadBrands();
|
||||
|
||||
function loadBrands() {
|
||||
// Show loading spinner
|
||||
loadingSpinner.classList.remove('d-none');
|
||||
|
||||
// Make AJAX request for brands
|
||||
fetch('{{ route("product.ajax.brands") }}')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.brands) {
|
||||
brandContainer.innerHTML = data.brands;
|
||||
} else {
|
||||
// Handle error
|
||||
brandContainer.innerHTML = '<div class="swiper-slide text-center py-4">Error loading brands</div>';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading brands:', error);
|
||||
brandContainer.innerHTML = '<div class="swiper-slide text-center py-4">Error loading brands</div>';
|
||||
})
|
||||
.finally(() => {
|
||||
// Hide loading spinner
|
||||
loadingSpinner.classList.add('d-none');
|
||||
|
||||
// Re-initialize Swiper
|
||||
if (window.Swiper) {
|
||||
const swiper = section.querySelector('.swiper');
|
||||
if (swiper && swiper.swiper) {
|
||||
swiper.swiper.update();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,248 @@
|
|||
<section class="container py-5 my-2 my-sm-3 my-lg-4 my-xl-5" id="popular-products-section">
|
||||
<div class="row align-items-lg-center py-xxl-3">
|
||||
|
||||
<!-- Products -->
|
||||
<div class="col-md-6 col-xl-5 offset-xl-1 order-md-2 mb-4 mb-md-0">
|
||||
<div class="ps-md-3 ps-lg-4 ps-xl-0">
|
||||
<div class="d-flex align-items-center justify-content-between pb-4 mb-md-1 mb-lg-2 mb-xl-3">
|
||||
<h2 class="me-3 mb-0">Popular products</h2>
|
||||
|
||||
<!-- 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="popularPrev" 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"
|
||||
id="popularNext" aria-label="Next">
|
||||
<i class="ci-chevron-right fs-lg animate-target"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Products master slider -->
|
||||
<div class="swiper"
|
||||
data-swiper='{
|
||||
"spaceBetween": 24,
|
||||
"loop": true,
|
||||
"speed": 400,
|
||||
"controlSlider": "#sliderImages",
|
||||
"navigation": {
|
||||
"prevEl": "#popularPrev",
|
||||
"nextEl": "#popularNext"
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper" id="popular-products-container">
|
||||
<!-- Products will be loaded via AJAX -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Images -->
|
||||
<div class="col-md-6 col-xl-5 order-md-1">
|
||||
<div class="position-relative">
|
||||
<div class="ratio d-none d-md-block" style="--cz-aspect-ratio: calc(720 / 636 * 100%)">
|
||||
</div>
|
||||
<div class="ratio ratio-4x3 d-md-none"></div>
|
||||
<div class="swiper position-absolute top-0 start-0 w-100 h-100 user-select-none"
|
||||
id="sliderImages"
|
||||
data-swiper='{
|
||||
"allowTouchMove": false,
|
||||
"loop": true,
|
||||
"effect": "fade",
|
||||
"fadeEffect": {
|
||||
"crossFade": true
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper" id="popular-images-container">
|
||||
<!-- Images will be loaded via AJAX -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading state -->
|
||||
<div class="text-center py-5 d-none" id="popular-products-loading">
|
||||
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-4 gy-4 gy-md-5 pb-xxl-3">
|
||||
@for ($i = 1; $i <= 6; $i++)
|
||||
<div class="col mb-2 mb-sm-3 mb-md-0">
|
||||
<div class="shimmer-wrapper">
|
||||
<div class="shimmer">
|
||||
<div class="shimmer-content rounded">
|
||||
<div class="shimmer-line shimmer-image rounded mb-3"
|
||||
style="height: 0; padding-bottom: 100%; position: relative;">
|
||||
<div
|
||||
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.1); border-radius: 4px;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="shimmer-line shimmer-title rounded mb-2"
|
||||
style="height: 20px; width: 80%;"></div>
|
||||
<div class="shimmer-line shimmer-price rounded" style="height: 16px; width: 60%;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endfor
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const productsContainer = document.getElementById('popular-products-container');
|
||||
const imagesContainer = document.getElementById('popular-images-container');
|
||||
const loadingSpinner = document.getElementById('popular-products-loading');
|
||||
const section = document.getElementById('popular-products-section');
|
||||
|
||||
if (!productsContainer || !imagesContainer || !loadingSpinner) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load popular products on page load
|
||||
loadPopularProducts();
|
||||
|
||||
function loadPopularProducts() {
|
||||
// Show loading spinner
|
||||
if (loadingSpinner) {
|
||||
loadingSpinner.classList.remove('d-none');
|
||||
}
|
||||
|
||||
// Make AJAX request for popular products
|
||||
fetch('{{ route("product.ajax.highlights") }}?type=best_sellers&limit=6')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.products) {
|
||||
// Parse the HTML to extract individual product cards
|
||||
const tempDiv = document.createElement('div');
|
||||
tempDiv.innerHTML = data.products;
|
||||
|
||||
const productCards = tempDiv.querySelectorAll('.col');
|
||||
const productsArray = Array.from(productCards);
|
||||
|
||||
// Split products into two slides (3 products each)
|
||||
const slide1 = productsArray.slice(0, 3);
|
||||
const slide2 = productsArray.slice(3, 6);
|
||||
|
||||
// Create slides with product lists
|
||||
productsContainer.innerHTML = '';
|
||||
|
||||
[slide1, slide2].forEach((slide, index) => {
|
||||
const slideDiv = document.createElement('div');
|
||||
slideDiv.className = 'swiper-slide';
|
||||
|
||||
const listDiv = document.createElement('div');
|
||||
listDiv.className = 'd-flex flex-column gap-3 gap-lg-4';
|
||||
|
||||
slide.forEach(product => {
|
||||
// Convert product card to list item format
|
||||
const productImg = product.querySelector('img');
|
||||
const productLink = product.querySelector('a');
|
||||
const productPrice = product.querySelector('.h6, .price');
|
||||
|
||||
const listItem = document.createElement('div');
|
||||
listItem.className = 'd-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline';
|
||||
|
||||
const img = document.createElement('img');
|
||||
img.src = productImg ? productImg.src : '/img/shop/fashion/thumbs/0' + (index * 3 + slide.indexOf(product) + 1) + '.png';
|
||||
img.width = 110;
|
||||
img.alt = 'Thumbnail';
|
||||
|
||||
const navDiv = document.createElement('div');
|
||||
navDiv.className = 'nav flex-column gap-2 min-w-0 p-3';
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.className = 'nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0';
|
||||
link.href = productLink ? productLink.href : '#';
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.className = 'animate-target text-truncate';
|
||||
span.textContent = productLink ? productLink.textContent.trim() : 'Product Name';
|
||||
|
||||
const price = document.createElement('div');
|
||||
price.className = 'h6 mb-0';
|
||||
price.textContent = productPrice ? productPrice.textContent : '$0.00';
|
||||
|
||||
link.appendChild(span);
|
||||
navDiv.appendChild(link);
|
||||
navDiv.appendChild(price);
|
||||
listItem.appendChild(img);
|
||||
listItem.appendChild(navDiv);
|
||||
listDiv.appendChild(listItem);
|
||||
});
|
||||
|
||||
slideDiv.appendChild(listDiv);
|
||||
productsContainer.appendChild(slideDiv);
|
||||
});
|
||||
|
||||
// Load corresponding images
|
||||
loadPopularImages();
|
||||
|
||||
} else {
|
||||
// Handle error
|
||||
productsContainer.innerHTML = '<div class="swiper-slide"><div class="text-center py-4">Error loading products</div></div>';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading popular products:', error);
|
||||
productsContainer.innerHTML = '<div class="swiper-slide"><div class="text-center py-4">Error loading products</div></div>';
|
||||
})
|
||||
.finally(() => {
|
||||
// Hide loading spinner
|
||||
if (loadingSpinner) {
|
||||
loadingSpinner.classList.add('d-none');
|
||||
}
|
||||
|
||||
// Re-initialize Swiper
|
||||
if (window.Swiper) {
|
||||
const swiperElements = section.querySelectorAll('.swiper');
|
||||
swiperElements.forEach(element => {
|
||||
if (element.swiper) {
|
||||
element.swiper.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPopularImages() {
|
||||
// Load images for the slider
|
||||
const images = [
|
||||
'/img/home/fashion/v1/popular/01.jpg',
|
||||
'/img/home/fashion/v1/popular/02.jpg'
|
||||
];
|
||||
|
||||
imagesContainer.innerHTML = '';
|
||||
|
||||
images.forEach((src, index) => {
|
||||
const slideDiv = document.createElement('div');
|
||||
slideDiv.className = 'swiper-slide';
|
||||
|
||||
const ratioDiv = document.createElement('div');
|
||||
ratioDiv.className = index === 0 ? 'ratio d-none d-md-block' : 'ratio d-none d-md-block';
|
||||
ratioDiv.style.setProperty('--cz-aspect-ratio', 'calc(720 / 636 * 100%)');
|
||||
|
||||
const mobileRatioDiv = document.createElement('div');
|
||||
mobileRatioDiv.className = 'ratio ratio-4x3 d-md-none';
|
||||
|
||||
const img = document.createElement('img');
|
||||
img.src = src;
|
||||
img.className = 'position-absolute top-0 start-0 w-100 h-100 object-fit-cover rounded-5';
|
||||
img.alt = 'Image';
|
||||
|
||||
if (index === 1) {
|
||||
img.style.objectPosition = 'center top';
|
||||
}
|
||||
|
||||
slideDiv.appendChild(ratioDiv);
|
||||
slideDiv.appendChild(mobileRatioDiv);
|
||||
slideDiv.appendChild(img);
|
||||
imagesContainer.appendChild(slideDiv);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<section class="bg-body-tertiary">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<!-- Titles master slider -->
|
||||
<div class="col-md-6 col-lg-5 d-flex flex-column">
|
||||
<div class="py-4 mt-auto">
|
||||
<div class="swiper pb-1 pt-3 pt-sm-4 py-md-4 py-lg-3"
|
||||
data-swiper='{
|
||||
"spaceBetween": 24,
|
||||
"loop": true,
|
||||
"speed": 400,
|
||||
"controlSlider": "#heroImages",
|
||||
"pagination": {
|
||||
"el": "#sliderBullets",
|
||||
"clickable": true
|
||||
},
|
||||
"autoplay": {
|
||||
"delay": 5500,
|
||||
"disableOnInteraction": false
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper align-items-center">
|
||||
|
||||
<!-- Item -->
|
||||
<div class="swiper-slide text-center text-md-start">
|
||||
<p class="fs-xl mb-2 mb-lg-3 mb-xl-4">The new warm collection</p>
|
||||
<h2 class="display-4 text-uppercase mb-4 mb-xl-5">New fall <br
|
||||
class="d-none d-md-inline">season 2024</h2>
|
||||
<a class="btn btn-lg btn-outline-dark" href="{{ route('second', ['shop', 'catalog-fashion']) }}">
|
||||
Shop now
|
||||
<i class="ci-arrow-up-right fs-lg ms-2 me-n1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Item -->
|
||||
<div class="swiper-slide text-center text-md-start">
|
||||
<p class="fs-xl mb-2 mb-lg-3 mb-xl-4">Ready for the party?</p>
|
||||
<h2 class="display-4 text-uppercase mb-4 mb-xl-5">Choose outfits for parties</h2>
|
||||
<a class="btn btn-lg btn-outline-dark" href="{{ route('second', ['shop', 'catalog-fashion']) }}">
|
||||
Shop now
|
||||
<i class="ci-arrow-up-right fs-lg ms-2 me-n1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Item -->
|
||||
<div class="swiper-slide text-center text-md-start">
|
||||
<p class="fs-xl mb-2 mb-lg-3 mb-xl-4">Shades of gray for your look</p>
|
||||
<h2 class="display-4 text-uppercase mb-4 mb-xl-5">-50% on gray Collection</h2>
|
||||
<a class="btn btn-lg btn-outline-dark" href="{{ route('second', ['shop', 'catalog-fashion']) }}">
|
||||
Shop now
|
||||
<i class="ci-arrow-up-right fs-lg ms-2 me-n1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Slider bullets (pagination) -->
|
||||
<div
|
||||
class="d-flex justify-content-center justify-content-md-start pb-4 pb-xl-5 mt-n1 mt-md-auto mb-md-3 mb-lg-4">
|
||||
<div class="swiper-pagination position-static w-auto pb-1" id="sliderBullets"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Linked images (controlled slider) -->
|
||||
<div class="col-md-6 col-lg-7 align-self-end">
|
||||
<div class="position-relative ms-md-n4">
|
||||
<div class="ratio" style="--cz-aspect-ratio: calc(662 / 770 * 100%)"></div>
|
||||
<div class="swiper position-absolute top-0 start-0 w-100 h-100 user-select-none"
|
||||
id="heroImages"
|
||||
data-swiper='{
|
||||
"allowTouchMove": false,
|
||||
"loop": true,
|
||||
"effect": "fade",
|
||||
"fadeEffect": {
|
||||
"crossFade": true
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide">
|
||||
<img src="/img/home/fashion/v1/hero-slider/01.png" class="rtl-flip"
|
||||
alt="Image">
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<img src="/img/home/fashion/v1/hero-slider/02.png" class="rtl-flip"
|
||||
alt="Image">
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<img src="/img/home/fashion/v1/hero-slider/03.png" class="rtl-flip"
|
||||
alt="Image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -76,7 +76,7 @@
|
|||
<span class="text-truncate">{{ $product->name }}</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="h6 mb-0">{{ number_format($product->price, 0, ',', '.') }}</div>
|
||||
<div class="h6 mb-0">Rp {{ number_format($product->display_price, 0, ',', '.') }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
|
|
|||
|
|
@ -1,35 +1,204 @@
|
|||
<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">{{ __('weeks_highlights.this_weeks_highlights') }}</h2>
|
||||
<style>
|
||||
.shimmer-wrapper-highlight {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<!-- 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="#!">{{ __('weeks_highlights.best_sellers') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#!">{{ __('weeks_highlights.new_arrivals') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#!">{{ __('weeks_highlights.sale_items') }}</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#!">{{ __('weeks_highlights.top_rated') }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
.shimmer-wrapper-highlight .shimmer {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
<!-- Products grid -->
|
||||
.shimmer-wrapper-highlight .shimmer::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg,
|
||||
rgba(255, 255, 255, 0) 0%,
|
||||
rgba(255, 255, 255, 0.3) 50%,
|
||||
rgba(255, 255, 255, 0) 100%);
|
||||
animation: shimmer-wrapper-highlight-shimmer 1.5s infinite;
|
||||
}
|
||||
|
||||
@keyframes shimmer-wrapper-highlight-shimmer {
|
||||
0% {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translateX(100%);
|
||||
}
|
||||
}
|
||||
|
||||
.shimmer-wrapper-highlight .shimmer-line {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.shimmer-wrapper-highlight .shimmer-content {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
<section class="container pb-5 mb-2 mb-sm-3 mb-lg-4 mb-xl-5" id="product-highlights-section">
|
||||
<h2 class="text-center pb-2 pb-sm-3">{{ __('weeks_highlights.this_weeks_highlights') }}</h2>
|
||||
|
||||
<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" id="product-highlights-tabs">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" href="#" data-type="best_sellers"
|
||||
data-url="{{ route('product.ajax.highlights') }}">
|
||||
{{ __('weeks_highlights.best_sellers') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-type="new_arrivals"
|
||||
data-url="{{ route('product.ajax.highlights') }}">
|
||||
{{ __('weeks_highlights.new_arrivals') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-type="sale_items"
|
||||
data-url="{{ route('product.ajax.highlights') }}">
|
||||
{{ __('weeks_highlights.sale_items') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#" data-type="top_rated"
|
||||
data-url="{{ route('product.ajax.highlights') }}">
|
||||
{{ __('weeks_highlights.top_rated') }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="position-relative">
|
||||
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-4 gy-4 gy-md-5 pb-xxl-3" id="product-highlights-container">
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="text-center py-5 d-none" id="product-highlights-loading">
|
||||
<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">
|
||||
<x-home.product-card :product="$product" />
|
||||
</div>
|
||||
@endforeach
|
||||
|
||||
@for ($i = 1; $i <= 8; $i++)
|
||||
<div class="col-6 col-md-4 mb-2 mb-sm-3 mb-md-0">
|
||||
<div class="shimmer-wrapper-highlight">
|
||||
<div class="shimmer">
|
||||
<div class="shimmer-content rounded">
|
||||
<div class="shimmer-line shimmer-image rounded mb-3"
|
||||
style="height: 0; padding-bottom: 100%; position: relative;">
|
||||
<div
|
||||
style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.1); border-radius: 4px;">
|
||||
</div>
|
||||
</div>
|
||||
<div class="shimmer-line shimmer-title rounded mb-2"
|
||||
style="height: 20px; width: 80%;"></div>
|
||||
<div class="shimmer-line shimmer-price rounded" style="height: 16px; width: 60%;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endfor
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
/*!
|
||||
* Product Highlights AJAX functionality
|
||||
* Handles tab switching and AJAX loading for product highlights section
|
||||
*/
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const tabsContainer = document.getElementById('product-highlights-tabs');
|
||||
const productsContainer = document.getElementById('product-highlights-container');
|
||||
const loadingSpinner = document.getElementById('product-highlights-loading');
|
||||
|
||||
if (!tabsContainer || !productsContainer || !loadingSpinner) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load first tab content on page load
|
||||
const firstTab = tabsContainer.querySelector('.nav-link.active');
|
||||
if (firstTab) {
|
||||
const type = firstTab.dataset.type;
|
||||
const url = firstTab.dataset.url;
|
||||
if (type && url) {
|
||||
loadProductHighlights(type, url);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle tab clicks
|
||||
tabsContainer.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const tab = e.target.closest('.nav-link');
|
||||
if (!tab) return;
|
||||
|
||||
// Get the type and URL from data attributes
|
||||
const type = tab.dataset.type;
|
||||
const url = tab.dataset.url;
|
||||
|
||||
if (!type || !url) return;
|
||||
|
||||
// Update active tab
|
||||
tabsContainer.querySelectorAll('.nav-link').forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
|
||||
// Load products via AJAX
|
||||
loadProductHighlights(type, url);
|
||||
});
|
||||
|
||||
function loadProductHighlights(type, url) {
|
||||
// Show loading spinner
|
||||
productsContainer.style.display = 'none';
|
||||
loadingSpinner.classList.remove('d-none');
|
||||
|
||||
// Build URL with parameters
|
||||
const requestUrl = `${url}?type=${type}`;
|
||||
|
||||
// Make AJAX request
|
||||
fetch(requestUrl)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
// Update products container with new HTML
|
||||
productsContainer.innerHTML = data.products;
|
||||
} else {
|
||||
// Handle error
|
||||
productsContainer.innerHTML =
|
||||
'<div class="col-12 text-center py-4">Error loading products</div>';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading product highlights:', error);
|
||||
productsContainer.innerHTML =
|
||||
'<div class="col-12 text-center py-4">Error loading products</div>';
|
||||
})
|
||||
.finally(() => {
|
||||
// Hide loading spinner and show products
|
||||
loadingSpinner.classList.add('d-none');
|
||||
productsContainer.style.display = 'flex';
|
||||
|
||||
// Re-initialize any components that might be needed for the new products
|
||||
if (window.bootstrap && window.bootstrap.Tooltip) {
|
||||
const tooltipTriggerList = [].slice.call(productsContainer.querySelectorAll(
|
||||
'[data-bs-toggle="tooltip"]'));
|
||||
tooltipTriggerList.map(function(tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -8,267 +8,11 @@
|
|||
<main class="content-wrapper">
|
||||
|
||||
<!-- Hero slider -->
|
||||
<section class="bg-body-tertiary">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
||||
<!-- Titles master slider -->
|
||||
<div class="col-md-6 col-lg-5 d-flex flex-column">
|
||||
<div class="py-4 mt-auto">
|
||||
<div class="swiper pb-1 pt-3 pt-sm-4 py-md-4 py-lg-3"
|
||||
data-swiper='{
|
||||
"spaceBetween": 24,
|
||||
"loop": true,
|
||||
"speed": 400,
|
||||
"controlSlider": "#heroImages",
|
||||
"pagination": {
|
||||
"el": "#sliderBullets",
|
||||
"clickable": true
|
||||
},
|
||||
"autoplay": {
|
||||
"delay": 5500,
|
||||
"disableOnInteraction": false
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper align-items-center">
|
||||
|
||||
<!-- Item -->
|
||||
<div class="swiper-slide text-center text-md-start">
|
||||
<p class="fs-xl mb-2 mb-lg-3 mb-xl-4">The new warm collection</p>
|
||||
<h2 class="display-4 text-uppercase mb-4 mb-xl-5">New fall <br
|
||||
class="d-none d-md-inline">season 2024</h2>
|
||||
<a class="btn btn-lg btn-outline-dark" href="{{ route('second', ['shop', 'catalog-fashion']) }}">
|
||||
Shop now
|
||||
<i class="ci-arrow-up-right fs-lg ms-2 me-n1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Item -->
|
||||
<div class="swiper-slide text-center text-md-start">
|
||||
<p class="fs-xl mb-2 mb-lg-3 mb-xl-4">Ready for the party?</p>
|
||||
<h2 class="display-4 text-uppercase mb-4 mb-xl-5">Choose outfits for parties</h2>
|
||||
<a class="btn btn-lg btn-outline-dark" href="{{ route('second', ['shop', 'catalog-fashion']) }}">
|
||||
Shop now
|
||||
<i class="ci-arrow-up-right fs-lg ms-2 me-n1"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Item -->
|
||||
<div class="swiper-slide text-center text-md-start">
|
||||
<p class="fs-xl mb-2 mb-lg-3 mb-xl-4">Shades of gray for your look</p>
|
||||
<h2 class="display-4 text-uppercase mb-4 mb-xl-5">-50% on gray Collection</h2>
|
||||
<a class="btn btn-lg btn-outline-dark" href="{{ route('second', ['shop', 'catalog-fashion']) }}">
|
||||
Shop now
|
||||
<i class="ci-arrow-up-right fs-lg ms-2 me-n1"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Slider bullets (pagination) -->
|
||||
<div
|
||||
class="d-flex justify-content-center justify-content-md-start pb-4 pb-xl-5 mt-n1 mt-md-auto mb-md-3 mb-lg-4">
|
||||
<div class="swiper-pagination position-static w-auto pb-1" id="sliderBullets"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Linked images (controlled slider) -->
|
||||
<div class="col-md-6 col-lg-7 align-self-end">
|
||||
<div class="position-relative ms-md-n4">
|
||||
<div class="ratio" style="--cz-aspect-ratio: calc(662 / 770 * 100%)"></div>
|
||||
<div class="swiper position-absolute top-0 start-0 w-100 h-100 user-select-none"
|
||||
id="heroImages"
|
||||
data-swiper='{
|
||||
"allowTouchMove": false,
|
||||
"loop": true,
|
||||
"effect": "fade",
|
||||
"fadeEffect": {
|
||||
"crossFade": true
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide">
|
||||
<img src="/img/home/fashion/v1/hero-slider/01.png" class="rtl-flip"
|
||||
alt="Image">
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<img src="/img/home/fashion/v1/hero-slider/02.png" class="rtl-flip"
|
||||
alt="Image">
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<img src="/img/home/fashion/v1/hero-slider/03.png" class="rtl-flip"
|
||||
alt="Image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<x-home.home-slider />
|
||||
|
||||
|
||||
<!-- Popular products carousel -->
|
||||
<section class="container py-5 my-2 my-sm-3 my-lg-4 my-xl-5">
|
||||
<div class="row align-items-lg-center py-xxl-3">
|
||||
|
||||
<!-- Products -->
|
||||
<div class="col-md-6 col-xl-5 offset-xl-1 order-md-2 mb-4 mb-md-0">
|
||||
<div class="ps-md-3 ps-lg-4 ps-xl-0">
|
||||
<div class="d-flex align-items-center justify-content-between pb-4 mb-md-1 mb-lg-2 mb-xl-3">
|
||||
<h2 class="me-3 mb-0">Popular products</h2>
|
||||
|
||||
<!-- 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="popularPrev" 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"
|
||||
id="popularNext" aria-label="Next">
|
||||
<i class="ci-chevron-right fs-lg animate-target"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Products master slider -->
|
||||
<div class="swiper"
|
||||
data-swiper='{
|
||||
"spaceBetween": 24,
|
||||
"loop": true,
|
||||
"speed": 400,
|
||||
"controlSlider": "#sliderImages",
|
||||
"navigation": {
|
||||
"prevEl": "#popularPrev",
|
||||
"nextEl": "#popularNext"
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper">
|
||||
|
||||
<!-- Products list slide -->
|
||||
<div class="swiper-slide">
|
||||
<div class="d-flex flex-column gap-3 gap-lg-4">
|
||||
<div
|
||||
class="d-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline">
|
||||
<img src="/img/shop/fashion/thumbs/01.png" width="110" alt="Thumbnail">
|
||||
<div class="nav flex-column gap-2 min-w-0 p-3">
|
||||
<a class="nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0"
|
||||
href="{{ route('second', ['shop', 'product-fashion']) }}">
|
||||
<span class="animate-target text-truncate">Short jacket in long-pile
|
||||
faux fur</span>
|
||||
</a>
|
||||
<div class="h6 mb-0">$218.00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline">
|
||||
<img src="/img/shop/fashion/thumbs/02.png" width="110" alt="Thumbnail">
|
||||
<div class="nav flex-column gap-2 min-w-0 p-3">
|
||||
<a class="nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0"
|
||||
href="{{ route('second', ['shop', 'product-fashion']) }}">
|
||||
<span class="animate-target text-truncate">Women's walking shoes tennis
|
||||
sneakers</span>
|
||||
</a>
|
||||
<div class="h6 mb-0">$54.99</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline">
|
||||
<img src="/img/shop/fashion/thumbs/03.png" width="110" alt="Thumbnail">
|
||||
<div class="nav flex-column gap-2 min-w-0 p-3">
|
||||
<a class="nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0"
|
||||
href="{{ route('second', ['shop', 'product-fashion']) }}">
|
||||
<span class="animate-target text-truncate">Classic aviator sunglasses
|
||||
for women</span>
|
||||
</a>
|
||||
<div class="h6 mb-0">$76.00</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Products list slide -->
|
||||
<div class="swiper-slide">
|
||||
<div class="d-flex flex-column gap-3 gap-lg-4">
|
||||
<div
|
||||
class="d-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline">
|
||||
<img src="/img/shop/fashion/thumbs/04.png" width="110" alt="Thumbnail">
|
||||
<div class="nav flex-column gap-2 min-w-0 p-3">
|
||||
<a class="nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0"
|
||||
href="{{ route('second', ['shop', 'product-fashion']) }}">
|
||||
<span class="animate-target text-truncate">Vintage oversized wool
|
||||
blazer jacket</span>
|
||||
</a>
|
||||
<div class="h6 mb-0">$174.00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline">
|
||||
<img src="/img/shop/fashion/thumbs/05.png" width="110" alt="Thumbnail">
|
||||
<div class="nav flex-column gap-2 min-w-0 p-3">
|
||||
<a class="nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0"
|
||||
href="{{ route('second', ['shop', 'product-fashion']) }}">
|
||||
<span class="animate-target text-truncate">Classic pilot style
|
||||
polarized sunglasses</span>
|
||||
</a>
|
||||
<div class="h6 mb-0">$93.00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="d-flex align-items-center position-relative bg-body-tertiary rounded overflow-hidden animate-underline">
|
||||
<img src="/img/shop/fashion/thumbs/06.png" width="110" alt="Thumbnail">
|
||||
<div class="nav flex-column gap-2 min-w-0 p-3">
|
||||
<a class="nav-link text-dark-emphasis stretched-link w-100 min-w-0 p-0"
|
||||
href="{{ route('second', ['shop', 'product-fashion']) }}">
|
||||
<span class="animate-target text-truncate">Cotton dress straight-leg
|
||||
pants</span>
|
||||
</a>
|
||||
<div class="h6 mb-0">$65.00</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Complete look images (controlled slider) -->
|
||||
<div class="col-md-6 order-md-1">
|
||||
<div class="swiper user-select-none" id="sliderImages"
|
||||
data-swiper='{
|
||||
"allowTouchMove": false,
|
||||
"loop": true,
|
||||
"effect": "fade",
|
||||
"fadeEffect": {
|
||||
"crossFade": true
|
||||
}
|
||||
}'>
|
||||
<div class="swiper-wrapper">
|
||||
<div class="swiper-slide">
|
||||
<div class="ratio d-none d-md-block" style="--cz-aspect-ratio: calc(720 / 636 * 100%)">
|
||||
</div>
|
||||
<div class="ratio ratio-4x3 d-md-none"></div>
|
||||
<img src="/img/home/fashion/v1/popular/01.jpg"
|
||||
class="position-absolute top-0 start-0 w-100 h-100 object-fit-cover rounded-5"
|
||||
alt="Image">
|
||||
</div>
|
||||
<div class="swiper-slide">
|
||||
<div class="ratio d-none d-md-block" style="--cz-aspect-ratio: calc(720 / 636 * 100%)">
|
||||
</div>
|
||||
<div class="ratio ratio-4x3 d-md-none"></div>
|
||||
<img src="/img/home/fashion/v1/popular/02.jpg"
|
||||
class="position-absolute top-0 start-0 w-100 h-100 object-fit-cover rounded-5"
|
||||
style="object-position: center top" alt="Image">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<x-home.home-popular-products />
|
||||
|
||||
|
||||
<!-- Featured products -->
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use App\Http\Controllers\LocationController;
|
|||
use App\Http\Controllers\LocaleController;
|
||||
use App\Http\Controllers\ProductController;
|
||||
use App\Http\Controllers\SearchController;
|
||||
use App\Http\Controllers\ComponentController;
|
||||
|
||||
Route::group(['prefix' => '/dummy'], function () {
|
||||
Route::get('', [RoutingController::class, 'index'])->name('root');
|
||||
|
|
@ -26,9 +27,14 @@ Route::get('/', [HomeController::class, 'index'])->name('home');
|
|||
|
||||
Route::get('/products',[ProductController::class, 'index'])->name('product.index');
|
||||
Route::get('/products/ajax',[ProductController::class, 'ajax'])->name('product.ajax');
|
||||
Route::get('/products/ajax/highlights',[ProductController::class, 'highlights'])->name('product.ajax.highlights');
|
||||
Route::get('/products/ajax/brands',[ProductController::class, 'brands'])->name('product.ajax.brands');
|
||||
Route::get('/products/ajax/categories',[ProductController::class, 'categories'])->name('product.ajax.categories');
|
||||
Route::get('/products/ajax/genders',[ProductController::class, 'genders'])->name('product.ajax.genders');
|
||||
Route::get('/product/{slug}',[ProductController::class, 'detail'])->name('product.detail');
|
||||
|
||||
// Search routes
|
||||
Route::get('/search', [SearchController::class, 'search'])->name('search.ajax');
|
||||
Route::get('/search', [SearchController::class, 'search'])->name('search.ajax');
|
||||
|
||||
// Component loading routes
|
||||
Route::get('/components/{component}', [ComponentController::class, 'load'])->name('component.load');
|
||||
Loading…
Reference in New Issue