Skip to content

Commit

Permalink
bug-fix(button-loading):add a loading state to clicked button
Browse files Browse the repository at this point in the history
  • Loading branch information
emmanueltct committed Jul 12, 2024
1 parent f6cfec4 commit 174282b
Show file tree
Hide file tree
Showing 7 changed files with 56 additions and 28 deletions.
14 changes: 11 additions & 3 deletions src/app/products/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,19 @@ import { useQuery } from '@tanstack/react-query';
import ReviewCard from '@/components/ReviewCard';
import Button from '@/components/Button';
import { averageReviews } from '@/utils/averageReviews';
import { useAppDispatch } from '@/redux/store';
import { handleUserAddCart } from '@/redux/slices/userCartSlice';
import { RootState, useAppDispatch, useAppSelector } from '@/redux/store';
import { handleUserAddCart, IUSERCART } from '@/redux/slices/userCartSlice';
//import StripeProvider from '@/components/StripeProvider';

function Page() {
const [thumbsSwiper, setThumbsSwiper] = useState(null);
const [addProductToCart, setAddProductToCart]=useState(false)

const {cart} = useAppSelector(
(state: RootState) => state.userCartData,
);

const carts=cart as IUSERCART
const { id } = useParams();
const handleSwiper = (swiper: any) => {
setThumbsSwiper(swiper);
Expand Down Expand Up @@ -149,8 +156,9 @@ function Page() {
<div className="p-3 rounded-full bg-gray-200 hover:bg-green-500 hover:text-white cursor-pointer">
<FaRegHeart />
</div>
<div className="p-3 rounded-full bg-gray-200 hover:bg-green-500 hover:text-white cursor-pointer">
<div className={`p-3 rounded-full hover:bg-green-500 hover:text-white cursor-pointer '${(addProductToCart || carts.product.some(item => item.product ===data.product.id)) ?' bg-red-500 pointer-events-none':'pointer-events-auto bg-gray-200'}`}>
<MdOutlineShoppingCart

onClick={() => {
handleNewItem();
}}
Expand Down
18 changes: 15 additions & 3 deletions src/components/Card.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { MdOutlineRemoveRedEye, MdOutlineShoppingCart } from 'react-icons/md';
import Image from 'next/image'; //@ts-ignore
import ReactStars from 'react-rating-stars-component';
Expand All @@ -8,7 +8,7 @@ import image from '../../public/product.png';
import Link from 'next/link';
import { averageReviews } from '@/utils/averageReviews';
import { RootState, useAppDispatch, useAppSelector } from '@/redux/store';
import { handleUserAddCart } from '@/redux/slices/userCartSlice';
import { handleUserAddCart, IUSERCART } from '@/redux/slices/userCartSlice';

// import { useRouter } from 'next/router';

Expand All @@ -20,10 +20,20 @@ function Card({
id,
reviews,
}: Cards) {

const [addProductToCart, setAddProductToCart]=useState(false)
const {cart} = useAppSelector(
(state: RootState) => state.userCartData,
);

const carts=cart as IUSERCART
const productId = id;


const dispatch = useAppDispatch();

const handleNewItem = () => {
setAddProductToCart(true)
dispatch(handleUserAddCart({ productPrice, productId }));
};
return (
Expand Down Expand Up @@ -69,7 +79,9 @@ function Card({
</Link>
<FaRegHeart className="text-gray-700 mr-4 hover:text-red-500 cursor-pointer" />
<MdOutlineShoppingCart
className="text-gray-700 hover:text-green-500 cursor-pointer"

className={` hover:text-green-500 cursor-pointer ${addProductToCart || carts.product.some(item => item.product === id) ?
'text-red-600 pointer-events-none':'text-gray-700'}`}
onClick={() => {
handleNewItem();
}}
Expand Down
28 changes: 17 additions & 11 deletions src/components/CartContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const CartContainer = (hideOverLay: any) => {

const handleshow = hideOverLay;


const dispatch = useAppDispatch();
const allProduct = JSON.parse(localStorage.getItem('productItem') || '');
const carts = handleCartInfoManipulation(cart as IUSERCART, allProduct);
Expand All @@ -43,7 +44,7 @@ const CartContainer = (hideOverLay: any) => {
setCurrentCartItem(id);
dispatch(handleRemoveItemInCart(id));
};
const { handlePayment} = usePayments();
const { handlePayment, paymentLoading } = usePayments();

const handleIncreaseCartItem = async (id: string) => {
const updatedItems = carts;
Expand Down Expand Up @@ -236,7 +237,7 @@ const CartContainer = (hideOverLay: any) => {
{carts && carts.length > 0 ? (
<div className="w-full bottom-2 sm:max-w-full ">
<div className="bg-[#E5E5E5] w-full h-30 flex flex-col items-end ">
<div className="px-10 h-[60px] w-full flex justify-between font-semibold items-center">
<div className="px-10 h-[60px] w-full flex justify-between font-bold text-black items-center border-blue-50 border-b-2">
<span>Total Price</span>
<span>{formatNumber(cart?.totalPrice as number)} RWF</span>
</div>
Expand All @@ -246,28 +247,33 @@ const CartContainer = (hideOverLay: any) => {
<div className="border-t-4 border-b-4 border-blue-900 rounded-full w-6 h-6 animate-spin m-auto"></div>
) : (
<button
className={`w-1/2 h-[40px] bg-primaryBlue text-white flex justify-center items-center text-[20px] ${loading || carts.length == 0 ? 'cursor-not-allowed' : 'cursor-pointer'}`}
className={`w-1/2 h-[40px] bg-primaryBlue text-white flex justify-center items-center text-[20px] ${loading || paymentLoading || carts.length == 0 ? 'cursor-not-allowed opacity-40' : 'cursor-pointer'}`}
onClick={() => {
RemoveAllCart();
}}
disabled={paymentLoading || loading || carts.length === 0}
>
Clear All
</button>
)}
<button
className={`w-1/2 h-[40px] bg-[#71C154] text-white flex justify-center items-center text-[20px] ${loading || carts.length === 0 ? 'cursor-not-allowed' : 'cursor-pointer'}`}
onClick={handlePayment}
disabled={loading || carts.length === 0}
>
Place Order
</button>

{paymentLoading ? (
<div className="border-t-4 border-b-4 border-blue-900 rounded-full w-6 h-6 animate-spin m-auto"></div>
) : (
<button
className={`w-1/2 h-[40px] bg-[#71C154] text-white flex justify-center items-center text-[20px] ${paymentLoading || loading || carts.length === 0 ? 'cursor-not-allowed opacity-6' : 'cursor-pointer'}`}
onClick={handlePayment}
disabled={paymentLoading || loading || carts.length === 0}
>
Place Order
</button>
)}
</div>
</div>
</div>
) : (
''
)}

</div>
);
};
Expand Down
2 changes: 1 addition & 1 deletion src/components/ReviewCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface ReviewInterface {
const ReviewCard: React.FC<ReviewInterface> =({ rating, feedback, image, firstName, lastName }) =>{
return(
<div className='block'>
<div className="double-grid w-sm-[100%] w-md-[60%] w-[36%] border rounded-2xl border">
<div className="double-grid w-sm-[100%] w-md-[60%] w-[36%] rounded-2xl border">
<div className='flex items-center justify-center w-full'>
<img src={image} className="rounded-full h-[60px] w-[60px] border-black-1 "/>
</div>
Expand Down
10 changes: 6 additions & 4 deletions src/components/ReviewProductPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export const ReviewProduct: React.FC<ReviewProductInterface> = ({ id, isOpen, h
mutationFn: (feedback: string) => {
return request.post(`/products/${id}/reviews`, { feedback, rating })
},
onError: (error) => console.log(error),
onError: (error: any) => console.log(error),

onSuccess: async () => {
toast('successfully submitted your review', {
position: "top-right",
Expand All @@ -59,8 +60,8 @@ export const ReviewProduct: React.FC<ReviewProductInterface> = ({ id, isOpen, h
setFeedbackErrro("Feedback must be 10 chars atleast");
setRatingError('Please add rating');
return;
}if(feedback.length < 10) {
setFeedbackErrro("Feedback must be 10 chars atleast");
}if(feedback.length < 10 || feedback.length > 200 ) {
setFeedbackErrro("Feedback must be between 10 and 200 characters at least");
return;
}if(rating === 0){
setRatingError('Please add rating');
Expand Down Expand Up @@ -89,7 +90,8 @@ export const ReviewProduct: React.FC<ReviewProductInterface> = ({ id, isOpen, h
</div>
</div>
<div className='justify-center pb-4 flex w-full'>
<Button background='green' name='Submit' handle={handleSubmitReiew}/>
{mutation.isPending?(<div className="border-t-4 border-b-4 border-blue-900 rounded-full w-6 h-6 animate-spin m-auto"></div>):(<Button background='green' name='Submit' handle={handleSubmitReiew}/>)}

</div>
</dialog >
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/TruckOrder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ const TruckOrder: React.FC<any> = ({ id, isOpen, handleClose }) => {

<div className="w-1/3 flex flex-col items-center ">
<img
alt="delivery"
alt={orderData && orderData.Product.productName}
src={orderData && orderData.Product.productThumbnail}
className="w-[50%]"
/>
Expand Down
10 changes: 5 additions & 5 deletions src/hooks/payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const usePayments = () => {

const [error, setError] = useState('');
const [success, setSuccess] = useState(false);
const [loading, setLoading] = useState(false);
const [paymentLoading, setPaymentLoading] = useState(false);


const router = useRouter();
Expand All @@ -16,22 +16,22 @@ export const usePayments = () => {


try {
setPaymentLoading(true)
const res: any = await request.post(`/payments`, {});

router.push(`${res.paymenturl}`);
//router.push(`${res.paymenturl}`);

} catch (error: any) {
console.log('error', error);

setPaymentLoading(false)
setError(error.response.data.error);
}
};

return {
handlePayment,
success,
loading,

paymentLoading,
error,
};
};

0 comments on commit 174282b

Please sign in to comment.