Skip to content

Commit

Permalink
user is now able to perform payments
Browse files Browse the repository at this point in the history
  • Loading branch information
EddyShimwa committed Jul 25, 2024
1 parent a81ebd7 commit c8d62a3
Show file tree
Hide file tree
Showing 21 changed files with 625 additions and 71 deletions.
512 changes: 468 additions & 44 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"pre-commit": "npm run lint:fix && npm run format"
},
"dependencies": {
"@emotion/styled": "^11.13.0",
"@mui/material": "^5.16.4",
"@react-jvectormap/core": "^1.0.4",
"@react-jvectormap/world": "^1.1.2",
"@reduxjs/toolkit": "^2.2.5",
Expand All @@ -26,8 +28,6 @@
"axios": "^1.7.2",
"axios-mock-adapter": "^1.22.0",
"chart.js": "^4.4.3",
"chart.js": "^4.4.3",
"date-fns": "^3.6.0",
"cloudinary": "^2.2.0",
"cloudinary-core": "^2.13.1",
"date-fns": "^3.6.0",
Expand Down Expand Up @@ -88,6 +88,7 @@
"eslint-plugin-react": "^7.34.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.6",
"husky": "^8.0.0",
"jest": "^29.7.0",
"jsdom": "^24.1.0",
"lint-staged": "^15.2.5",
Expand All @@ -99,7 +100,6 @@
"tailwindcss": "^3.4.3",
"typescript": "^5.2.2",
"vite": "^5.2.0",
"vitest": "^1.6.0",
"husky": "^8.0.0"
"vitest": "^1.6.0"
}
}
Binary file added src/assets/icons/Airtel.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/MemberDiscount.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/assets/icons/add.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/assets/icons/discount.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icons/masterCARD.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/moneyReturn.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions src/assets/icons/moneyReturn.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/mtn-momo.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/mtn_momo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions src/assets/icons/support.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/supportIcon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/assets/icons/truck.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions src/assets/icons/truck.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions src/assets/icons/visaIcon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/components/Cart/Cart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export default function Cart() {
const products: Product[] = useAppSelector((state: RootState) =>
selectProducts(state)
);

const cartItems = useAppSelector((state: RootState) =>
selectCartItems(state)
);
Expand Down
33 changes: 23 additions & 10 deletions src/components/Checkout/Checkout.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useState, useEffect } from 'react';
import { useState, useEffect, SetStateAction } from 'react';
import { useNavigate } from 'react-router-dom';
import CardInput, { Card } from './CardInput';
import { RootState } from '@/app/store';
import { fetchCartItems } from '@/features/Cart/cartSlice';
import { Checkout as CheckoutType } from '@/interfaces/checkout';
import BeatLoader from 'react-spinners/BeatLoader';

