Files
the-pet-loft/apps/storefront/src/components/wishlist/WishlistPageView.tsx
ianshaloom 23efcab80c
Some checks failed
CI / Lint, Typecheck & Test (push) Failing after 2m11s
fix: resolve CI and workspace lint errors (admin + storefront)
- Allow require() in next.config.js (eslint-disable) for both apps
- Replace all catch (e: any) with catch (e: unknown) and proper error handling
- Remove no-explicit-any: add types (PreviewProduct, ProductImage, Id<addresses>,
  ProductDetailReview, error payloads) across admin and storefront
- Admin: use next/image in ImageUploadSection and ProductImageCarousel; remove
  unused layout fonts and sidebar imports; fix products page useMemo deps
- Storefront: use Link for /sign-in in header actions; fix useAddressMutations
  and product detail types; remove unused imports/vars and fix useMemo deps

Made-with: Cursor
2026-03-08 00:45:57 +03:00

99 lines
2.9 KiB
TypeScript

"use client";
import { useConvexAuth } from "convex/react";
import { useState, useCallback } from "react";
import { toast } from "@heroui/react";
import { useWishlist } from "@/lib/wishlist/useWishlist";
import { useWishlistMutations } from "@/lib/wishlist/useWishlistMutations";
import type { WishlistItem } from "@/lib/wishlist/types";
import { WishlistItemGrid } from "./WishlistItemGrid";
import { RemoveFromWishlistDialog } from "./RemoveFromWishlistDialog";
import { WishlistSkeleton } from "./state/WishlistSkeleton";
import { WishlistEmptyState } from "./state/WishlistEmptyState";
import { WishlistSignInPrompt } from "./state/WishlistSignInPrompt";
export function WishlistPageView() {
const { isAuthenticated, isLoading: authLoading } = useConvexAuth();
const { items, isLoading, isEmpty } = useWishlist();
const { removeItem, isRemoving, addToCart } = useWishlistMutations();
const [removeTarget, setRemoveTarget] = useState<WishlistItem | null>(null);
const [removingId, setRemovingId] = useState<string | null>(null);
const [addingToCartId, setAddingToCartId] = useState<string | null>(null);
const handleRemove = useCallback(
(id: string) => {
const target = items.find((i) => i._id === id);
setRemoveTarget(target ?? null);
},
[items],
);
const handleConfirmRemove = useCallback(async () => {
if (!removeTarget) return;
const name = removeTarget.product?.name ?? "Item";
setRemovingId(removeTarget._id);
try {
await removeItem(removeTarget._id);
toast.success(`${name} removed from wishlist`);
} catch {
toast.danger("Failed to remove item");
} finally {
setRemovingId(null);
setRemoveTarget(null);
}
}, [removeTarget, removeItem]);
const handleAddToCart = useCallback(
async (variantId: string) => {
const item = items.find(
(i) =>
i.variant?._id === variantId ||
i.product?.variants[0]?._id === variantId,
);
setAddingToCartId(item?._id ?? null);
try {
await addToCart(variantId, 1);
toast.success("Added to cart");
} catch {
toast.danger("This item is currently out of stock");
} finally {
setAddingToCartId(null);
}
},
[items, addToCart],
);
if (!authLoading && !isAuthenticated) {
return <WishlistSignInPrompt />;
}
if (authLoading || isLoading) {
return <WishlistSkeleton />;
}
if (isEmpty) {
return <WishlistEmptyState />;
}
return (
<>
<WishlistItemGrid
items={items}
onRemove={handleRemove}
onAddToCart={handleAddToCart}
removingId={removingId}
addingToCartId={addingToCartId}
/>
<RemoveFromWishlistDialog
isOpen={!!removeTarget}
onClose={() => setRemoveTarget(null)}
onConfirm={handleConfirmRemove}
isRemoving={isRemoving}
productName={removeTarget?.product?.name ?? "this item"}
/>
</>
);
}