Skip to content

Commit

Permalink
landing page bugfix
Browse files Browse the repository at this point in the history
add cart
add wishlist
  • Loading branch information
hozayves committed Jul 24, 2024
1 parent f6b7c98 commit d89f3aa
Show file tree
Hide file tree
Showing 17 changed files with 301 additions and 229 deletions.
42 changes: 11 additions & 31 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@ import GoogleAuthSuccess from './components/authentication/GoogleAuthSucces';
import { ToastContainer } from 'react-toastify';
import Searchpage from './containers/searchResults/SearchPage';
import { useDispatch } from 'react-redux';
import { ProductResponse, Product } from './types/Types';
import { useEffect, useRef } from 'react';
import { useGetProductsQuery } from './services/productApi';
import { setError, setIsLoading, setProductFetched, setProductsDataList } from './redux/slices/productsSlice';
import { useEffect } from 'react';
import { productsApi } from './services/productApi';
import Checkout from './components/checkout/Checkout';
import RestrictedRoute from './components/dashboard/RestrictedRoute';
import AdminPage from './pages/admin';
Expand All @@ -37,38 +35,20 @@ import { cartApi } from './services/cartApi';
import VerifyOTPPage from './pages/VerifyOTPPage';
import PaymentSuccessCard from './components/checkout/PaymentSuccessCard';
import PaymentPage from './pages/PaymentPage';
import { useSelector } from 'react-redux';
import { RootState } from './redux/store';

import BuyerRestrictedRoutes from './containers/buyer/BuyerRestrictedRoutes';
const App = () => {
const { data, error, isLoading } = useGetProductsQuery();
const isAuthenticated = useSelector((state: RootState) => state.user.token);
const dispatch = useDispatch();
const firstRender = useRef(true);

const productsData: ProductResponse = data as unknown as ProductResponse;

useEffect(() => {
const fetchProducts = async () => {
if (firstRender.current) {
firstRender.current = false;
return;
}
if (error) {
dispatch(setError(error));
dispatch(setIsLoading(false));
dispatch(setProductFetched(false));
return;
}
if (!isLoading && productsData) {
const productsList = productsData.data as unknown as Product[];
dispatch(setProductsDataList([...productsList]));
dispatch(setIsLoading(false));
dispatch(setProductFetched(true));
}
};
fetchProducts();

dispatch<any>(cartApi.endpoints.getCarts.initiate());
}, [productsData, isLoading, dispatch]);
dispatch<any>(productsApi.endpoints.getProducts.initiate())
if (isAuthenticated) {
dispatch<any>(cartApi.endpoints.getCarts.initiate());
console.log("Cart")
}
}, [dispatch]);

