fix step otp phone, email, tambah nama di produk populer home, brands home, hapus newsletter di cart (hide)
This commit is contained in:
parent
d58c8d7ca2
commit
be7aabbcb3
|
|
@ -62,6 +62,7 @@ class LoginWaController extends Controller
|
|||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => __('otp.sent'),
|
||||
|
||||
'redirect' => route('login-phone.otp.view', ['identity' => $identity]),
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
|
|
@ -78,6 +79,7 @@ class LoginWaController extends Controller
|
|||
{
|
||||
return view('account.otp', [
|
||||
'identity' => $identity,
|
||||
'type' => 'phone',
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -205,6 +205,31 @@ class ProductController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function brandsWithImages(Request $request)
|
||||
{
|
||||
$brandRepository = new \App\Repositories\Catalog\BrandRepository;
|
||||
$brands = $brandRepository->getList([]);
|
||||
|
||||
// Render brand links HTML with images as swiper slides
|
||||
$brandHtml = '';
|
||||
$currentBrandId = $request->input('current_brand');
|
||||
|
||||
foreach ($brands as $brand) {
|
||||
$isActive = $currentBrandId == $brand->id;
|
||||
// Only show brands that have images
|
||||
if ($brand->image_url) {
|
||||
$brandHtml .= '<a class="swiper-slide text-body" href="#!" aria-label="'.$brand->name.'" role="group" style="width: 170.2px; margin-right: 20px;">';
|
||||
$brandHtml .= '<img src="'.$brand->image_url.'" alt="'.$brand->name.'" class="me-2" width="100" height="100">';
|
||||
$brandHtml .= '</a>';
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'brands' => $brandHtml,
|
||||
]);
|
||||
}
|
||||
|
||||
public function announcements(Request $request)
|
||||
{
|
||||
// Static announcements for now - can be moved to database later
|
||||
|
|
@ -388,6 +413,70 @@ class ProductController extends Controller
|
|||
]);
|
||||
}
|
||||
|
||||
public function populersJson(Request $request)
|
||||
{
|
||||
$type = $request->input('type', 'new');
|
||||
$limit = 6;
|
||||
|
||||
$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 'new':
|
||||
$params['sort'] = 'new';
|
||||
break;
|
||||
case 'best_sellers':
|
||||
$params['sort'] = 'best_sellers';
|
||||
break;
|
||||
case 'special-offer':
|
||||
$params['event'] = 'special-offer';
|
||||
break;
|
||||
case 'top_rated':
|
||||
$params['sort'] = 'random';
|
||||
break;
|
||||
default:
|
||||
$params['sort'] = 'new';
|
||||
break;
|
||||
}
|
||||
|
||||
$params['limit'] = 10;
|
||||
|
||||
$products = $productRepository->getList($params);
|
||||
|
||||
|
||||
$p = $products->map(function($row){
|
||||
$row->image_url = $row->image_url;
|
||||
return $row;
|
||||
});
|
||||
|
||||
return response()->json([
|
||||
'data' =>$p,
|
||||
]);
|
||||
}
|
||||
|
||||
public function detail($slug, Request $request, ProductRepository $productRepository)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
|
||||
<div class="position-relative mb-4">
|
||||
<label for="otp" class="form-label">{{ __('otp.enter_code') }}</label>
|
||||
<input class="form-control form-control-lg" type="text" placeholder="000000" maxlength="6"
|
||||
<input class="form-control form-control-lg" type="text" placeholder="{{ __('otp.enter_code') }}" maxlength="6"
|
||||
pattern="[0-9]{6}" required="" name="otp" id="otp" autocomplete="one-time-code" />
|
||||
<div class="invalid-tooltip bg-transparent py-0">{{ __('otp.invalid_code') }}</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -660,7 +660,7 @@
|
|||
|
||||
|
||||
<!-- Subscription form + Vlog -->
|
||||
<section class="bg-body-tertiary py-5">
|
||||
{{-- <section class="bg-body-tertiary py-5">
|
||||
<div class="container pt-sm-2 pt-md-3 pt-lg-4 pt-xl-5">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-lg-5 mb-5 mb-md-0">
|
||||
|
|
@ -728,7 +728,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section> --}}
|
||||
</main>
|
||||
|
||||
<!-- Clear Cart Confirmation Modal -->
|
||||
|
|
|
|||
|
|
@ -71,8 +71,8 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
// Show loading spinner
|
||||
loadingSpinner.classList.remove('d-none');
|
||||
|
||||
// Make AJAX request for brands
|
||||
fetch('{{ route("product.ajax.brands") }}')
|
||||
// Make AJAX request for brands with images
|
||||
fetch('{{ route("product.ajax.brands-with-images") }}')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.success && data.brands) {
|
||||
|
|
|
|||
|
|
@ -113,16 +113,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
}
|
||||
|
||||
// Make AJAX request for popular products
|
||||
fetch('{{ route("product.ajax.populers") }}?type=best_sellers&limit=6')
|
||||
fetch('{{ route("product.ajax.populers-json") }}?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);
|
||||
if ( data.data) {
|
||||
// Handle JSON response directly
|
||||
const productsArray = data.data;
|
||||
|
||||
// Split products into two slides (3 products each)
|
||||
const slide1 = productsArray.slice(0, 3);
|
||||
|
|
@ -139,16 +135,16 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
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');
|
||||
// Convert product object to list item format
|
||||
const productImg = product.image_url;
|
||||
const productLink = product.name;
|
||||
const productPrice = product.unit_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.src = productImg ? productImg : '/img/shop/fashion/thumbs/0' + (index * 3 + slide.indexOf(product) + 1) + '.png';
|
||||
img.width = 110;
|
||||
img.alt = 'Thumbnail';
|
||||
|
||||
|
|
@ -157,23 +153,22 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
|
||||
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 : '#';
|
||||
link.href = product.slug ? '/product/' + product.slug : '#';
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.className = 'animate-target text-truncate';
|
||||
span.textContent = productLink ? productLink.textContent.trim() : 'Product Name';
|
||||
span.textContent = productLink ? productLink : 'Product Name';
|
||||
|
||||
const price = document.createElement('div');
|
||||
price.className = 'h6 mb-0';
|
||||
price.textContent = productPrice ? productPrice.textContent : '$0.00';
|
||||
price.textContent = productPrice ? Number(productPrice).toLocaleString('id-ID', { style: 'currency', currency: 'IDR', minimumFractionDigits: 0 }) : '$0.00';
|
||||
|
||||
const name = document.createElement('div');
|
||||
name.className = 'text-truncate mb-1';
|
||||
name.textContent = productLink ? productLink.textContent.trim() : 'Product Name';
|
||||
name.textContent = productLink ? productLink : 'Product Name';
|
||||
|
||||
link.appendChild(span);
|
||||
navDiv.appendChild(link);
|
||||
navDiv.appendChild(name);
|
||||
navDiv.appendChild(price);
|
||||
listItem.appendChild(img);
|
||||
listItem.appendChild(navDiv);
|
||||
|
|
|
|||
|
|
@ -16,20 +16,6 @@
|
|||
<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"
|
||||
|
|
|
|||
|
|
@ -39,8 +39,10 @@ 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/populers', [ProductController::class, 'populers'])->name('product.ajax.populers');
|
||||
Route::get('/products/ajax/populers-json', [ProductController::class, 'populersJson'])->name('product.ajax.populers-json');
|
||||
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/brands-with-images', [ProductController::class, 'brandsWithImages'])->name('product.ajax.brands-with-images');
|
||||
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('/products/ajax/announcements', [ProductController::class, 'announcements'])->name('product.ajax.announcements');
|
||||
|
|
|
|||
Loading…
Reference in New Issue