Skip to content

Commit

Permalink
Merge pull request #165 from Utsavladia/wishlist
Browse files Browse the repository at this point in the history
Added functionality of wishlist
  • Loading branch information
trishanu-init authored Jun 25, 2024
2 parents cab2167 + 42db888 commit 6777c4e
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 49 deletions.
53 changes: 53 additions & 0 deletions app/(routes)/wishlist/components/wishlist-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import Image from "next/image";
import { toast } from "react-hot-toast";
import { X } from "lucide-react";

import IconButton from "@/components/ui/icon-button";
import Currency from "@/components/ui/currency";
import useWishlist from "@/hooks/use-wishlist";
import { Product } from "@/types";

interface CartItemProps {
data: Product;
}

const WishlistItem: React.FC<CartItemProps> = ({ data }) => {
const wishlist = useWishlist();

const onRemove = () => {
wishlist.removeItem(data.id);
};

return (
<li className="flex py-6 border-b">
<div className="relative h-24 w-24 rounded-md overflow-hidden sm:h-48 sm:w-48">
<Image
fill
src={data.images[0].url}
alt=""
className="object-cover object-center"
/>
</div>
<div className="relative ml-4 flex flex-1 flex-col justify-between sm:ml-6">
<div className="absolute z-10 right-0 top-0">
<IconButton onClick={onRemove} icon={<X size={15} />} />
</div>
<div className="relative pr-9 sm:grid sm:grid-cols-2 sm:gap-x-6 sm:pr-0">
<div className="flex justify-between">
<p className=" text-lg font-semibold text-black">{data.name}</p>
</div>

<div className="mt-1 flex text-sm">
<p className="text-gray-500">{data.color.name}</p>
<p className="ml-4 border-l border-gray-200 pl-4 text-gray-500">
{data.size.name}
</p>
</div>
<Currency value={data.price} />
</div>
</div>
</li>
);
};

export default WishlistItem;
42 changes: 42 additions & 0 deletions app/(routes)/wishlist/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"use client";

import { useEffect, useState } from "react";

import Container from "@/components/ui/container";
import useWishlist from "@/hooks/use-wishlist";

import WishlistItem from "./components/wishlist-item";

const CartPage = () => {
const [isMounted, setIsMounted] = useState(false);
const wishlist = useWishlist();

useEffect(() => {
setIsMounted(true);
}, []);

if (!isMounted) {
return null;
}

return (
<div className="bg-white pt-10">
<Container>
<div className="px-4 py-16 sm:px-6 lg:px-8">
<h1 className="text-3xl font-bold text-black">Your Wishlist</h1>
<div className="mt-12 lg:grid lg:grid-cols-12 lg:items-start gap-x-12">
<div className="lg:col-span-7">
<ul>
{wishlist.items.map((item) => (
<WishlistItem key={item.id} data={item} />
))}
</ul>
</div>
</div>
</div>
</Container>
</div>
);
};

export default CartPage;
101 changes: 63 additions & 38 deletions components/info.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,55 @@
"use client";

import { ShoppingCart, Trash2 } from "lucide-react";
import { Heart, ShoppingCart, Trash2 } from "lucide-react";

import Currency from "@/components/ui/currency";
import Currency from "@/components/ui/currency";
import Button from "@/components/ui/button";
import { Product } from "@/types";
import useCart from "@/hooks/use-cart";
import useWishlist from "@/hooks/use-wishlist";
import Rating from "./ui/ratings";

interface InfoProps {
data: Product
};
data: Product;
}

const Info: React.FC<InfoProps> = ({ data }) => {
const cart = useCart();
const wishlist = useWishlist();

const onAddToCart = () => {
cart.addItem(data);
}
};

