getList([]);
// Render gender links HTML
$genderHtml = '';
$currentGenderId = $request->input('current_gender');
foreach ($genders as $gender) {
$isActive = $currentGenderId == $gender->id;
$genderHtml .= '
';
$genderHtml .= 'id.'">';
$genderHtml .= $gender->name;
$genderHtml .= '';
}
return response()->json([
'success' => true,
'genders' => $genderHtml,
]);
}
public function categories(Request $request)
{
$categoryRepository = new CategoryRepository;
$categories = $categoryRepository->getList([]);
// Render category links HTML
$categoryHtml = '';
$currentCategoryId = $request->input('current_category');
foreach ($categories as $category) {
$isActive = $currentCategoryId == $category->id;
$categoryHtml .= '';
$categoryHtml .= 'id.'">';
$categoryHtml .= $category->name;
$categoryHtml .= '';
}
return response()->json([
'success' => true,
'categories' => $categoryHtml,
]);
}
public function ajax(Request $request)
{
$limit = 20;
$page = $request->page ?? 1;
$search = $request->search;
$filter = $request->filter ?? [];
$sortBy = $request->sort_by ?? 'relevance';
$price_range_start = $request->price_range_start ?? null;
$price_range_end = $request->price_range_end ?? null;
$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;
$products = $productRepository->getList([
'limit' => $page * $limit,
'sort' => $sortBy,
'category_id' => $filter['category'] ?? null,
'gender_id' => $filter['gender'] ?? null,
'brand_id' => $filter['brand'] ?? null,
'search' => $search,
'location_id' => $location_id,
'is_consignment' => $is_consignment,
'price_range_start' => $price_range_start,
'price_range_end' => $price_range_end,
]);
// Check if there are more products
$hasMore = count($products) >= $limit;
// Render product cards HTML
$productHtml = '';
if (count($products) == 0) {
$productHtml = '';
$productHtml .= 'Pencarian tidak ditemukan';
$productHtml .= '
';
} else {
foreach ($products as $product) {
$productHtml .= '';
$productHtml .= view('components.home.product-card', ['product' => $product])->render();
$productHtml .= '
';
}
}
// filter
$filter = $request->filter ?? [];
if (isset($filter['category']) && $filter['category']) {
$category = StoreCategory::find($filter['category']);
if ($category) {
$filter['category'] = $category->name;
} else {
unset($filter);
}
}
if (isset($filter['gender']) && $filter['gender']) {
$gender = Gender::find($filter['gender']);
if ($gender) {
$filter['gender'] = $gender->name;
} else {
unset($filter);
}
}
if (isset($filter['brand']) && $filter['brand']) {
$brand = \App\Models\Brand::find($filter['brand']);
if ($brand) {
$filter['brand'] = $brand->name;
} else {
unset($filter);
}
}
$filters = $filter;
return response()->json([
'success' => true,
'filters' => $filters,
'products' => $productHtml,
'count' => count($products),
'has_more' => $hasMore,
'current_page' => $page,
]);
}
public function index(Request $request)
{
$productRepository = new ProductRepository;
$products = [];
$filters = [];
$min_max_price = $productRepository->getMinMaxPrice();
return view('shop.catalog-fashion', [
'products' => $products,
'min_max_price' => $min_max_price,
]);
}
public function brands(Request $request)
{
$brandRepository = new \App\Repositories\Catalog\BrandRepository;
$brands = $brandRepository->getList([]);
// Render brand links HTML
$brandHtml = '';
$currentBrandId = $request->input('current_brand');
foreach ($brands as $brand) {
$isActive = $currentBrandId == $brand->id;
$brandHtml .= '';
$brandHtml .= 'id.'">';
$brandHtml .= $brand->name;
$brandHtml .= '';
}
return response()->json([
'success' => true,
'brands' => $brandHtml,
]);
}
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 .= '';
$brandHtml .= '
';
$brandHtml .= '';
}
}
return response()->json([
'success' => true,
'brands' => $brandHtml,
]);
}
public function announcements(Request $request)
{
// Static announcements for now - can be moved to database later
$announcements = [
// [
// 'icon' => '🎉',
// 'message' => 'Free Shipping on orders over $250',
// 'detail' => "Don't miss a discount!",
// ],
// [
// 'icon' => '💰',
// 'message' => 'Money back guarantee',
// 'detail' => 'We return money within 30 days',
// ],
// [
// 'icon' => '💪',
// 'message' => 'Friendly 24/7 customer support',
// 'detail' => "We've got you covered!",
// ],
];
// Render announcement slides HTML
$announcementHtml = '';
foreach ($announcements as $announcement) {
$announcementHtml .= '';
$announcementHtml .= $announcement['icon'].' '.$announcement['message'].' '.$announcement['detail'].'';
$announcementHtml .= '
';
}
return response()->json([
'success' => true,
'announcements' => $announcementHtml,
]);
}
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;
}
$params['limit'] = 10;
$products = $productRepository->getList($params);
// Render product cards HTML
$productHtml = '';
if (count($products) == 0) {
$productHtml = '';
$productHtml .= 'No products found';
$productHtml .= '
';
} else {
foreach ($products as $product) {
$productHtml .= '';
$productHtml .= view('components.home.product-card', ['product' => $product])->render();
$productHtml .= '
';
}
}
return response()->json([
'success' => true,
'products' => $productHtml,
'count' => count($products),
'type' => $type,
]);
}
public function populers(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;
}
$products = $productRepository->getList($params);
// Render product cards HTML
$productHtml = '';
if (count($products) == 0) {
$productHtml = '';
$productHtml .= 'No products found';
$productHtml .= '
';
} else {
foreach ($products as $product) {
$productHtml .= '';
$productHtml .= view('components.home.product-card', ['product' => $product])->render();
$productHtml .= '
';
}
}
return response()->json([
'success' => true,
'products' => $productHtml,
'count' => count($products),
'type' => $type,
]);
}
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,
]);
}
/**
* Track product visit analytics
*/
private function trackProductVisit(int $productId, Request $request): void
{
try {
$analyticsRepository = new AnalyticsProductVisitRepository();
$visitData = [
'item_id' => $productId,
'user_id' => auth()->id(),
'session_id' => session()->getId(),
'ip_address' => $request->ip(),
'user_agent' => $request->userAgent(),
'started_at' => now(),
'duration_seconds' => 0, // Will be updated when user leaves
'device_type' => $this->getDeviceType($request->userAgent()),
];
$analyticsRepository->create($visitData);
} catch (\Exception $e) {
// Log error but don't break the application
\Log::error('Failed to track product visit: ' . $e->getMessage());
}
}
/**
* Detect device type from user agent
*/
private function getDeviceType(string $userAgent): string
{
$userAgent = strtolower($userAgent);
if (strpos($userAgent, 'mobile') !== false) {
return 'Mobile';
}
if (strpos($userAgent, 'tablet') !== false) {
return 'Tablet';
}
return 'Desktop';
}
public function detailFashion($slug, Request $request, ProductRepository $productRepository)
{
$product = $productRepository->show($slug);
// Track product visit analytics
$this->trackProductVisit($product->id, $request);
$complete_look_products_data = $productRepository->getList([
'category_id' => $product->category1_id,
'limit' => 4,
]);
$complete_look_products = collect($complete_look_products_data->items())->chunk(2);
$variants = $product->publishedItemVariants ?? [];
if (count($variants) == 0) {
$variants = collect([$product]);
}
return view('shop.product-fashion', [
'product' => $product,
'variants' => $variants,
'complete_look_products' => $complete_look_products,
]);
}
}