Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[finishes #187943570] buyer dashboard #38

Merged
merged 1 commit into from
Jul 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ import { ProductDetail } from './pages/product/ProductDetail';
import Cart from './components/cart/Cart';
import { cartApi } from './services/cartApi';
import VerifyOTPPage from './pages/VerifyOTPPage';
import PaymentSuccessCard from './components/checkout/PaymentSuccessCard';
import PaymentPage from './pages/PaymentPage';

import BuyerRestrictedRoutes from './containers/buyer/BuyerRestrictedRoutes';
const App = () => {
const { data, error, isLoading } = useGetProductsQuery();
const dispatch = useDispatch();
Expand Down Expand Up @@ -91,6 +94,16 @@ const App = () => {
path: 'categories/:categoryId',
element: <CategoriesPage />,
},
{
path: 'payment',
element: <PaymentPage />,
children: [
{
path: 'success',
element: <PaymentSuccessCard />,
},
],
},
{
path: 'verifyOTP',
element: <VerifyOTPPage />,
Expand All @@ -110,9 +123,13 @@ const App = () => {
element: <ProductDetail />,
},
{
path: "/checkoutbag",
element: <Checkout />
path: '/checkoutbag',
element: <Checkout />,
},
{
path: 'buyer-profile',
element: <BuyerRestrictedRoutes role='buyer' />,
}
],
},
{
Expand Down
4 changes: 2 additions & 2 deletions src/components/OrderTables.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import { Button } from './ui/button';
import { useGetOrdersQuery } from "../services/ordersApi";
import { useGetOrdersQuery } from "../services/orderApi";
import { Order } from "../types/Types";
import { CiSearch } from 'react-icons/ci';

Expand All @@ -18,7 +18,7 @@ const TransactionTable: React.FC = () => {
const [currentPage, setCurrentPage] = useState<number>(1);
const [searchQuery, setSearchQuery] = useState<string>('');
const { data: ordersData, isLoading, isError } = useGetOrdersQuery();
const orders = ordersData?.data || [];
const orders = ordersData || [];

const handleStatusChange = (status: string) => {
setSelectedStatus(status);
Expand Down
9 changes: 8 additions & 1 deletion src/components/authentication/Enable2FA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { useEffect, useState } from 'react';
import { useAppSelector, useAppDispatch } from '../../hooks/customHooks';
import { enable2FA as set2FA } from '../../redux/slices/userSlice';
import { useEnable2FAMutation } from '../../services/Enable2FAApi';
import { useGetUserByIdQuery } from '../../services/userApi';
import { toast } from 'react-toastify';
const Enable2FA = () => {
const userId = useAppSelector(state => state.user.userId);
const { data: userData, isSuccess: isUserFetched } = useGetUserByIdQuery(userId);

const initialState = useAppSelector(state => state.user.is2FAEnabled) as boolean;
const token = useAppSelector(state => state.user.token) as string;
const [enabled, setEnabled] = useState<boolean>(initialState);
Expand All @@ -17,12 +21,15 @@ const Enable2FA = () => {
if (initialState === true && enabled) toast.success('Disabled 2 factor Authentication');
if (!enabled) toast.success('Enabled 2 factor Authentication');
} catch (err) {
console.log(err);
toast.error('Error handling 2 factor authentication!');
}
};
useEffect(() => {
if (isError) dispatch(set2FA(!enabled));
if (isUserFetched) {
dispatch(set2FA(userData.message.enable2FA));
setEnabled(userData.message.enable2FA);
}
}, [enabled, dispatch, isError, setEnabled]);
return (
<div className='flex gap-4 bg-grayColor lg:w-1/3 sm:mx-0 md:w-1/2 lg:ml-2 md:ml-[10%] sm:2/3 w-4/5 mx-auto justify-center items-center py-4 rounded-md px-4'>
Expand Down
133 changes: 75 additions & 58 deletions src/components/cart/Cart.tsx
Original file line number Diff line number Diff line change
@@ -1,67 +1,84 @@
import React, { useEffect, useState } from "react"
import Navbar from "../navbar/Navbar"
import CartItem from "./CartItem"
import { Link } from "react-router-dom"
import { ICartProduct, ICartsHookResponse, ICartsResponse } from "../../utils/schemas"
import { useGetCartsQuery } from "../../services/cartApi"
import React, { useEffect, useState } from 'react';
import Navbar from '../navbar/Navbar';
import CartItem from './CartItem';
import { Link } from 'react-router-dom';
import { ICartProduct, ICartsHookResponse, ICartsResponse } from '../../utils/schemas';
import { useGetCartsQuery } from '../../services/cartApi';

const Cart: React.FC = () => {
const { data: carts, isLoading, isSuccess, isError, error } = useGetCartsQuery<ICartsResponse>() as ICartsHookResponse;
const [totalPrice, setTotalPrice] = useState(0)
const [items, setItems] = useState(0)
const {
data: carts,
isLoading,
isSuccess,
isError,
error,
} = useGetCartsQuery<ICartsResponse>() as ICartsHookResponse;
const [totalPrice, setTotalPrice] = useState(0);
const [items, setItems] = useState(0);

useEffect(() => {
if (isSuccess && carts) {
// Calculate total price
const calculatedTotalPrice = carts.cartProducts.reduce((total: number, cart: ICartProduct) => {
const pricePerItem = cart.sizes[0]?.price || 0;
const itemTotalPrice = pricePerItem * cart.quantity;
return total + itemTotalPrice;
}, 0);
useEffect(() => {
if (isSuccess && carts) {
// Calculate total price
const calculatedTotalPrice = carts.cartProducts.reduce((total: number, cart: ICartProduct) => {
const pricePerItem = cart.sizes[0]?.price || 0;
const itemTotalPrice = pricePerItem * cart.quantity;
return total + itemTotalPrice;
}, 0);

// Update total price state
setTotalPrice(calculatedTotalPrice);
// Update total price state
setTotalPrice(calculatedTotalPrice);

// Optionally calculate the number of items if needed
const totalItems = carts.cartProducts.length;
setItems(totalItems);
}
}, [isSuccess, carts]);
// Optionally calculate the number of items if needed
const totalItems = carts.cartProducts.length;
setItems(totalItems);
}
}, [isSuccess, carts]);

let content;
if (isLoading) {
content = <div>Loading</div>
} else if (isSuccess) {
const renderedCart = carts?.cartProducts.map((cart, index) => {
const price = cart.sizes[0]?.price
return <CartItem key={index} {...cart} price={price} />
let content;
if (isLoading) {
content = <div>Loading</div>;
} else if (isSuccess) {
const renderedCart =
carts?.cartProducts?.length === 0 ? (
<p>No item in the cart</p>
) : (
carts?.cartProducts.map((cart, index) => {
const price = cart.sizes[0]?.price;
return <CartItem key={index} {...cart} price={price} />;
})
content = renderedCart
} 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 />
<div className="w-full px-3 pt-5 flex flex-col gap-2 md:p-4 xl:px-10 2xl:w-[1440px]">
<h1 className="leading-none font-semibold text-lg subpixel-antialiased tracking-wide">Shopping Cart ({items})</h1>
<p className="leading-none subpixel-antialiased text-xs tracking-wide font-light hidden md:block">Your cart contains {items} items and comes to a total of ${totalPrice}</p>
<div className="flex flex-col md:flex-row-reverse lg:gap-10 xl:gap-12">
<div className="flex flex-col gap-4 px-3 py-2 pt-4 md:flex-grow lg:w-72 lg:flex-grow-0 xl:flex-grow-0 xl:w-80">
<div className="flex justify-between text-sm font-medium">
<span className="md:font-semibold md:text-lg">Total:</span>
<span className="md:font-semibold md:text-lg">${totalPrice}</span>
</div>
<Link to="/checkoutbag"
className="leading-none bg-greenColor hover:bg-[#1a6461] rounded-full px-5 py-3 text-whiteColor font-medium text-xs transition-all delay-75 ease-in cursor-pointer text-center"
>Checkout</Link>
</div>
<div className="bg-[#f7f7f7] flex flex-col py-3 mt-2 md:flex-grow">
{content}
</div>
</div>
);
content = renderedCart;
} 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 />
<div className='w-full px-3 pt-5 flex flex-col gap-2 md:p-4 xl:px-10 2xl:w-[1440px]'>
<h1 className='leading-none font-semibold text-lg subpixel-antialiased tracking-wide'>
Shopping Cart ({items})
</h1>
<p className='leading-none subpixel-antialiased text-xs tracking-wide font-light hidden md:block'>
Your cart contains {items} items and comes to a total of ${totalPrice}
</p>
<div className='flex flex-col md:flex-row-reverse lg:gap-10 xl:gap-12'>
<div className='flex flex-col gap-4 px-3 py-2 pt-4 md:flex-grow lg:w-72 lg:flex-grow-0 xl:flex-grow-0 xl:w-80'>
<div className='flex justify-between text-sm font-medium'>
<span className='md:font-semibold md:text-lg'>Total:</span>
<span className='md:font-semibold md:text-lg'>${totalPrice}</span>
</div>
<Link
to='/checkoutbag'
className='leading-none bg-greenColor hover:bg-[#1a6461] rounded-full px-5 py-3 text-whiteColor font-medium text-xs transition-all delay-75 ease-in cursor-pointer text-center'
>
Checkout
</Link>
</div>
<div className='bg-[#f7f7f7] flex flex-col py-3 mt-2 md:flex-grow'>{content}</div>
</div>
)
}
export default Cart
</div>
</div>
);
};
export default Cart;
Loading
Loading