const isInCart = cart.items.some((item) => item.id === data.id);
const onRemoveFromCart= () => {
const isInWishlist = wishlist.items.some((item) => item.id === data.id);
const onRemoveFromCart = () => {
cart.removeItem(data.id);
};
const onShare = () => {
if (navigator.share) {
navigator.share({
title: data.name,
text: `Check out this product: ${data.name}`,
url: window.location.href
}).then(() => console.log('Shared successfully'))
.catch((error) => console.error('Error sharing:', error));
navigator
.share({
title: data.name,
text: `Check out this product: ${data.name}`,
url: window.location.href,
})
.then(() => console.log("Shared successfully"))
.catch((error) => console.error("Error sharing:", error));
} else {
console.log("Web Share API is not supported in this browser.");
}
};

const toggleWishlist = () => {
if (isInWishlist) {
wishlist.removeItem(data.id);
} else {
console.log('Web Share API is not supported in this browser.');
wishlist.addItem(data);
}
};

return (
return (
<div>
<h1 className="text-3xl font-bold text-gray-900">{data.name}</h1>
<div className="mt-3 flex items-end justify-between">
Expand All @@ -48,40 +61,52 @@ const Info: React.FC<InfoProps> = ({ data }) => {
<div className="flex flex-col gap-y-6">
<div className="flex items-center gap-x-4">
<h3 className="font-semibold text-black">Size:</h3>
<div>
{data?.size?.value}
</div>
<div>{data?.size?.value}</div>
</div>
<div className="flex items-center gap-x-4">
<h3 className="font-semibold text-black">Color:</h3>
<div className="h-6 w-6 rounded-full border border-gray-600" style={{ backgroundColor: data?.color?.value }} />
<div
className="h-6 w-6 rounded-full border border-gray-600"
style={{ backgroundColor: data?.color?.value }}
/>
</div>
<div className="flex items-center gap-x-4">
<h3 className="font-semibold text-black">Color:</h3>
<Rating value={Math.floor(Math.random() * 5) + 1} />
<div className="flex items-center gap-x-4">
<h3 className="font-semibold text-black">Color:</h3>
<Rating value={Math.floor(Math.random() * 5) + 1} />
</div>
</div>
<div className="mt-10 flex items-center gap-x-3">
{
isInCart ? (
<Button onClick={onRemoveFromCart} className="flex items-center gap-x-2">
Remove Item
<Trash2 size={20} className="text-red-600"/>
</Button>
) :
(
<Button onClick={onAddToCart} className="flex items-center gap-x-2">
Add To Cart
<ShoppingCart size={20} />
</Button>
)
}
<div className="mt-10 flex items-center gap-x-3 flex-wrap gap-y-2">
{isInCart ? (
<Button
onClick={onRemoveFromCart}
className="flex items-center gap-x-2"
>
Remove Item
<Trash2 size={20} className="text-red-600" />
</Button>
) : (
<Button onClick={onAddToCart} className="flex items-center gap-x-2">
Add To Cart
<ShoppingCart size={20} />
</Button>
)}
<Button onClick={onShare} className="flex items-center gap-x-2">
Share
</Button>
<Button
className="flex bg-black items-ceter gap-x-2 text-white "
onClick={toggleWishlist}
>
Wishlist
{isInWishlist ? (
<Heart className=" text-red-600 fill-red-600" />
) : (
<Heart className="bg-none text-white" />
)}
</Button>
</div>
</div>
);
}
};

export default Info;
25 changes: 14 additions & 11 deletions components/navbar-actions.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { ShoppingBag } from "lucide-react";
import { ShoppingBag, Heart } from "lucide-react";
import { useRouter } from "next/navigation";
import { useEffect, useState } from "react";

Expand All @@ -21,19 +21,22 @@ const NavbarActions = () => {
return null;
}

return (
<div className="ml-auto flex items-center gap-x-4">
<Button onClick={() => router.push('/cart')} className="flex items-center rounded-full bg-black px-4 py-2">
<ShoppingBag
size={20}
color="white"
/>
return (
<div className="ml-auto flex items-center md:gap-x-4 gap-x-1">
<Button
onClick={() => router.push("/cart")}
className="flex items-center rounded-full bg-black md:px-4 px-1 py-1 md:py-2"
>
<ShoppingBag size={20} color="white" />
<span className="ml-2 text-sm font-medium text-white">
{cart.items.length}
</span>
</Button>
<div onClick={() => router.push("/wishlist")}>
<Heart />
</div>
</div>
);
}
export default NavbarActions;
};

export default NavbarActions;
43 changes: 43 additions & 0 deletions hooks/use-wishlist.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { create } from "zustand";
import { toast } from "react-hot-toast";
import { persist, createJSONStorage } from "zustand/middleware";

import { Product } from "@/types";
import { AlertTriangle } from "lucide-react";

interface WishlistStore {
items: Product[];
addItem: (data: Product) => void;
removeItem: (id: string) => void;
removeAll: () => void;
}

const useWishlist = create(
persist<WishlistStore>(
(set, get) => ({
items: [],
addItem: (data: Product) => {
const currentItems = get().items;
const existingItem = currentItems.find((item) => item.id === data.id);

if (existingItem) {
return toast("Item already in wishlist.");
}

set({ items: [...get().items, data] });
toast.success("Item added to wishlist.");
},
removeItem: (id: string) => {
set({ items: [...get().items.filter((item) => item.id !== id)] });
toast.success("Item removed from wishlist.");
},
removeAll: () => set({ items: [] }),
}),
{
name: "wishlist-storage",
storage: createJSONStorage(() => localStorage),
}
)
);

export default useWishlist;

0 comments on commit 6777c4e

Please sign in to comment.