Skip to content

Commit

Permalink
Merge pull request #26 from hdcola/hddev
Browse files Browse the repository at this point in the history
link cart to checkout first version
  • Loading branch information
hdcola authored Nov 3, 2024
2 parents d669319 + 1ab4c79 commit e151bc1
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 77 deletions.
68 changes: 68 additions & 0 deletions src/api/useGetCartItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
import useLoginStore from '../store/useLoginStore';


interface ICheckout {
itemsTotal: number;
shopDiscount: number;
subtotal: number;
shipping: number;
total: number;
}

interface IItem {
item_id: number;
image_url?: string;
name: string;
description?: string;
price: number;
quantity: number;
store: IStore;
carts_items: ICartsItems;
}

interface ICartsItems {
quantity: number;
discount_percent: number | null;
}

interface IStore {
store_id: number;
name: string;
description?: string;
rating: number;
logo_url?: string;
image_url?: string;
country: ICountry;
}

interface ICountry {
country_id: number;
name: string;
code: string;
}

const fetchCartItems = async () => {
const apiUrl = import.meta.env.VITE_API_URL;
const { authToken } = useLoginStore.getState();

const res = await axios.get(`${apiUrl}/api/carts`, {
headers: { Authorization: `Bearer ${authToken}` },
});
if (res.status === 200) {
return { items: res.data.items as IItem[], checkout: res.data.checkout as ICheckout };
}
throw new Error('Failed to fetch cart items');
}

const useGetCartItems = (enabled: boolean) => {
return useQuery({
queryKey: ['getCartItems'],
queryFn: fetchCartItems,
enabled
})
}

export default useGetCartItems;
export type { ICheckout, IItem, ICartsItems, IStore, ICountry };
90 changes: 17 additions & 73 deletions src/pages/Cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import { useState, useEffect } from 'react';
import { useAppContext } from '../App';
import NumberCounter from '../components/NumberCounter';
import useCartCount from '../hooks/useCartCount';
import { useNavigate } from 'react-router-dom';
import useGetCartItems from '../api/useGetCartItems';
import type { IItem } from '../api/useGetCartItems';

const CartItem = ({ refreshCart, removeItem, itemData }: Props) => {
const { server } = useAppContext();
Expand Down Expand Up @@ -124,28 +127,10 @@ const CartItem = ({ refreshCart, removeItem, itemData }: Props) => {

const Cart = () => {
const { isInit, server, setCartCount } = useAppContext();
const [items, setItems] = useState<IItem[]>([]);
const [checkout, setCheckout] = useState<ICheckout>({} as ICheckout);
useCartCount();
const navigate = useNavigate();

const { refetch } = useQuery({
queryKey: ['cart'],
queryFn: async () => {
return axios
.get(`${server.apiUrl}/api/carts`, {
headers: { Authorization: `Bearer ${server.authToken}` },
})
.then((res) => {
if (res.status === 200) {
setItems(res.data.items);
setCheckout(res.data.checkout);
return res.data;
}
return items;
});
},
enabled: isInit,
});
const { refetch, data: { items, checkout } = {} } = useGetCartItems(isInit);

const handleRemove = (itemId: number) => {
axios
Expand All @@ -154,10 +139,6 @@ const Cart = () => {
})
.then((res) => {
if (res.status === 204) {
const newItems = items.filter(
(item) => item.item_id !== itemId
);
setItems(newItems);
setCartCount((prev: number) => prev - 1);
refetch();
}
Expand All @@ -173,7 +154,7 @@ const Cart = () => {
Your cart
</Typography>
<Stack spacing={2}>
{items.map((item) => {
{items?.map((item) => {
return (
<CartItem
key={item.item_id}
Expand All @@ -198,7 +179,7 @@ const Cart = () => {
Item(s) total
</Typography>
<Typography variant="body1">
CA${checkout.itemsTotal}
CA${checkout?.itemsTotal}
</Typography>
</Stack>
{/* Shop discount */}
Expand All @@ -210,7 +191,7 @@ const Cart = () => {
Shop discount
</Typography>
<Typography variant="body1">
- CA${checkout.shopDiscount}
- CA${checkout?.shopDiscount}
</Typography>
</Stack>
<Divider />
Expand All @@ -223,7 +204,7 @@ const Cart = () => {
Subtotal
</Typography>
<Typography variant="body1">
CA${checkout.subtotal}
CA${checkout?.subtotal}
</Typography>
</Stack>
{/* Shipping */}
Expand All @@ -235,7 +216,7 @@ const Cart = () => {
Shipping
</Typography>
<Typography variant="body1">
CA${checkout.shipping}
CA${checkout?.shipping}
</Typography>
</Stack>
<Divider />
Expand All @@ -245,10 +226,10 @@ const Cart = () => {
justifyContent="space-between"
>
<Typography fontWeight={'bold'}>
Total ({items.length} items)
Total ({items?.length} items)
</Typography>
<Typography variant="body1" fontWeight={'bold'}>
CA${checkout.total}
CA${checkout?.total}
</Typography>
</Stack>
</Stack>
Expand All @@ -259,6 +240,9 @@ const Cart = () => {
sx={{
borderRadius: 50,
}}
onClick={() => {
navigate('/checkout');
}}
>
Checkout
</Button>
Expand All @@ -271,48 +255,8 @@ const Cart = () => {

interface Props {
itemData: IItem;
removeItem: Function;
refreshCart: Function;
}

interface IItem {
item_id: number;
image_url?: string;
name: string;
description?: string;
price: number;
quantity: number;
store: IStore;
carts_items: ICartsItems;
}

interface ICartsItems {
quantity: number;
discount_percent: number | null;
}

interface IStore {
store_id: number;
name: string;
description?: string;
rating: number;
logo_url?: string;
image_url?: string;
country: ICountry;
}

interface ICountry {
country_id: number;
name: string;
code: string;
}

interface ICheckout {
itemsTotal: number;
shopDiscount: number;
subtotal: number;
shipping: number;
total: number;
removeItem: (itemId: number) => void;
refreshCart: () => void;
}

export default Cart;
17 changes: 13 additions & 4 deletions src/pages/CheckoutPage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import { Elements, useStripe } from '@stripe/react-stripe-js';
import { useStripeClientSecret } from '../api/useStripeClientSecret';
import { CheckoutForm } from '../components/CheckoutForm';
import useGetCartItems from '../api/useGetCartItems';

export const CheckoutPage = () => {
const items = [
{ id: 'M4 MacBook Pro', amount: 20000 },
{ id: 'M1 MacBook Air', amount: 10000 },
];
const { data: { items: cartItem, checkout } = {} } = useGetCartItems(true);
console.log(cartItem);
console.log(checkout);

const items = cartItem
? cartItem.map((item) => {
return {
id: item.name,
amount: Number(item.price) * item.quantity * 100,
};
})
: [];

const stripe = useStripe();

Expand Down

0 comments on commit e151bc1

Please sign in to comment.