THE ROUTES
- IN FRONTEND, LOGGING IN AND SIGINING IN SHOULD REDIRECT TO DASHBOARD
- FROM THE DASHBOARD, WHATEVER THE NECESSARY OPERATION WANTED, DATA IS FETCHED FROM BACKEND
LOGIN.JS
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
import { ToastContainer, toast } from "react-toastify";
import "../Auth.css";
const Login = () => {
const navigate = useNavigate();
const [inputValue, setInputValue] = useState({
email: "",
password: "",
});
const { email, password } = inputValue;
const handleOnChange = (e) => {
const { name, value } = e.target;
setInputValue({
...inputValue,
[name]: value,
});
};
const handleError = (err) =>
toast.error(err, {
position: "bottom-left",
});
const handleSuccess = (msg) =>
toast.success(msg, {
position: "bottom-left",
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.post(
"https://tradeeasy.onrender.com/login",
{
...inputValue,
},
{ withCredentials: true }
);
console.log(data);
const { success, message } = data;
if (success) {
handleSuccess(message);
setTimeout(() => {
window.location.href = "https://tradeeasy-2.onrender.com";
}, 1000);
} else {
console.log(data.message);
handleError(message);
}
} catch (error) {
console.log(error);
}
setInputValue({
...inputValue,
email: "",
password: "",
});
};
return (
<div className="authWindow my-5">
<div className="form_container ">
<h2>Login Account</h2>
<form className="mb-5" onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
value={email}
placeholder="Enter your email"
onChange={handleOnChange}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
type="password"
name="password"
value={password}
placeholder="Enter your password"
onChange={handleOnChange}
/>
</div>
<button type="submit">Submit</button>
<span>
Don't have an account? <Link to={"/signup"}>Signup</Link>
</span>
</form>
<ToastContainer />
</div>
</div>
);
};
export default Login;
SIGNUP.JS
import React, { useState } from "react";
import { Link, useNavigate } from "react-router-dom";
import axios from "axios";
import { ToastContainer, toast } from "react-toastify";
import "../Auth.css";
const Signup = () => {
const navigate = useNavigate();
const [inputValue, setInputValue] = useState({
email: "",
password: "",
username: "",
});
const { email, password, username } = inputValue;
const handleOnChange = (e) => {
const { name, value } = e.target;
setInputValue({
...inputValue,
[name]: value,
});
};
const handleError = (err) =>
toast.error(err, {
position: "bottom-left",
});
const handleSuccess = (msg) =>
toast.success(msg, {
position: "bottom-right",
});
const handleSubmit = async (e) => {
e.preventDefault();
try {
const { data } = await axios.post(
"https://tradeeasy.onrender.com/signup",
{
...inputValue,
},
{ withCredentials: true }
);
console.log(data);
const { success, message } = data;
if (success) {
handleSuccess(message);
setTimeout(() => {
window.location.href = "https://tradeeasy-2.onrender.com";
}, 1000);
} else {
console.log(data.message);
handleError(message);
}
} catch (error) {
console.log(error);
}
setInputValue({
...inputValue,
email: "",
password: "",
username: "",
});
};
return (
<div className="authWindow">
<div className="form_container m-5 ">
<h2>Signup Account</h2>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">Email</label>
<input
type="email"
name="email"
value={email}
placeholder="Enter your email"
onChange={handleOnChange}
/>
</div>
<div>
<label htmlFor="email">Username</label>
<input
type="text"
name="username"
value={username}
placeholder="Enter your username"
onChange={handleOnChange}
/>
</div>
<div>
<label htmlFor="password">Password</label>
<input
type="password"
name="password"
value={password}
placeholder="Enter your password"
onChange={handleOnChange}
/>
</div>
<button type="submit">Submit</button>
<span>
Already have an account? <Link to={"/login"}>Login</Link>
</span>
</form>
<ToastContainer />
</div>
</div>
);
};
export default Signup;
DASHBOARD
MENU.JS
import React, { useState, useEffect } from "react";
import { Link } from "react-router-dom";
import { useNavigate } from "react-router-dom";
import { useCookies } from "react-cookie";
import axios from "axios";
export default function Menu() {
const [selectedMenu, setSelectedMenu] = useState(0);
const [isProfileDropdownOpen, setIsProfileDropdownOpen] = useState(false);
const navigate = useNavigate();
const [cookies, removeCookie] = useCookies([]);
const [username, setUsername] = useState("");
useEffect(() => {
const verifyCookie = async () => {
const { data } = await axios.get(
"https://tradeeasy.onrender.com/verifyUser",
{ withCredentials: true }
);
const { status, user } = data;
console.log(user);
setUsername(user);
if (!status) {
removeCookie("token");
window.location.href = "https://tradeeasy-frontend.onrender.com/login";
}
};
verifyCookie();
}, [cookies, navigate, removeCookie]);
const Logout = () => {
removeCookie("token");
window.location.href = "https://tradeeasy-frontend.onrender.com";;
};
const handleMenuClick = (index) => {
setSelectedMenu(index);
};
const handleDropdownOpen = () => {
setIsProfileDropdownOpen(!isProfileDropdownOpen);
};
const menuClass = "menu";
const activeMenuClass = "menu selected";
return (
<>
<div className="menu-container">
<img src="logo3.png" style={{ width: "5%" }} />
<div className="menus">
<ul>
<li>
<Link
style={{ textDecoration: "none" }}
to="/"
onClick={() => handleMenuClick(0)}
>
<p className={selectedMenu === 0 ? activeMenuClass : menuClass}>
Dashboard
</p>
</Link>
</li>
<li>
<Link
style={{ textDecoration: "none" }}
to="/orders"
onClick={() => handleMenuClick(1)}
>
<p className={selectedMenu === 1 ? activeMenuClass : menuClass}>
Orders
</p>
</Link>
</li>
<li>
<Link
style={{ textDecoration: "none" }}
to="/holdings"
onClick={() => handleMenuClick(2)}
>
<p className={selectedMenu === 2 ? activeMenuClass : menuClass}>
Holdings
</p>
</Link>
</li>
<li>
<Link
style={{ textDecoration: "none" }}
to="/positions"
onClick={() => handleMenuClick(3)}
>
<p className={selectedMenu === 3 ? activeMenuClass : menuClass}>
Positions
</p>
</Link>
</li>
<li>
<Link
style={{ textDecoration: "none" }}
to="/funds"
onClick={() => handleMenuClick(4)}
>
<p className={selectedMenu === 4 ? activeMenuClass : menuClass}>
Funds
</p>
</Link>
</li>
<li>
<Link
style={{ textDecoration: "none" }}
onClick={Logout}
>
<p className={selectedMenu === 4 ? activeMenuClass : menuClass}>
Logout
</p>
</Link>
</li>
</ul>
<hr />
<div className="profile">
<div className="avatar">ZU</div>
<div className="usename">
<p style={{color:"white"}}>{username}</p>
</div>
</div>
</div>
</div>
</>
);
}
HOLDINGS.JS
import React, { useState, useEffect } from "react";
import axios from "axios";
// import { holdings } from "../data/data";
import { AreaGraph } from "./AreaGraph";
export default function Holdings() {
const [allHoldings, setAllHoldings] = useState([]);
useEffect(() => {
axios
.get("https://tradeeasy.onrender.com/allHoldings", { withCredentials: true })
.then((res) => {
if (res.data) {
console.log(res.data);
setAllHoldings(res.data);
} else {
setAllHoldings([]);
}
})
.catch((error) => {
setAllHoldings([]);
console.error(error);
});
}, []);
const labels = allHoldings.map((subArray) => subArray["name"]);
const data = {
labels,
datasets: [
{
fill: true,
label: "Stock Price",
data: allHoldings.map((stock) => stock.price),
borderColor: "rgb(53, 235, 147)",
backgroundColor: "rgba(53, 235,147, 0.5)",
},
],
};
return (
<>
{allHoldings.length === 0 ? (
<p style={{ color: "white" }}>No holdings available!!</p>
) : (
<>
<h3 className="title">Holdings({allHoldings.length})</h3>
<div className="order-table">
<table>
<tr>
<th>Instrument</th>
<th>Qty.</th>
<th>Avg.cost</th>
<th>LTP</th>
<th>Cur.val</th>
<th>P&L</th>
<th>Net chg.</th>
<th>Day chg.</th>
</tr>
{allHoldings.map((stock, index) => {
const currValue = stock.qty * stock.price;
const isProfit = currValue - stock.avg * stock.qty >= 0.0;
const profitClass = isProfit ? "profit" : "loss";
const dayClass = stock.isLoss ? "loss" : "true";
return (
<>
<tr key={index}>
<td>{stock.name}</td>
<td>{stock.qty}</td>
<td>{stock.avg.toFixed(2)}</td>
<td>{stock.price.toFixed(2)}</td>
<td>{currValue.toFixed(2)}</td>
<td className={profitClass}>
{(currValue - stock.avg * stock.qty).toFixed(2)}
</td>
<td className={profitClass}>{stock.net}</td>
<td className={dayClass}>{stock.day}</td>
</tr>
</>
);
})}
</table>
</div>
<AreaGraph data={data} />
</>
)}
</>
);
}
ORDERS.JS
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import axios from "axios";
import "../index.css";
const Orders = () => {
const [allOrders, setAllOrders] = useState([]);
useEffect(() => {
axios
.get("https://tradeeasy.onrender.com/allOrders", { withCredentials: true })
.then((res) => {
if (res.data) {
setAllOrders(res.data);
} else {
setAllOrders([]);
}
})
.catch((err) => {
console.error(err);
setAllOrders([]);
});
});
return (
<>
{allOrders.length === 0 ? (
<h2 style={{color:"white"}}>No Orers Placed!</h2>
) : (
<>
<h3 className="title">Your Orders:({allOrders.length})</h3>
{allOrders.length === 0 ? (
<div className="orders">
<div className="no-orders">
<p>You haven't placed any orders today</p>
<Link to={"/"} className="btn">
Get started
</Link>
</div>
</div>
) : (
<div className="order-table">
<table>
<tr>
<th>Name</th>
<th>Qty.</th>
<th>Price</th>
<th>Mode</th>
</tr>
{allOrders.map((stock, index) => {
return (
<>
<tr key={index}>
<td>{stock.name}</td>
<td>{stock.qty}</td>
<td>{stock.price}</td>
<td>{stock.mode}</td>
</tr>
</>
);
})}
</table>
</div>
)}
</>
)}
</>
);
};
export default Orders;
POSITIONS.JS
import React, { useState, useEffect } from "react";
// import { positions } from "../data/data";
import axios from "axios";
import { ToastContainer } from "react-toastify";
const Positions = () => {
const [allPositions, setAllPositions] = useState([]);
useEffect(() => {
axios
.get("https://tradeeasy.onrender.com/allPositions", { withCredentials: true })
.then((res) => {
if (res.data) {
console.log(res.data);
setAllPositions(res.data);
} else {
setAllPositions([]);
}
})
.catch((err) => {
console.log(err);
setAllPositions([]);
});
}, []);
return (
<>
{allPositions.length === 0 ? (
<h2 style={{ color: "white" }}>No positions available!</h2>
) : (
<>
<h3 className="title">Positions({allPositions.length})</h3>
<div className="order-table">
<table>
<tr>
<th>Product</th>
<th>Instrument</th>
<th>Qty</th>
<th>Avg</th>
<th>LTP</th>
<th>P&L</th>
<th>Chg</th>
</tr>
{allPositions.map((stock, index) => {
const currValue = stock.qty * stock.price;
const isProfit = currValue - stock.avg * stock.qty >= 0.0;
const profitClass = isProfit ? "profit" : "loss";
const dayClass = stock.isLoss ? "loss" : "true";
return (
<>
<tr key={index}>
<td>{stock.product}</td>
<td>{stock.name}</td>
<td>{stock.qty}</td>
<td>{stock.avg.toFixed(2)}</td>
<td>{stock.price.toFixed(2)}</td>
<td className={profitClass}>
{(currValue - stock.avg * stock.qty).toFixed(2)}
</td>
<td className={dayClass}>{stock.day}</td>
</tr>
</>
);
})}
</table>
</div>
</>
)}
</>
);
};
export default Positions;
BUYACTIONWINDOW.JS
import React, { useState, useContext } from "react";
import { Link } from "react-router-dom";
import GeneralContext from "./GeneralContext";
import "./BuyActionWindow.css";
import axios from "axios";
import { toast } from "react-toastify";
export default function BuyActionWindow({ uid, price }) {
const [stockQty, setStockQty] = useState(1);
const [stockPrice, setStockPrice] = useState(price);
const generalContext = useContext(GeneralContext);
const handleBuyClick = () => {
axios.post(
"https://tradeeasy.onrender.com/newOrder",
{
name: uid,
qty: stockQty,
price: stockPrice,
mode: "BUY",
},
{ withCredentials: true }
);
console.log(uid);
toast.success("Buy order placed successfully.");
generalContext.closeBuyWindow();
};
const handleCancelClick = () => {
generalContext.closeBuyWindow();
};
return (
<div className="container" id="buy-window" draggable="true">
<div className="regular-order">
<div className="inputs">
<fieldset>
<legend>Qty.</legend>
<input
type="number"
name="qty"
id="qty"
onChange={(e) => {
setStockQty(e.target.value);
}}
value={stockQty}
/>
</fieldset>
<fieldset>
<legend>Price</legend>
<input
type="number"
name="price"
id="price"
step="0.05"
onChange={(e) => {
setStockPrice(e.target.value);
}}
value={stockPrice}
/>
</fieldset>
</div>
</div>
<div className="buttons">
{uid}
<br />
<span>Price:{stockPrice}</span>
<div>
<Link className="btn btn-blue" onClick={handleBuyClick}>
Buy
</Link>
<Link to="" className="btn btn-grey" onClick={handleCancelClick}>
Cancel
</Link>
</div>
</div>
</div>
);
}
SELLACTIONWINDOW.JS
import React, { useState, useContext } from "react";
import { Link } from "react-router-dom";
import GeneralContext from "./GeneralContext";
import "./BuyActionWindow.css";
import axios from "axios";
import { toast } from "react-toastify";
export default function SellActionWindow({ uid, price }) {
const [stockQty, setStockQty] = useState(1);
const [stockPrice, setStockPrice] = useState(price);
const generalContext = useContext(GeneralContext);
const handleSellClick = async () => {
try {
const response = await axios.post(
"https://tradeeasy.onrender.com/newOrder",
{
name: uid,
qty: stockQty,
price: stockPrice,
mode: "SELL",
},
{ withCredentials: true }
);
console.log(response);
try {
generalContext.closeSellWindow();
toast.success("Sell order placed successfully.");
} catch (e) {
console.error("Error after response:", e);
}
} catch (error) {
if (error.response && error.response.status === 400) {
toast.error(
error.response.data.message || "Not enough holdings to sell."
);
} else {
toast.error("Something went wrong. Please try again.");
}
console.error("Sell failed:", error);
}
};
const handleCancelClick = () => {
generalContext.closeSellWindow();
};
return (
<div className="container" id="buy-window" draggable="true">
<div className="regular-order">
<div className="inputs">
<fieldset>
<legend>Qty.</legend>
<input
type="number"
name="qty"
id="qty"
onChange={(e) => {
setStockQty(e.target.value);
}}
value={stockQty}
/>
</fieldset>
<fieldset>
<legend>Price</legend>
<input
type="number"
name="price"
id="price"
step="0.05"
onChange={(e) => {
setStockPrice(e.target.value);
}}
value={stockPrice}
/>
</fieldset>
</div>
</div>
<div className="buttons">
{uid}
<span>Selling starts at:{price}</span>
<div>
<Link className="btn btn-error" onClick={handleSellClick}>
Sell
</Link>
<Link to="" className="btn btn-grey" onClick={handleCancelClick}>
Cancel
</Link>
</div>
</div>
</div>
);
}
INDEX.JS (BACKEND)
require("dotenv").config();
const express = require("express");
const mongoose = require("mongoose");
const cors = require("cors");
const bodyParser = require("body-parser");
const PORT = process.env.PORT || 3002;
const url = process.env.MONGO_URL;
const key = process.env.API_KEY;
const axios = require("axios");
const { HoldingModel } = require("./Models/HoldingModel");
const { PositionModel } = require("./Models/PositionModel");
const { OrderModel } = require("./Models/OrderModel");
const app = express();
const cookieParser = require("cookie-parser");
const { createSecretToken } = require("./SecretToken");
const bcrypt = require("bcryptjs");
const { UserModel } = require("./Models/UserModel");
const { userVerification } = require("./Middlewares/userVerification");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(
cors({
origin: [
"http://localhost:3000",
"https://tradeeasy-2.onrender.com",
"https://tradeeasy-frontend.onrender.com",
],
methods: ["GET", "POST", "PUT", "DELETE"],
credentials: true,
})
);
app.use(bodyParser.json());
app.use(cookieParser());
// app.get("/addHoldings", async (req, res) => {
// let tempHoldings = [
// {
// name: "BHARTIARTL",
// qty: 2,
// avg: 538.05,
// price: 541.15,
// net: "+0.58%",
// day: "+2.99%",
// },
// {
// name: "HDFCBANK",
// qty: 2,
// avg: 1383.4,
// price: 1522.35,
// net: "+10.04%",
// day: "+0.11%",
// },
// {
// name: "HINDUNILVR",
// qty: 1,
// avg: 2335.85,
// price: 2417.4,
// net: "+3.49%",
// day: "+0.21%",
// },
// {
// name: "INFY",
// qty: 1,
// avg: 1350.5,
// price: 1555.45,
// net: "+15.18%",
// day: "-1.60%",
// isLoss: true,
// },
// {
// name: "ITC",
// qty: 5,
// avg: 202.0,
// price: 207.9,
// net: "+2.92%",
// day: "+0.80%",
// },
// {
// name: "KPITTECH",
// qty: 5,
// avg: 250.3,
// price: 266.45,
// net: "+6.45%",
// day: "+3.54%",
// },
// {
// name: "M&M",
// qty: 2,
// avg: 809.9,
// price: 779.8,
// net: "-3.72%",
// day: "-0.01%",
// isLoss: true,
// },
// {
// name: "RELIANCE",
// qty: 1,
// avg: 2193.7,
// price: 2112.4,
// net: "-3.71%",
// day: "+1.44%",
// },
// {
// name: "SBIN",
// qty: 4,
// avg: 324.35,
// price: 430.2,
// net: "+32.63%",
// day: "-0.34%",
// isLoss: true,
// },
// {
// name: "SGBMAY29",
// qty: 2,
// avg: 4727.0,
// price: 4719.0,
// net: "-0.17%",
// day: "+0.15%",
// },
// {
// name: "TATAPOWER",
// qty: 5,
// avg: 104.2,
// price: 124.15,
// net: "+19.15%",
// day: "-0.24%",
// isLoss: true,
// },
// {
// name: "TCS",
// qty: 1,
// avg: 3041.7,
// price: 3194.8,
// net: "+5.03%",
// day: "-0.25%",
// isLoss: true,
// },
// {
// name: "WIPRO",
// qty: 4,
// avg: 489.3,
// price: 577.75,
// net: "+18.08%",
// day: "+0.32%",
// },
// ];
// tempHoldings.forEach((item) => {
// let newHoldings = new HoldingModel({
// name: item.name,
// qty: item.qty,
// avg: item.avg,
// price: item.price,
// net: item.net,
// day: item.day,
// });
// newHoldings.save();
// });
// res.send("Done!");
// });
// app.get("/addPositions", async (req, res) => {
// let tempPositions = [
// {
// product: "CNC",
// name: "EVEREADY",
// qty: 2,
// avg: 316.27,
// price: 312.35,
// net: "+0.58%",
// day: "-1.24%",
// isLoss: true,
// },
// {
// product: "CNC",
// name: "JUBLFOOD",
// qty: 1,
// avg: 3124.75,
// price: 3082.65,
// net: "+10.04%",
// day: "-1.35%",
// isLoss: true,
// },
// ];
// tempPositions.forEach((item) => {
// let newPositions = new PositionModel({
// product: item.product,
// name: item.name,
// qty: item.qty,
// avg: item.avg,
// price: item.price,
// net: item.net,
// day: item.day,
// isLoss: item.isLoss,
// });
// newPositions.save();
// });
// res.send("Done!!")
// });
app.get("/allHoldings", userVerification, async (req, res) => {
const userId = req.user._id;
// console.log(userId);
const allHoldings = await HoldingModel.find({ userId });
// console.log(allHoldings);
res.json(allHoldings);
});
app.get("/allPositions", userVerification, async (req, res) => {
const userId = req.user._id;
let allPositions = await PositionModel.find({ userId });
res.json(allPositions);
});
app.get("/allOrders", userVerification, async (req, res) => {
const userId = req.user._id;
let allOrders = await OrderModel.find({ userId });
res.json(allOrders);
});
app.post("/newOrder", userVerification, async (req, res) => {
const userId = req.user._id;
console.log(userId);
const { name, qty, price, mode } = req.body;
try {
let newOrder = new OrderModel({
userId,
name,
qty,
price,
mode,
});
await newOrder.save();
//TO CALCULATE AVG,NET AND DAY
const { data } = await axios.get("https://finnhub.io/api/v1/quote", {
params: {
symbol: name,
token: key,
},
});
const currPrice = data.c;
const prevClose = data.pc;
const net = ((currPrice - price) * qty).toFixed(2);
const day = ((currPrice - prevClose) * qty).toFixed(2);
const existingHolding = await HoldingModel.findOne({
userId,
name,
});
const existingPosition = await PositionModel.findOne({ userId, name });
console.log(existingHolding);
console.log(existingPosition);
//CALCULATING AVG
if (mode === "BUY") {
//UPDATNG HOLDINGS
if (existingHolding) {
const totalQty = existingHolding.qty + qty;
const totalCost =
existingHolding.qty * existingHolding.avg + qty * price;
const newAvg = totalCost / totalQty;
existingHolding.qty = totalQty;
existingHolding.price = currPrice;
existingHolding.avg = newAvg;
existingHolding.net = ((currPrice - newAvg) * totalQty).toFixed(2);
existingHolding.day = ((currPrice - prevClose) * totalQty).toFixed(2);
await existingHolding.save();
//UPDATING POSITIONS
if (existingPosition) {
existingPosition.qty += qty;
const totalPositionCost =
existingPosition.avg * existingPosition.qty + qty * price;
const newPositionAvg =
totalPositionCost / (existingPosition.qty + qty);
existingPosition.avg = newPositionAvg;
existingPosition.price = currPrice;
existingPosition.net = (
(currPrice - newPositionAvg) *
existingPosition.qty
).toFixed(2);
existingPosition.day = (
(currPrice - prevClose) *
existingPosition.qty
).toFixed(2);
existingPosition.isLoss = existingPosition.net < 0;
await existingPosition.save();
}
} else {
const newHolding = new HoldingModel({
userId,
name,
qty,
avg: price,
price: currPrice,
net,
day,
});
await newHolding.save();
}
const newPosition = new PositionModel({
userId,
product: "MIs",
name,
qty,
avg: price,
price: currPrice,
net,
day,
isLoss: net < 0,
});
await newPosition.save();
} else if (mode === "SELL") {
//UPDATING HOLDINGS
if (!existingHolding || qty > existingHolding.qty) {
return res
.status(400)
.json({ message: "Not enough holdings to sell." });
}
if (qty === existingHolding.qty) {
await HoldingModel.deleteOne({ userId, name });
} else {
existingHolding.qty -= qty;
if (existingHolding.qty == 0) {
await existingHolding.deleteOne({ userId, name });
}
await existingHolding.save();
}
//UPDATING POSITIONS
if (!existingPosition) {
return res
.status(400)
.json({ message: "No position found to update." });
}
if (existingPosition) {
if (existingPosition.qty < qty) {
return res
.status(400)
.json({ message: "Not enough position quantity to sell." });
}
if (qty === existingPosition.qty) {
await PositionModel.deleteOne({ userId, name });
console.log("Position deleted");
} else {
existingPosition.qty -= qty;
existingPosition.net = (
(currPrice - existingPosition.avg) *
existingPosition.qty
).toFixed(2);
existingPosition.day = (
(currPrice - prevClose) *
existingPosition.qty
).toFixed(2);
existingPosition.isLoss = existingPosition.net < 0;
await existingPosition.save();
}
} else {
return res
.status(400)
.json({ message: "No existing position to update." });
}
console.log("position updated");
return res
.status(200)
.json({ message: "Sell order placed successfully." });
}
} catch (err) {
console.error(err);
res.status(500).json({ message: "Server error" });
}
});
app.post("/signup", async (req, res, next) => {
try {
console.log(req.body);
const { email, username, password, createdAt } = req.body;
if (!email || !password || !username) {
return res.json({ message: "All fields are required" });
}
const existingUser = await UserModel.findOne({ email });
if (existingUser) {
return res.json({ message: "User already exists" });
}
const user = await UserModel.create({
email,
password,
username,
createdAt,
});
const token = createSecretToken(user._id);
res.cookie("token", token, {
httpOnly: true,
secure: true, // ✅ REQUIRED on HTTPS (Render)
sameSite: "None", // ✅ Required for cross-origin cookies (frontend <-> backend)
});
res
.status(201)
.json({ message: "user signed in successfully!!", success: true, user });
next();
} catch (err) {
console.error(err);
}
});
app.post("/login", async (req, res, next) => {
try {
const { email, password } = req.body;
if (!email || !password) {
return res.json({ message: "All fields are required" });
}
const user = await UserModel.findOne({ email });
if (!user) {
return res.json({ message: "Incorrect password or email" });
}
const auth = await bcrypt.compare(password, user.password);
if (!auth) {
return res.json({ message: "Incorrect password or email" });
}
const token = createSecretToken(user._id);
res.cookie("token", token, {
httpOnly: true,
secure: true, // ✅ REQUIRED on HTTPS (Render)
sameSite: "None", // ✅ Required for cross-origin cookies (frontend <-> backend)
});
res
.status(201)
.json({ message: "User logged in successfully", success: true });
next();
} catch (error) {
console.error(error);
}
});
app.get("/getData/:symbol", async (req, res) => {
const rawSymbol = req.params.symbol.toUpperCase();
const fetchData = async (symbolVariant) => {
const { data } = await axios.get("https://finnhub.io/api/v1/quote", {
params: {
symbol: symbolVariant,
token: key,
},
});
const price = data.c.toFixed(2);
const prevPrice = data.pc.toFixed(2);
const percentChange = data.dp.toFixed(2);
const isDown = price < prevPrice;
console.log(data);
return {
name: rawSymbol,
price: price,
percent: `${isDown ? "" : "+"}${percentChange}%`,
isDown,
};
};
try {
let stockData = await fetchData(rawSymbol);
console.log(stockData);
if (!stockData) {
return res.status(404).json({ error: "Stock data not found" });
}
res.json(stockData);
} catch (err) {
console.error("Error fetching stock:", err);
res.status(500).json({ error: "Internal server error" });
}
});
app.get("/verifyUser", userVerification, (req, res) => {
try {
if (!req.user || !req.user.username) {
return res.json({ status: false, message: "User data missing!" });
}
res.json({ status: true, user: req.user.username });
} catch (err) {
console.log(err);
res.json({ status: false, message: "Error in verification" });
}
});
app.get("/", (req, res) => {
res.send("server working..");
});
app.listen(PORT, () => {
console.log(`port listening to ${PORT}`);
mongoose.connect(url).then(() => {
console.log("DB connected");
});
});
Comments
Post a Comment