import {
selectCheckout,
placeOrder,
Expand Down Expand Up @@ -46,6 +48,7 @@ function Checkout() {
const dispatch = useAppDispatch();
const navigate = useNavigate();
const user = useAppSelector((state) => state.signIn.user);

function handleAdding() {
setAdding(!adding);
}
Expand All @@ -54,6 +57,7 @@ function Checkout() {
);
const order = checkoutState.checkout;
const { loading, error, paying } = checkoutState;

function handleSave(newCard: Card) {
setCards((prev) => [...prev, newCard]);

Expand All @@ -71,7 +75,9 @@ function Checkout() {
dispatch(placeOrder(checkout));
}


function handlePayment() {
console.log(order.id)
dispatch(makePayment(order.id));
}

Expand All @@ -84,7 +90,7 @@ function Checkout() {
dispatch(fetchCartItems());
navigate('/');
} else if (paying && error) {
showErrorToast(error || 'failed');
showErrorToast('failed');
}
}, [error, loading, paying, navigate, dispatch]);

Expand Down Expand Up @@ -369,7 +375,7 @@ function Checkout() {
<div className="mb-2">
<div className="flex justify-between py-2 text-xl">
<span className="text-gray-600">Total</span>
<span>${order.totalAmount}</span>
<span>${checkoutState.checkout.totalAmount}</span>
</div>
</div>

Expand All @@ -383,18 +389,25 @@ function Checkout() {
<div className="font-bold">
<div className="flex justify-between py-2 text-xl">
<span className="text-gray-600">Total Cost</span>
<span>${order.totalAmount}</span>
<span>${checkoutState.checkout.totalAmount}</span>
</div>
</div>
</div>

<button
className="w-full bg-primary text-white py-4 text-2xl font-medium rounded-md"
type="button"
onClick={handlePayment}
>
Pay Here
</button>
className={`w-full bg-primary text-white py-4 text-2xl font-medium rounded-md ${chosen ? '' : 'opacity-50 cursor-not-allowed'} ${paying ? 'opacity-75 cursor-not-allowed' : ''}`}
type="button"
onClick={handlePayment}
disabled={!chosen || paying}
>

{paying ? (
<BeatLoader data-testid="Loading" color="#ffffff" size={8} />
) : (
'Pay Here'
)}
</button>

</div>
</div>
);
Expand Down
36 changes: 24 additions & 12 deletions src/features/Cart/cartSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
import Cart from '@/interfaces/cart';
import { RootState } from '../../app/store';
import {
showSuccessToast,
showErrorToast,
showInfoToast,
} from '@/utils/ToastConfig';


interface CartState {
cartItems: Cart[];
Expand Down Expand Up @@ -70,18 +76,24 @@ export const removeCartItem = createAsyncThunk(

export const addCartItem = createAsyncThunk(
'cart/addCartItem',
async ({ productId, quantity }: { productId: number; quantity: number }) => {
const tokenFromStorage = localStorage.getItem('token') || '';
const response = await axios.post<AddPayload>(
`${baseUrl}/cart`,
{ productId, quantity },
{
headers: {
Authorization: `Bearer ${tokenFromStorage}`,
},
}
);
return response.data.cartItem;
async ({ productId, quantity }: { productId: number; quantity: number }, { rejectWithValue }) => {
try {
const tokenFromStorage = localStorage.getItem('token') || '';
const response = await axios.post<AddPayload>(
`${baseUrl}/cart`,
{ productId, quantity },
{
headers: {
Authorization: `Bearer ${tokenFromStorage}`,
},
}
);
showSuccessToast(response.data.cartItem.product.name + ' added to cart');
return response.data.cartItem;
} catch (error) {
showErrorToast('Failed to add cart item');
return rejectWithValue((error as any).response.data);
}
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import axios from 'axios';
import { RootState } from '../../app/store';
import { Checkout } from '@/interfaces/checkout';
import Order from '@/interfaces/order';
import { showErrorToast, showSuccessToast } from '@/utils/ToastConfig';

export interface CheckoutState {
checkout: Order;
Expand Down Expand Up @@ -36,6 +37,12 @@ const initialOrder: Order = {
],
};

interface MomoPaymentParams {
momoNumber: string;
orderId: number;
}


const initialState: CheckoutState = {
checkout: initialOrder,
loading: false,
Expand All @@ -62,6 +69,40 @@ export const placeOrder = createAsyncThunk(
}
);

export const makeMomoPayment = createAsyncThunk(
'payment/momoPayment',
async ({ momoNumber, orderId }: MomoPaymentParams, { rejectWithValue }) => {
try {
const tokenFromStorage = localStorage.getItem('token') || '';
const response = await axios.post(
`${import.meta.env.VITE_BASE_URL}/buyer/momoPay`,

{
momoNumber,
orderId,
},
{
headers: {
Authorization: `Bearer ${tokenFromStorage}`,
},
}
);
showSuccessToast(response.data.message);
return response.data;
} catch (error) {
if (axios.isAxiosError(error)) {
// const errorMessage = error.response?.data?.message || 'Payment failed';
// showErrorToast(errorMessage);
return rejectWithValue(error.response?.data || 'Payment failed');
}
console.error('Unexpected error:', error);
showErrorToast('Payment failed');
return rejectWithValue('Payment failed');
}
}
);


export const getOrders = createAsyncThunk('order/get', async () => {
const tokenFromStorage = localStorage.getItem('token') || '';
const response = await axios.get(`${baseUrl}/checkout/getall-order`, {
Expand All @@ -70,7 +111,7 @@ export const getOrders = createAsyncThunk('order/get', async () => {
},
});
return {
...response.data[0],
...response.data,
deliveryInfo: JSON.parse(response.data[0].deliveryInfo),
};
});
Expand All @@ -91,6 +132,7 @@ export const makePayment = createAsyncThunk(
},
}
);

return response.data;
}
);
Expand Down
2 changes: 2 additions & 0 deletions src/routes/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import Cart from '@/components/Cart/Cart';
import Seller from '@/pages/Seller';
import CheckoutPage from '@/pages/Checkout';
import Aboutus from '@/components/home/Aboutus';
import OrderCompletion from '@/pages/OrderCompletion';

function AppRoutes() {
return (
Expand All @@ -44,6 +45,7 @@ function AppRoutes() {
<Route path="wishlist" element={<Wishlist />} />
<Route path="/cart" element={<Cart />} />
<Route path="/checkout" element={<CheckoutPage />} />
<Route path="/order-completion" element={<OrderCompletion />} />
</Route>
<Route path="/signup" element={<SignUp />} />
<Route path="/signIn" element={<SignIn />} />
Expand Down

0 comments on commit c8d62a3

Please sign in to comment.