today we create watchlist application using reactjs, nodejs.
Backend
config.js
{
"DB_URL": "mongodb+srv://user:password@cluster0.wb0iyao.mongodb.net/?retryWrites=true&w=majority"
}
default.js
module.exports.defaultSymbols=[
{
symbol:"SYY",
bid:"sp",
ask:"sp",
bidSize:3,
askSize:4,
volume:5,
description:"Fixed wrong interpolated variables with node-sass/Hugo"
},
{
symbol:"KJJ",
bid:"d",
ask:"d",
bidSize:3,
askSize:4,
volume:5,
description:"Fixed wrong interpolated variables with node-sass/Hugo"
},
{
symbol:"LLL",
bid:"ru",
ask:"ru",
bidSize:3,
askSize:4,
volume:5,
description:"Fixed wrong interpolated variables with node-sass/Hugo"
},
{
symbol:"NHD",
bid:"nd",
ask:"nd",
bidSize:2,
askSize:6,
volume:0,
description:"Fixed wrong interpolated variables with node-sass/Hugo"
},
{
symbol:"QWA",
bid:"ts",
ask:"ts",
bidSize:7,
askSize:4,
volume:1,
description:"Fixed wrong interpolated variables with node-sass/Hugo"
}
]
watchlist.controller.js
const WatchListModel = require("../models/WatchList")
module.exports.getWatchLists=async(req,res,next)=>{
try {
const watchLists=await WatchListModel.find({});
res.status(200).send(watchLists);
} catch (error) {
next(error)
}
}
module.exports.addSymbol=async(req,res,next)=>{
try {
const {symbol,bid,ask,bidSize,askSize,volume}=req.body;
const symbolObj={
symbol,
bid,
ask,
bidSize,
askSize,
volume
}
const watchList=await WatchListModel.findOneAndUpdate({
_id: req.params.id
},{
$push:{
symbols:symbolObj
}
},{new:true})
res.status(200).send(watchList);
} catch (error) {
next(error)
}
}
module.exports.updateSymbol=async(req,res,next)=>{
try {
const {symbolId,symbol,bid,ask,bidSize,askSize,volume,description}=req.body;
const symbolObj={
symbol,
bid,
ask,
bidSize,
askSize,
volume,description
}
let watchList=await WatchListModel.findOne({
_id: req.params.id
})
const index=watchList?.symbols.findIndex((symbol)=>symbol?._id?.toString()==symbolId);
watchList.symbols[index]=symbolObj;
watchList=await WatchListModel.findOneAndUpdate({_id: req.params.id},{$set:{
symbols:watchList?.symbols
}},{new:true})
res.status(200).send(watchList);
} catch (error) {
next(error)
}
}
module.exports.removeSymbol=async(req,res,next)=>{
try {
const {symbolId}=req.body
let watchList=await WatchListModel.findOne({
_id: req.params.id
})
const updatedSymbols=watchList?.symbols.filter((symbol)=>symbol?._id?.toString()!==symbolId);
watchList=await WatchListModel.findOneAndUpdate({_id: req.params.id},{$set:{
symbols:updatedSymbols
}},{new:true})
res.status(200).send(watchList);
} catch (error) {
next(error)
}
}
createDefaultwatchlist.middleware.js
const WatchListModel = require("../models/WatchList")
const symbols=require('../constants/defaults')
module.exports.createDefaultWatchList=async(req,res,next)=>{
try {
let watchList=await WatchListModel.findOne({});
console.log(watchList)
if(!watchList){
watchList=new WatchListModel({symbols:symbols.defaultSymbols});
watchList=await watchList.save();
next(watchList)
}
} catch (error) {
next(error)
}
}
error.middleware.js
module.exports=async(err,req,res)=>{
try {
if(err){
return res.status(500).send({status:500,message:err})
}
} catch (error) {
console.log(error.body);
}
}
validateObjectId.middleware.js
const mongoose= require("mongoose")
module.exports.validateObjectId=(req,res,next)=>{
try {
if(!mongoose.Types.ObjectId.isValid(req.params.id))
return res.status(400).send({message:"Invalid Id",status:400});
next();
} catch (error) {
next(error)
}
}
watchlist.model.js
const mongoose=require('mongoose');
const {Schema,model}=mongoose;
const watchlistSchema=new Schema({
symbols:[
{
symbol:{
type:String,
required: true,
index:true
},
bid:{
type:String,
default:''
},
ask:{
type:String,
default:''
},
bidSize:{
type:Number,
default:null
},
askSize:{
type:Number,
default:null
},
volume:{
type:Number,
default:null
},
description:{
type:String,
default: ""
}
}
]
})
const WatchListModel=model('watchlist',watchlistSchema);
module.exports=WatchListModel;
watchlist.route.js
const express=require('express');
const { createDefaultWatchList } = require("../middlewares/createDefaultWatchList.middleware");
const WatchListModel = require("../models/WatchList.model");
const router=express.Router();
const symbols=require('../constants/defaults');
const { addSymbol, getWatchLists, removeSymbol, updateSymbol } = require("../controllers/watchlist.controller");
const { validateObjectId } = require('../middlewares/validateObjectId.middleware');
router.get('',getWatchLists);
router.post('/create-default',createDefaultWatchList);
router.post('/add-symbol/:id',validateObjectId,addSymbol);
router.patch('/update-symbol/:id',validateObjectId,updateSymbol);
router.patch('/remove-symbol/:id',validateObjectId,removeSymbol);
module.exports=router;
(async ()=>{
let watchList=await WatchListModel.findOne({});
if(!watchList){
watchList=new WatchListModel({symbols:symbols.defaultSymbols});
watchList=await watchList.save();
console.log('default watch list created')
}
})()
connection.js
const mongoose=require('mongoose');
const config=require('config');
const DB_URL=config.get('DB_URL');
module.exports=mongoose.connect(DB_URL).then((conn)=>{
console.log(`Database connected on mongo server ${DB_URL}`);
}).catch((err)=>{
console.log(`Database Error ->: ${err}`);
})
app.js
const express=require('express');
const cors=require('cors');
require('./services/connection');
const errorMiddleware=require('./middlewares/error.middleware');
const watchListRouter=require('./routes/watchlist.route')
const app=express();
const PORT=process.env.PORT|| 8000;
//middlewares
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use(cors());
//routes of app
app.use('/api/v1/watchlist',watchListRouter);
//global error middleware
app.use(errorMiddleware)
app.listen(PORT,()=>{
console.log(`server is running on the port ${PORT}`)
})
package.json
{
"name": "backend",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node app.js",
"dev": "nodemon app.js"
},
"keywords": [],
"author": "Sandeep Jaiswal",
"license": "MIT",
"dependencies": {
"config": "^3.3.9",
"cors": "^2.8.5",
"express": "^4.18.2",
"mongoose": "^7.0.3"
}
}
Frontend
Header.js
import React from 'react'
const Header = () => {
return (
<div className="container-fluid bg-primary">
<nav className="navbar navbar-expand-lg bg-body-tertiary">
<div className="container-fluid">
<a className="navbar-brand text-white fw-bold" href="#">Watchlist</a>
</div>
</nav>
</div>
)
}
export default Header
UpdateWatch.js
import React, { useEffect, useState } from 'react'
const UpdateWatch = ({ data, updateSymbol }) => {
const [form, setForm] = useState({
symbolId: '', symbol: '', bid: '', ask: '', bidSize: null, askSize: null, volume: null, description: ''
})
useEffect(() => {
setForm({ symbolId: data?._id, symbol: data?.symbol,
bid: data?.bid, ask: data?.ask, bidSize: data?.bidSize||0,
askSize: data?.askSize||0 ,volume:data?.volume||0,description:data?.description});
}, [data?._id])
const change = (event) => {
const { name, value } = event.target;
setForm({ ...form, [name]: value })
}
const submit = () => {
updateSymbol(form);
setForm({
symbolId: '', symbol: '', bid: '', ask: '', bidSize: 0, askSize: 0, volume: 0, description: ''
})
}
return (
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="exampleModalLabel">Update Symbol</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Symbol:</label>
<input type="text" name="symbol" value={form.symbol} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Bid:</label>
<input type="text" name="bid" value={form.bid} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">ask:</label>
<input type="text" name="ask" value={form.ask} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Bid Size:</label>
<input type="number" name="bidSize" value={form.bidSize} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Ask Size:</label>
<input type="number" name="askSize" value={form.askSize} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Volume:</label>
<input type="number" name="volume" value={form.volume} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
<div class="mb-3">
<label for="recipient-name" class="col-form-label">Description:</label>
<input type="text" name="description" value={form.description} onChange={(e) => change(e)} class="form-control" id="recipient-name" />
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" onClick={() => submit()}> Update</button>
</div>
</div>
</div>
</div>
)
}
export default UpdateWatch
watchlist.js
import React, { useContext, useState } from 'react'
import WatchListContext from "../contexts/WatchListContext";
import { addSymbols, removeSymbols, updateSymbols } from "../services/watchList.service";
import UpdateWatch from "./common/UpdateWatch";
const WatchList = () => {
const [watchlist, setWatchlist] = useContext(WatchListContext);
const [updateObject,setUpdateObject]=useState({});
const [selectedSymbol,setSelectedSymbol]=useState([])
const addSymbol = async (event) => {
if (event.keyCode === 13) {
const res = await addSymbols(watchlist?._id, { symbol: event.target.value });
setWatchlist(res.data);
event.target.value = '';
}
}
const removeSymbol = async (symbolId) => {
const res = await removeSymbols(watchlist?._id, { symbolId });
setWatchlist(res.data);
}
const updateSymbol = async (data) => {
const res = await updateSymbols(watchlist?._id, data)
setWatchlist(res.data);
}
const toggleSelect=(symbol)=>{
const check=selectedSymbol.find(s=>s?._id===symbol?._id)
if(check){
let s=selectedSymbol.filter(sym=>sym?._id!==symbol?._id)
setSelectedSymbol(s);
}else{
let s=[...selectedSymbol,symbol]
setSelectedSymbol(s);
}
}
return (
<div>
<div className="p-4">
<div className="row">
<div className="col-3 fs-2">
Quote Details
</div>
<div className="col-9">
{selectedSymbol?.length ?
selectedSymbol?.map((s)=>(
<div key={s?._id}>
<h5>{s?.symbol}</h5>
<p>{s?.description}</p>
</div>
)
):"No Any row selected"}
</div>
</div>
<div className="border">
<div className="bg-light p-2 fw-bold">My Watchlist</div>
<table className="table table-bordered">
<thead>
<tr>
<th scope="col"></th>
<th scope="col">Bid</th>
<th scope="col">Ask</th>
<th scope="col">Bid Size</th>
<th scope="col">Ask Size</th>
<th scope="col">Volume</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{watchlist?.symbols.map((symbol) => (
<tr key={symbol?._id} onClick={()=>toggleSelect(symbol)} className={selectedSymbol?.find(s=>s?._id===symbol?._id)?'table-success':''}>
<th scope="row">{symbol?.symbol}</th>
<td>{symbol?.bid}</td>
<td>{symbol?.ask}</td>
<td>{symbol?.bidSize}</td>
<td>{symbol?.askSize}</td>
<td>{symbol?.volume}</td>
<td>
<div className="d-flex justify-content-around">
<button className="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@mdo" onClick={()=>setUpdateObject(symbol)}>Edit</button>
<button className="btn btn-danger" onClick={()=>removeSymbol(symbol?._id)}>Delete</button>
</div></td>
</tr>
))}
</tbody>
</table>
<div className="bg-light p-1 w-100" style={{ height: 40 }}>
Add Symbol <input className="ms-2 rounded" placeholder="" onKeyUp={(e) => addSymbol(e)} />
</div>
</div>
<UpdateWatch data={updateObject} updateSymbol={updateSymbol}/>
</div>
</div>
)
}
export default WatchList
watchlist.service.js
import { toast } from "react-toastify";
const { http, URL } = require("./http.service")
export const getWatchList = async () => {
try {
const res = await http.get(URL + '/watchlist');
return res;
} catch (error) {
handleError(error);
}
}
export const addSymbols = async (watchListId,payload) => {
try {
const res = await http.post(URL + '/watchlist/add-symbol/'+watchListId, payload);
return res;
} catch (error) {
handleError(error);
}
}
export const removeSymbols = async (watchListId, payload) => {
try {
const res = await http.patch(URL +'/watchlist/remove-symbol/' + watchListId, payload);
return res;
} catch (error) {
handleError(error);
}
}
export const updateSymbols = async (watchListId, payload) => {
try {
const res = await http.patch(URL +'/watchlist/update-symbol/' + watchListId, payload);
return res;
} catch (error) {
handleError(error);
}
}
export const isLogged = () => {
const token = localStorage.getItem('token');
return token ? true : false;
}
export const logoutUser = () => {
localStorage.removeItem('token');
}
export const getToken = () => {
return localStorage.getItem('token');
}
export const handleError = (error) => {
toast.error(error?.message)
}
export const setCredentials=(token)=>{
http.defaults.headers.common['x-auth-token'] = token;
}
App.js
import { useEffect, useState } from "react";
import './App.css';
import WatchList from "./components/WatchList";
import WatchListContext from "./contexts/WatchListContext";
import { getWatchList } from "./services/watchList.service";
import Header from "./components/common/Header";
import Loader from "./components/common/Loader";
function App() {
const [watchlist,setWatchlist]=useState();
const [isLoading,setIsLoading]=useState(false);
useEffect(()=>{
getWatchListData()
},[]);
const getWatchListData=async ()=>{
setIsLoading(true)
const result=await getWatchList();
if(result.status ===200 ){
setWatchlist(result?.data?.[0])
setIsLoading(false)
}else{
setIsLoading(false)
}
}
return (
<WatchListContext.Provider value={[watchlist,setWatchlist]}>
<Header />
{isLoading?<Loader />:<WatchList />}
</WatchListContext.Provider>
);
}
export default App;
this is not of the complete code if you have any doubt regarding this comment in this post. I give the answer as soon as possible. thank you for reading my post.
Top comments (0)