-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Code to handle synchronization between local and DB user cart data (#8)
* Code to handle synchronization between local and DB user cart data * Updated file names of component files * Reverted file name changes to fix issue with Vercel build * Synchronizing cart data mutations with the backend * Refactored code & re-orgnanized project structure to follow standard guidelines
- Loading branch information
1 parent
4dc1a3a
commit 7604410
Showing
81 changed files
with
2,063 additions
and
398 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
app/(routes)/category/[id]/subcategory/[subCategoryId]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
app/(routes)/category/[id]/subcategory/[subCategoryId]/product/[productId]/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import {SignedIn, SignedOut, SignOutButton} from '@clerk/nextjs'; | ||
import {User2Icon} from 'lucide-react'; | ||
import Link from 'next/link'; | ||
|
||
export const SignInSignUpButtons = () => { | ||
return ( | ||
<div className="flex flex-row items-center justify-center rounded-lg"> | ||
<SignedOut> | ||
<Link | ||
href="/auth/sign-in" | ||
className="text-center text-violet-900 hover:bg-violet-50 rounded-lg px-2 py-1 md:px-3 md:py-2"> | ||
<span className={`font-[500]`}>Sign in</span> | ||
</Link> | ||
<Link | ||
href="/auth/sign-up" | ||
className="bg-violet-900 hover:bg-violet-800 text-white rounded-lg text-center px-2 py-1 md:px-3 md:py-2"> | ||
Sign up | ||
</Link> | ||
</SignedOut> | ||
<SignedIn> | ||
<SignOutButton> | ||
<div className="w-full flex flex-row gap-2 text-violet-900 text-md items-center cursor-pointer hover:bg-violet-50 px-2 py-1 md:px-3 md:py-2"> | ||
<span>Sign Out</span> | ||
<User2Icon size={20} /> | ||
</div> | ||
</SignOutButton> | ||
</SignedIn> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SignInSignUpButtons; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
'use client'; | ||
import {PlusIcon, ShoppingCartIcon} from 'lucide-react'; | ||
import classNames from 'classnames'; | ||
import {FC, useEffect, useMemo, useState} from 'react'; | ||
import {Toast} from '../toast/Toast'; | ||
import {CartItem, Product} from '@/app/lib/plamatio-backend/types'; | ||
import {useAppDispatch} from '@/app/lib/store/storeHooks'; | ||
import {addCartItem} from '@/app/lib/store/reducers/cart/cartReducer'; | ||
import {useAddCartItemMutation} from '@/app/lib/api/cart-items-slice'; | ||
|
||
type AddToCartButtonProps = { | ||
product: Product; | ||
userId?: string; | ||
showLabel?: boolean; | ||
className?: string; | ||
labelClassName?: string; | ||
}; | ||
|
||
export const AddToCartButton: FC<AddToCartButtonProps> = ( | ||
props: AddToCartButtonProps | ||
) => { | ||
const [toastVisible, setToastVisible] = useState(false); | ||
// dispatch cart actions | ||
const dispatch = useAppDispatch(); | ||
// when user logged in, need to add cart item to database | ||
const [addCartItemToDB, {isError, error}] = useAddCartItemMutation(); | ||
|
||
// Log any error in updating cart item on database | ||
useMemo(() => { | ||
if (isError) { | ||
console.error(`AddToCartButton: error adding cart item: ${error}`); | ||
} | ||
}, [isError, error]); | ||
|
||
useEffect(() => { | ||
if (toastVisible) { | ||
setTimeout(() => { | ||
setToastVisible(false); | ||
}, 1500); | ||
} | ||
}, [toastVisible]); | ||
|
||
const handleAddToCart = async () => { | ||
// prepare cart item | ||
const cartItemToAdd: CartItem = { | ||
id: Math.floor(Math.random() * 10000), | ||
product_id: props.product.id, | ||
quantity: 1, | ||
user_id: props.userId && props.userId.length > 0 ? props.userId : '', // no user id if not logged in | ||
}; | ||
|
||
// if valid user id, add cart item to database | ||
if (props.userId && props.userId.length > 0) { | ||
console.log( | ||
`AddToCartButton: adding cart item to database for user: ${props.userId}` | ||
); | ||
const r = await addCartItemToDB({ | ||
product_id: cartItemToAdd.product_id, | ||
quantity: cartItemToAdd.quantity, | ||
user_id: cartItemToAdd.user_id, | ||
}); | ||
if (r.data) { | ||
cartItemToAdd.id = r.data.id; | ||
} else { | ||
console.error(`AddToCartButton: error adding cart item: ${r.error}`); | ||
} | ||
} | ||
|
||
// add product to cart items | ||
dispatch(addCartItem(cartItemToAdd)); | ||
|
||
// show toast | ||
setToastVisible(true); | ||
}; | ||
|
||
return ( | ||
<> | ||
<Toast | ||
title="Added to Cart" | ||
visible={toastVisible} | ||
setVisible={setToastVisible} | ||
description={`${props.product.name} has been added to your cart.`} | ||
/> | ||
<button | ||
className={classNames( | ||
'flex flex-row align-middle justify-center p-2 rounded-md bg-violet-100 cursor-pointer hover:text-violet-100 hover:bg-violet-800', | ||
props.className | ||
)} | ||
onClick={handleAddToCart}> | ||
{props.showLabel && ( | ||
<span | ||
className={classNames('text-lg ml-3 mr-3', props.labelClassName)}> | ||
Add to Cart | ||
</span> | ||
)} | ||
<PlusIcon /> | ||
<ShoppingCartIcon /> | ||
</button> | ||
</> | ||
); | ||
}; | ||
|
||
export default AddToCartButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
'use client'; | ||
import {Product} from '@/app/lib/plamatio-backend/types'; | ||
import {FC} from 'react'; | ||
import StatefulCartButton from '@/app/components/cart/StatefulCartButton'; | ||
import {useUser} from '@clerk/nextjs'; | ||
import LoadingSpinner from '../ui/loading-spinner'; | ||
import MergeCartItems from './MergeCartItems'; | ||
|
||
type CartButtonProps = { | ||
product: Product; | ||
showLabel?: boolean; | ||
className?: string; | ||
labelClassName?: string; | ||
}; | ||
|
||
export const CartButton: FC<CartButtonProps> = (props) => { | ||
// get user id | ||
const {isLoaded, user} = useUser(); | ||
// if user is not available | ||
return ( | ||
<> | ||
{!isLoaded ? ( | ||
<LoadingSpinner /> | ||
) : ( | ||
<> | ||
<StatefulCartButton | ||
userId={user?.id} | ||
product={props.product} | ||
showLabel={props.showLabel} | ||
className={props.className} | ||
labelClassName={props.labelClassName} | ||
/> | ||
{user && <MergeCartItems userId={user.id} />} | ||
</> | ||
)} | ||
|
||
{/* If user signed in, merge cart items if any difference between local cart items & database */} | ||
</> | ||
); | ||
}; | ||
|
||
export default CartButton; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
'use client'; | ||
import classNames from 'classnames'; | ||
import {ShoppingBagIcon} from 'lucide-react'; | ||
import {FC, useState} from 'react'; | ||
import {CartWindow} from './CartWindow'; | ||
|
||
type CartIconProps = { | ||
className?: string; | ||
iconSize?: number; | ||
strokeWidth?: number; | ||
iconClassName?: string; | ||
}; | ||
|
||
export const CartIcon: FC<CartIconProps> = ({ | ||
className, | ||
iconSize, | ||
strokeWidth, | ||
iconClassName, | ||
}) => { | ||
const [displayCartWindow, setDisplayCartWindow] = useState(false); | ||
|
||
return ( | ||
<> | ||
<div className={classNames('', className)}> | ||
<button | ||
onClick={() => setDisplayCartWindow(!displayCartWindow)} | ||
className="text-violet-900"> | ||
<ShoppingBagIcon | ||
size={iconSize || 35} | ||
strokeWidth={strokeWidth || 1} | ||
className={classNames('', iconClassName)} | ||
/> | ||
</button> | ||
</div> | ||
{displayCartWindow && ( | ||
<div className="z-10 absolute top-[50px] right-[10px] md:right-[0px] w-auto"> | ||
<CartWindow /> | ||
</div> | ||
)} | ||
</> | ||
); | ||
}; | ||
|
||
export default CartIcon; |
Oops, something went wrong.