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

Popular posts from this blog

*********UPDATING THE FRONTEND*********

**************** EXTRACTING DATA FROM API **************