$this->products($products)]); } /** * The same list for a guest, from their cookie. Logged-in users are sent * to the account version. */ public function guest(string $locale, ProductService $products): View|RedirectResponse { if (auth()->check()) { return redirect()->route('account.wishlist'); } return view('wishlist.guest', ['products' => $this->products($products)]); } /** * Adds or removes a product, for guests and logged-in shoppers alike. The * heart button's Stimulus controller asks for JSON; without JS the form * posts normally and comes back to the same page. */ public function toggle(string $locale, Request $request, int $productId): JsonResponse|RedirectResponse { abort_unless(Product::whereKey($productId)->exists(), 404); $active = $this->wishlist->toggle($productId); if ($request->expectsJson()) { return response()->json(['active' => $active]); } return back(); } /** * Product cards for the current wishlist, newest first. Products no longer * in the search index (deleted, unpublished) are simply skipped. */ private function products(ProductService $products): Collection { return collect($this->wishlist->ids()) ->map(fn (int $id) => $products->getById($id)) ->filter() ->map(fn (array $product) => ['id' => $product['id'], ...ProductCard::fromIndexed($product)]) ->values(); } }