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

Adds validations for user login, wallet and enough money #186

Merged
merged 16 commits into from
May 14, 2021
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 36 additions & 5 deletions components/stock-card/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,50 @@ import path from 'path';
import Image from 'next/image';
import StockOperation from '@components/stock-operation';

export const Card = ({ stock }) => {
export const Card = ({ stock, operationType }) => {
const {
id,
stockId,
name,
stockName,
price,
quantity,
initialStockValue,
} = stock;

const finalPrice = operationType == 'BUY' ? price : initialStockValue;
const finalName = operationType == 'BUY' ? name : stockName;
const finalId = operationType == 'BUY' ? id : stockId;

return (
<div className="stock-card">
<Image
src={path.join('/assets', 'stocks.jpg')}
alt={stock.name}
alt={stock.name || stock.stockName}
width={100}
height={100}
objectFit="cover"
layout="fixed"
/>

<div className="stock-card__content">
<p className="stock-card-product-name">{stock.name}</p>
<p className="stock-card-product-price">{stock.price}</p>
<p className="stock-card-product-name">
{stock.name || stock.stockName}
</p>
<p className="stock-card-product-price">
{stock.price || stock.initialStockValue} 💲
</p>
<p className="stock-card-product-quantity">
{' '}
Quantity : {stock.quantity}
</p>
<div>
<StockOperation stock={stock} />
<StockOperation
stockId={finalId}
name={finalName}
price={finalPrice}
availableQty={quantity}
/>
</div>
</div>
<style jsx>
Expand Down Expand Up @@ -67,6 +94,10 @@ export const Card = ({ stock }) => {
font-size: 1.3em;
color: #e30062;
}
.stock-card-product-quantity {
font-size: 1.3em;
color: #540075;
}
`}
</style>
</div>
Expand Down
113 changes: 85 additions & 28 deletions components/stock-operation-modal/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import React, { useState } from 'react';
import React, { useState, useEffect } from 'react';
import styles from '../stock-operation-modal/stock-operation.module.css';
import fetchSelfDetails from '../../utils/fetchSelfDetails';
import fetchData from '../../utils/fetchData';

const BASE_API_URL = process.env.NEXT_PUBLIC_BASE_API_URL;

const StockOperationModal = (props) => {
const {
Expand All @@ -9,45 +13,98 @@ const StockOperationModal = (props) => {
showModal,
transactionType,
stockId,
availableQty,
} = props;

const [quantity, setQuantity] = useState('');
const [isUserLoggedIn, setIsUserLoggedIn] = useState(false);
const [userMoney, setUserMoney] = useState(0);

const validateQuantity = (quantity) => {
if (quantity > availableQty) {
alert(`You can only ${transactionType} ${availableQty} stocks`);
} else {
setQuantity(quantity);
}
};

const closeModal = () => {
showModal((prev) => !prev);
setQuantity('');
};
const submitHandler = () => {
const body = {
tradeType: transactionType,
stockName: nameOfStock,
stockId,
quantity,
listedPrice: listedPriceOfStock,
totalPrice: quantity * listedPriceOfStock,
};

fetch('https://api.realdevsquad.com/trade/stock/new/self', {
useEffect(() => {
getUserWallet();
}, []);

const getUserWallet = async () => {
const response = await fetchData(`${BASE_API_URL}/wallet`, 'GET', {
credentials: 'include',
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(body),
})
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error(response.statusText);
});
const { wallet } = await response.json();
if (Object.keys(wallet).length === 0) return setUserMoney(0);
const {
currencies: { dinero },
} = wallet;
setUserMoney(dinero);
};

useEffect(() => {
fetchSelfDetails()
.then((res) => {
if (res.status === 200) {
setIsUserLoggedIn(true);
}
})
.then((data) =>
alert(`Trading Successful! Your balance is ${data.userBalance} Dineros`)
)
.catch((err) => {
alert(err.message);
console.error('User is not logged in', err);
});
}, []);

const submitHandler = () => {
if (!isUserLoggedIn) {
alert('Please log in to continue trading');
} else if (userMoney === 0) {
alert('You do not have a wallet!');
} else if (
transactionType == 'BUY' &&
parseInt(quantity * listedPriceOfStock) > parseInt(userMoney)
) {
alert('You do not have enough money!');
} else {
const body = {
tradeType: transactionType,
stockName: nameOfStock,
stockId,
quantity,
listedPrice: listedPriceOfStock,
totalPrice: quantity * listedPriceOfStock,
};

fetch(`${BASE_API_URL}/trade/stock/new/self`, {
credentials: 'include',
method: 'POST',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify(body),
})
.then((response) => {
if (response.status === 200) {
return response.json();
} else {
throw new Error(response.statusText);
}
})
.then((data) =>
alert(
`Trading Successful! Your balance is ${data.userBalance} Dineros`
)
)
.catch((err) => {
alert(err.message);
});
}
};

return (
Expand Down Expand Up @@ -92,9 +149,9 @@ const StockOperationModal = (props) => {
type="number"
name="quantity"
id="quantity"
min="1"
min={1}
value={quantity}
onChange={(e) => setQuantity(e.target.value)}
onChange={(e) => validateQuantity(+e.target.value)}
/>
<label className={styles.label} htmlFor="total-price">
Total Price
Expand Down
37 changes: 22 additions & 15 deletions components/stock-operation/index.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
import StockOperationModal from '@components/stock-operation-modal';
import React, { useState } from 'react';
import styles from '../../styles/Home.module.css';
import { useRouter } from 'next/router';

const StockOperation = (props) => {
const { id, name, price } = props.stock;
const { stockId, name, price, availableQty } = props;
const [modal, showModal] = useState(false);
const [transactionType, setTransactionType] = useState('');
const setTransaction = (operation) => {
setTransactionType(operation);
showModal((prev) => !prev);
};

const router = useRouter();

return (
<div className={styles.buttonWrapper}>
<div
className={`${styles.button} ${styles.greenButton}`}
onClick={() => setTransaction('BUY')}
>
BUY
</div>
{/* DISABLED UNTIL SELL #BUG ON BACKEND IS FIXED
<div
className={`${styles.button} ${styles.redButton}`}
onClick={() => setTransaction('SELL')}
>
SELL
</div> */}
{router.pathname == '/trading' && (
<div
className={`${styles.button} ${styles.greenButton}`}
onClick={() => setTransaction('BUY')}
>
BUY
</div>
)}
{router.pathname == '/trading/sell' && (
<div
className={`${styles.button} ${styles.redButton}`}
onClick={() => setTransaction('SELL')}
>
SELL
</div>
)}
<StockOperationModal
nameOfStock={name}
listedPriceOfStock={price}
availableQty={availableQty}
modal={modal}
showModal={showModal}
transactionType={transactionType}
stockId={id}
stockId={stockId}
/>
</div>
);
Expand Down
2 changes: 2 additions & 0 deletions constants/trading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const GET_STOCKS = 'GET_STOCKS';
export const GET_USER_STOCKS = 'GET_USER_STOCKS';
14 changes: 13 additions & 1 deletion pages/trading/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { Card } from '@components/stock-card';
import { Footer } from '@components/footer';
import personData from '../../mock/person.json';
import NavBar from '@components/NavBar';
import Link from 'next/link';
import { getStocks } from '../../redux/action';
import styles from '../../styles/Home.module.css';

const Invest = () => {
const stocks = useSelector((state) => state.stocksDetails.stocks);
Expand All @@ -18,6 +20,7 @@ const Invest = () => {

fetchData();
}, []);

return (
<>
<NavBar personData={personData} />
Expand All @@ -26,9 +29,18 @@ const Invest = () => {
<div className="content">
<div className="shoppinglist-container">
{stocks.map((itemName) => (
<Card key={itemName.id} stock={itemName} />
<Card
key={itemName.id}
stock={itemName}
operationType={'BUY'}
/>
))}
</div>
<div>
<Link href="/trading/sell">
<div className={`${styles.trade}`}>Sell Stocks</div>
</Link>
</div>
</div>
<Footer />
</div>
Expand Down