getList([]); // Render gender links HTML $genderHtml = ''; $currentGenderId = $request->input('current_gender'); foreach ($genders as $gender) { $isActive = $currentGenderId == $gender->id; $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 .= ''; } 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 .= ''; } 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 .= ''.$brand->name.''; $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, ]); } }