const router = createBrowserRouter([
{
Expand Down
124 changes: 100 additions & 24 deletions src/components/Products/ProductCard.tsx
Original file line number Diff line number Diff line change
@@ -1,46 +1,122 @@
import { FaHeart } from 'react-icons/fa6';
import { useSelector } from 'react-redux';
import { RootState } from '../../redux/store';
import { useAddProductToCartMutation, useDeleteCartMutation } from '../../services/cartApi';
import { useAddProductToWishlistMutation, useRemoveWishListMutation } from '../../services/wishlistApi';
import { Product } from '../../types/Types';
import { TiShoppingCart } from 'react-icons/ti';
import StarRating from '../common/Ratings';
import { IoIosHeart, IoIosHeartEmpty } from 'react-icons/io';
import { MdOutlineAddShoppingCart } from 'react-icons/md';
import { useNavigate } from 'react-router-dom';
interface ProductCardProps {
product: Product;
cartAdded?: boolean,
wishList?: boolean,
wishListId?: string | string
}

const ProductCard: React.FC<ProductCardProps> = ({ product }) => {
const ProductCard: React.FC<ProductCardProps> = ({ product, cartAdded, wishList, wishListId }) => {
const imageUrl = product?.images?.[0] ?? '';
const price = product?.sizes?.[0]?.price ?? '';
const navigate = useNavigate();
const productId = product?.id
const sizeId = product?.sizes[0].id
const [addProductToCart] = useAddProductToCartMutation()
const [deleteCart] = useDeleteCartMutation()
const [addProductToWishlist] = useAddProductToWishlistMutation()
const [removeWishList] = useRemoveWishListMutation()
const isAuthenticated = useSelector((state: RootState) => state.user.token) ? true : false;
const navigate = useNavigate()

// AddCart
const onAddProductToCart = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
if (isAuthenticated) {
await addProductToCart({ productId, sizeId })
} else {
navigate("/login")
}
}
// RemoveCart
const onRemoveProductToCart = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
if (isAuthenticated && sizeId) {
await deleteCart({ productId, sizeId })
} else {
navigate("/login")
}
}
// AddWishList
const onAddWishList = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
if (isAuthenticated && sizeId) {
await addProductToWishlist(sizeId)
} else {
navigate("/login")
}
}
// onRemoveWishList
const onRemoveWishList = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
if (isAuthenticated && wishListId) {
await removeWishList(wishListId)
} else {
navigate("/login")
}
}
return (
<div
onClick={() => {
navigate(`/products/${product.id}`);
window.scrollTo({ top: 0, behavior: 'smooth' });
window.open(`/products/${product.id}`, '_blank');
// window.scrollTo({ top: 0, behavior: 'smooth' });
}}
className='product-card bg-whiteColor min-w-44 md:min-w-56 lg:min-w-56
shadow-lg rounded-lg p-2 m-4 md:p-4 md:m-4 transition-transform hover:scale-105 cursor-pointer'
className='bg-whiteColor flex-col relative w-[49%] sm:w-52 md:w-[32.5%] lg:w-[19%] 2xl:w-[253px] mb-2 drop-shadow-md rounded-lg cursor-pointer'
>
<div className='product-image flex justify-center'>
<img src={imageUrl} alt={product.name} className='w-32 h-32 rounded-sm object-cover md:h-48 md:w-48' />
<div className='product-image flex justify-center w-full rounded-tl-lg rounded-tr-lg relative'>
<img src={imageUrl} alt={product.name} className='w-full h-52 md:h-60 rounded-tl-lg rounded-tr-lg object-cover object-top' />
<div className='absolute bottom-2 right-2 flex flex-col gap-1'>
{cartAdded
? (
<button
onClick={onRemoveProductToCart}
className={`cursor-pointer p-1 w-9 h-9 flex justify-center items-center rounded-full bg-[#fafafa] drop-shadow-lg ${cartAdded ? 'bg-blackColor' : ''}`}>
<MdOutlineAddShoppingCart size={20} color='white' />
</button>
)
: (
<button
onClick={onAddProductToCart}
className='cursor-pointer p-1 w-9 h-9 flex justify-center items-center rounded-full bg-[#fafafa] drop-shadow-lg'>
<MdOutlineAddShoppingCart size={20} />
</button>
)}
{wishList
? (
<button
onClick={onRemoveWishList}
className={`p-1 rounded-full w-9 h-9 flex justify-center items-center bg-[#fafafa] drop-shadow-md`}>
<IoIosHeart size={30} />
</button>
)
: (
<button
onClick={onAddWishList}
className='p-1 rounded-full w-9 h-9 flex justify-center items-center bg-[#fafafa] drop-shadow-md'>
<IoIosHeartEmpty size={30} />
</button>
)}

</div>
</div>
<div className='product-name-cart-button pt-2'>
<div className='product-name-cart-button p-1 '>
<div className='product-manufacturer'>
<div className='name-price flex justify-between'>
<h3 className='text-md font-bold'>{product.name}</h3>
<p className='text-md font-bold'>${price}</p>
</div>
<p className='text-sm p-2 text-[#949191]'>{product.manufacturer}</p>
</div>
<div className='cart-button mt-4'>
<div className='cart-wish-icons-ratings flex justify-between'>
<div className='cart-wish-icons text-2xl flex gap-2'>
<TiShoppingCart className='cursor-pointer' />
<FaHeart className='cursor-pointer' />
</div>
<div className='ratings flex '>
<div className='flex flex-col justify-between'>
<h3 className='text-xs font-normal tracking-tighter truncate capitalize'>{product.name.toLowerCase()}</h3>
<div>
<StarRating reviews={product.reviews} />
</div>
<p className='flex items-center py-2'>
<span className='self-start'>$</span>
<span className='text-2xl font-bold self-end'>{price.toFixed(2)}</span>
</p>
</div>
</div>
</div>
Expand Down
8 changes: 6 additions & 2 deletions src/components/authentication/GoogleAuthSucces.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useEffect } from 'react';
import { useNavigate, useLocation, useParams } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { setToken } from '../../redux/slices/userSlice';
import { setToken, setUser } from '../../redux/slices/userSlice';
import { CustomJwtPayload } from '../../types/Types';
import { jwtDecode } from 'jwt-decode';

const GoogleAuthSuccess = () => {
const navigate = useNavigate();
Expand All @@ -12,11 +14,13 @@ const GoogleAuthSuccess = () => {
useEffect(() => {
if (token) {
dispatch(setToken(token));
const decodedToken = jwtDecode<CustomJwtPayload>(token);
dispatch(setUser(decodedToken.id));
navigate('/');
}
}, [location, dispatch, navigate]);

return <div>Loading...</div>;
};

export default GoogleAuthSuccess;
export default GoogleAuthSuccess;
2 changes: 1 addition & 1 deletion src/components/authentication/LoginComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import GoogleIcon from '../../assets/googleIcon.svg';
import Button from '../common/Button';
import Input from '../common/Input';
import { loginSchema, LoginData } from '../../utils/schemas';
import { useNavigate, useLocation, useSearchParams } from 'react-router-dom';
import { useNavigate, useLocation, useSearchParams, Navigate } from 'react-router-dom';

Check failure on line 9 in src/components/authentication/LoginComponent.tsx

View workflow job for this annotation

GitHub Actions / Build (20)

'Navigate' is declared but its value is never read.
import { useSelector, useDispatch } from 'react-redux';
import { setToken, setUser, setRole, enable2FA } from '../../redux/slices/userSlice';
import { useLoginUserMutation } from '../../services/authAPI';
Expand Down
8 changes: 6 additions & 2 deletions src/components/cart/Cart.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
import React, { useEffect, useState } from 'react';
import { useSelector } from 'react-redux'; // Assuming you're using Redux for state management
import Navbar from '../navbar/Navbar';
import CartItem from './CartItem';
import { Link } from 'react-router-dom';
import { RootState } from '../../redux/store'; // Replace with your actual root state type
import { ICartProduct, ICartsHookResponse, ICartsResponse } from '../../utils/schemas';
import { useGetCartsQuery } from '../../services/cartApi';

const Cart: React.FC = () => {
const isAuthenticated = useSelector((state: RootState) => state.user.token ? true : false); // Assuming 'user' is part of your Redux state
const {
data: carts,
isLoading,
isSuccess,
isError,
error,
} = useGetCartsQuery<ICartsResponse>() as ICartsHookResponse;
} = useGetCartsQuery<ICartsResponse>({ enabled: isAuthenticated }) as ICartsHookResponse;

Check failure on line 18 in src/components/cart/Cart.tsx

View workflow job for this annotation

GitHub Actions / Build (20)

Argument of type '{ enabled: boolean; }' is not assignable to parameter of type 'void | unique symbol'.
const [totalPrice, setTotalPrice] = useState(0);
const [items, setItems] = useState(0);

Expand Down Expand Up @@ -51,7 +54,7 @@ const Cart: React.FC = () => {
} else if (isError) {
content = <div>{error?.toString()}</div>;
}

return (
<div className='w-full min-h-screen overflow-x-hidden font-roboto flex flex-col 2xl:items-center'>
<Navbar />
Expand Down Expand Up @@ -81,4 +84,5 @@ const Cart: React.FC = () => {
</div>
);
};

export default Cart;
6 changes: 4 additions & 2 deletions src/components/common/Ratings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ const StarRating: React.FC<RatingsProps> = ({ reviews }) => {
}
return stars;
};

return <div className="ratings flex">{renderStars()}</div>;
return <div className="ratings flex items-center gap-1 w-12">
<span className='flex'>{renderStars()}</span>
<span className='text-sm'>({reviews.length > 0 ? averageRating : '0'})</span>
</div>;
};

export default StarRating;
2 changes: 1 addition & 1 deletion src/components/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const Navbar: React.FC = () => {
isLoading: isFetchingUser,
isSuccess: isUserFetched,
data: userData,
} = useGetUserByIdQuery(userId);
} = useGetUserByIdQuery(userId, { skip: !userId });
const handleNavigate = () => {
const token = localStorage.getItem('token') || null;
if (!token) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/navbar/notifications/Notifications.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export const Notifications = () => {
const [notifications, setNotifications] = useState<NotificationProps[]>([]);
const [unRead, setUnRead] = useState<number>(0);

const { data: fetchedNotifications, isLoading, isError } = useGetNotificationsQuery(userId);
const { data: fetchedNotifications, isLoading, isError } = useGetNotificationsQuery(userId, { skip: !userId });

const [deleteAll, { isLoading: areAllDeleting, isSuccess: areDeleted }] = useDeleteAllNotificationsMutation();
const [markAll, { isLoading: areAllUpdating, isSuccess: areAllUpdated }] = useMarkAllNotificationsAsReadMutation();
Expand Down
Loading

0 comments on commit d89f3aa

Please sign in to comment.