How do I properly update my Postgres Database in Node.js? - node.js

The Problem: syntax error at or near "$"
The Context: My App does two CRUD operations - Update & Read Data from a Postgres database. It successfully reads data from the database and displays on the frontend. However, it fails to update the database when I query it to do so. It throws an error that 'syntax error at or near "$"'.
So far, I have failed to debug the error successfully.
The Stacks: Postgres, Node.js, React
The Query (BackEnd):
//burrow a book
app.post("/books/:id", async (req, res) => {
try {
const { id } = req.params;
const copies = await pool.query('SELECT copies FROM books WHERE book_id = $id', [id]);
const stock = copies - 1;
const updateBook = await pool.query("UPDATE books SET copies = $1 WHERE book_id = $2", [stock, id]);
const allBooks = await pool.query("SELECT * FROM books");
res.json(allBooks.rows);
} catch (err) {
console.error(err.message);
}
});
The Function(FrontEnd):
async function burrowbook(id) {
try {
const res = await fetch(`http://localhost:5000/books/${id}` , {method: "POST"});
console.log(res);
// setbooks(jsonData);
// console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
The Full React Component(FrontEnd):
import React, { Fragment, useEffect, useState } from 'react';
const ListBooks = () => {
const [books, setbooks] = useState([]);
async function burrowbook(id) {
try {
const res = await fetch(`http://localhost:5000/books/${id}` , {method: "POST"});
console.log(res);
// setbooks(jsonData);
// console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
const getBooks = async () => {
try {
const response = await fetch("http://localhost:5000/books");
const jsonData = await response.json();
setbooks(jsonData);
// console.log(jsonData);
} catch (err) {
console.error(err.message);
}
}
useEffect(() => {
getBooks();
}, []);
return (<Fragment>
<div class="container ">
<h1 class="text-center mt-5">Wakanda Library</h1>
</div>
<table class="table table-hover table-dark text-center mt-5">
<thead>
<tr>
<th scope="col">Book ID</th>
<th scope="col">Title</th>
<th scope="col">Author</th>
<th scope="col">Year</th>
<th scope="col">Stock</th>
<th scope="col">Burrow</th>
<th scope="col">Return</th>
</tr>
</thead>
<tbody>
{books.map(book => (
<tr key={book.book_id}>
<td>{book.book_id} </td>
<td>{book.title} </td>
<td>{book.author} </td>
<td>{book.publish_year} </td>
<td>{book.copies} </td>
<td><button
className="btn btn-success btn-circle btn-md"
onClick={() => burrowbook(book.book_id)}
>
Burrow
</button></td>
<td><button
className="btn btn-primary btn-circle btn-md"
// onClick={() => returnBook(book.book_id)}
>
Return
</button></td>
</tr>
))}
</tbody>
</table>
</Fragment>);
};
export default ListBooks;
The Full index.js script(BackEnd):
const express = require("express");
const app = express();
const cors = require('cors');
const pool = require('./db');
//middleware
app.use(cors());
app.use(express.json()); //req.body
//ROUTES//
//login user
//register user
//list of books in library
app.get("/books", async (req, res) => {
try {
const allBooks = await pool.query("SELECT * FROM books");
res.json(allBooks.rows);
} catch (err) {
console.error(err.message);
}
});
//burrow a book
app.post("/books/:id", async (req, res) => {
try {
const { id } = req.params;
console.log(id);
const copies = await pool.query('SELECT copies FROM books WHERE book_id = $id', [id]);
console.log("b");
const stock = copies - 1;
console.log("c")
const updateBook = await pool.query("UPDATE books SET copies = $1 WHERE book_id = $2", [stock, id]);
console.log("d")
const allBooks = await pool.query("SELECT * FROM books");
console.log("heee")
res.json(allBooks.rows);
} catch (err) {
console.error(err.message);
}
});
//return a book
app.put("/booksreturn/:id", async (req, res) => {
try {
const { id } = req.params;
const { copies } = req.body;
const returnBook = await pool.query(
"UPDATE books SET copies = $copies WHERE book_id = $id",
[copies = parseFloat(copies) + 1, id]
);
res.json("Book was returned!");
} catch (err) {
console.error(err.message);
}
});
//list of books in users possession
app.listen(5000, () => {
console.log("Baba... server don start on top port 5000.")
});

Related

React+Node webpage - Update endpoint throws 404 error

I have setup a webpage to search a number via user input and if it's available in the SQL Server database, 2 text boxes would show up with the data using AXIOS GET endpoint. Then I'm trying to get those ID's of the data rows and if the user needs to UPDATE it, then UPDATE it via AXIOS PUT endpoint. The issue is once user clicks the UPDATE button it throws an error PUT http://localhost:5000/api/customerOrder/[object%20Object],[object%20Object] 404 (Not Found)
Here's what I've tried
Server endpoints :
dboperations.js
var config = require('./dbconfig');
const sql = require('mssql');
async function getallcustomerOrders(){
try{
let pool = await sql.connect(config);
let orders = await pool.request()
.query("SELECT * FROM [100].[dbo].[OELINCMT_SQL] order by ID desc");
return orders.recordsets;
}
catch (error){
console.log(error);
}
}
async function getcustomerOrders(orderNumber){
try{
let pool = await sql.connect(config);
let orders = await pool.request()
.input('input_parameter', sql.NChar, orderNumber)
.query("SELECT ID,cmt FROM [100].[dbo].[OELINCMT_SQL] where LTRIM(ord_no) = LTRIM(#input_parameter)");
return orders.recordsets;
}
catch (error){
console.log(error);
}
}
async function updateComments(ID){
try {
let pool = await sql.connect(config);
let orders = await pool.request()
.input('ID', sql.NChar, ID)
.query(`SELECT ID,cmt FROM [100].[dbo].[OELINCMT_SQL] WHERE ID = #ID`);
let order = orders.recordset.length ? orders.recordset[0] : null;
if (order) {
await pool.request()
.input('cmt', req.body.cmt)
.query(`UPDATE [100].[dbo].[OELINCMT_SQL] SET cmt = #cmt WHERE ID = #ID;`);
order = { ...order, ...req.body };
res.json(order);
} else {
res.status(404).json({
message: 'Record not found'
});
}
} catch (error) {
res.status(500).json(error);
}
}
module.exports = {
getallcustomerOrders : getallcustomerOrders,
getcustomerOrders : getcustomerOrders,
updateComments : updateComments
}
api.js
var Db = require('./dboperations');
var dboperations = require('./dboperations');
var express = require('express');
var bodyParser = require('body-parser');
var cors = require('cors');
const { request, response } = require('express');
var app = express();
var router = express.Router();
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.use('/api', router);
router.use((request,response,next)=> {
console.log('middleware');
next();
})
router.route('/customerOrder').get((request,response)=>{
dboperations.getallcustomerOrders().then(result => {
response.json(result[0]);
console.log(result[0]);
})
})
router.route('/customerOrder/:orderNumber').get((request,response)=>{
dboperations.getcustomerOrders(request.params.orderNumber).then(result => {
response.json(result[0]);
console.log(result[0]);
})
})
router.route('customerOrder/:ID').put((request,response)=>{
dboperations.updateComments(request.params.ID).then(result => {
response.json(result[0]);
console.log(result[0]);
})
})
var port = process.env.PORT || 5000;
app.listen(port);
console.log('Customer Order API is running at ' + port);
dboperations.getcustomerOrders().then(result => {
console.log(result);
})
dboperations.getallcustomerOrders().then(result => {
console.log(result);
})
dboperations.updateComments().then(result => {
console.log(result);
})
Client :
EmailFaxDetails.js : This is the page user enters the number
import React, { useState,useEffect } from 'react'
import FetchOrderDetails from './FetchOrderDetails';
import axios from 'axios'
import '../App.css';
const EmailFaxDetails = () => {
const [orderNumber, setOrderNumber] = useState('');
const [id, setId] = useState([]);
const [isShown, setIsShown] = useState(false);
const url = `http://localhost:5000/api/customerOrder/${orderNumber}`
useEffect(() => {
axios.get(url)
.then(response => {
console.log(response.data)
setId(response.data)
})
.catch((err) => console.log(err));
}, [url]);
const handleChange = event => {
setOrderNumber(event.target.value);
console.log(event.target.value);
};
const handleClick = event => {
event.preventDefault();
setIsShown(true);
console.log(orderNumber);
}
return(
<div>
<br></br>
<br></br>
Order Number: <input placeholder="Order Number" type="text" id="message" name="message" onChange={handleChange} value={orderNumber} autoComplete="off" />
{id.map((idnum) => (
<div key={idnum.ID}>
<br></br>
ID : {idnum.ID}
</div>
))}
<button onClick={handleClick}>Search</button>
{isShown && <FetchOrderDetails ord_no={orderNumber} ID={id}/>}
</div>
)
}
export default EmailFaxDetails;
FetchOrderDetails.js : In this page user get's the output if the number is available in SQL server and let then UPDATE accordingly.
import React, { useEffect, useState } from 'react'
import axios from 'axios'
import '../App.css';
const FetchOrderDetails = ({ord_no,ID}) => {
const [data, setData] = useState([]);
const url = `http://localhost:5000/api/customerOrder/${ord_no}`
useEffect(() => {
axios.get(url)
.then(response => {
console.log(response.data)
setData(response.data)
})
.catch((err) => console.log(err));
}, [url]);
const url2 = `http://localhost:5000/api/customerOrder/${ID}`
const onSubmit = () => {
axios.put(url2)
.then((response) => {
if (response.status === 200) {
alert("Comment successfully updated");
ID.history.push(`/customerOrder/${ord_no}`);
} else Promise.reject();
})
.catch((err) => alert("Something went wrong"));
}
if(data) {
return(
<div>
{data.map((order) => (
<div key={order.ID}>
<br></br>
ID : {order.ID}
<br></br>
Email/Fax: <input defaultValue={order.cmt} placeholder="Sales Ack Email" id="salesAck" style={{width: "370px"}} />
</div>
))}
<div>
<br></br>
<br></br>
<button onClick={onSubmit}>Update</button>
</div>
</div>
)
}
return (
<h1>Something went wrong, please contact IT!</h1>
)
}
export default FetchOrderDetails;
What I suspect is the issue might be coming from the EmailFaxDetails.js page while trying to pass the ID since there are 2 ID's per number the user search. I might be wrong, if anyone could find the error and help making it correct I would really appreciate it.
I think problem here
setId(response.data)
You need retrieve only id and same for for orderid

My API data does not show up when calling from Nodejs

Below is my code to get data from an API and display on my server, the data comes in but does not display on the screen :
const express = require('express');
const router = express.Router();
const data = require('../data');
const peopleData = data.people;
router.get('/', async (req, res) => {
try {
const peopleList = await peopleData.getPeople();
res.render('people/user',{peopleList:peopleList});
} catch (e) {
res.status(500).send();
}
});
module.exports = router;
Data function:
require("util").inspect.defaultOptions.depth = null;
const axios = require('axios');
async function getPeople(){
const { data } = await axios.get('https://gist.githubusercontent.com/SwayamShah97/0f2cb53ddfae54eceea083d4aa8d0d65/raw/d7d89c672057cf7d33e10e558e001f33a10868b2/people.json');
return data; // this will be the array of people objects
}
module.exports = {
getPeople
}
Handlebars:
<div>
<table>
<tr>
<th>ID</th>
<th>First Name</th>
<th>Last Name</th>
</tr>
{{#each peopleList}}
<tr>
<td>{{id}}</td>
<td>{{firstName}}</td>
<td>{{lastName}}</td>
</tr>
{{/each}}
</table>
</div>
Not sure why nothing displays, I console log and the data comes in fine.

TypeError: users.map is not a function in Mern

I am trying to fetch data from backend, I want to load all data which are in database, when I load function then getting an error like "User.map is not a function", please let me know where am wrong.
User.js
import React, { useEffect, useState } from "react";
import { Link } from "react-router-dom";
import { getUsers } from "./apis";
const UserData = () => {
const [users, setUser] = useState([]);
useEffect(() => {
AllUsers();
}, []);
const AllUsers = async () => {
const response = await getUsers();
console.log(response.data);
setUser(response.data ? response.data : []);
};
return (
<div>
<div className="container">
<table className="table table-hover table-bordered mt-5">
<thead>
<tr>
{/* <th scope="col">No</th> */}
<th scope="col">Title</th>
<th scope="col">Details</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{users.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
};
Api.js
I have added api.js file please check it , and let me know where am wrong
export default UserData;
import Axios from "axios";
const url = "http://localhost:3000/";
export const getUsers = async (id) => {
id = id || "";
return await Axios.get(`${url}/${id}`);
};
export const deleteUser = async (id) => {
return await Axios.delete(`${url}/${id}`);
};
You can use Optional chaining (?.) for check the data is available or not. Because while API's is calling data not set in your state. It's might be a undefined.
const adventurer = {
name: 'Alice',
cat: {
name: 'Dinah'
}
};
const dogName = adventurer.dog?.name;
console.log(dogName);
In your case do with this way.
{users?.map((user, index) => (
<tr key={index}>
<th scope="row">{user.id}</th>
<td>{user.title}</td>
<td>{user.description}</td>
</tr>
))}
import Axios from "axios";
const url = "http://localhost:3000/";
export const getUsers = async (id) => {
id = id || "";
return await Axios.get(`${url}/${id}`);
};
export const deleteUser = async (id) => {
return await Axios.delete(`${url}/${id}`);
};

Change state and update it in the database

I'm working on a web app to track fruits vendor stock using React.js, MongoDB, Node.js, and Express. I called my database endpoints to render the data in the table. Now I try to increment and decrement the stock amount using a button, but when I try to set the new state, it doesn't work. I try to change the state by clicking, then update the new state in the database. Any advice?
FruitTable component:
import Reac, { Component } from 'react';
import * as ReactBootstrap from 'react-bootstrap';
import axios from 'axios';
import Button from 'react-bootstrap/Button';
class FruitTable extends Component {
constructor(props) {
super(props)
this.state = {
fruits: []
}
this.handleClick = this.handleClick.bind(this)
}
componentDidMount() {
axios.get('http://localhost:5000/fruits/')
.then(res => {
this.setState({
fruits: res.data
});
})
.catch((error) => {
console.log(error)
})
}
handleClick = () => {
const fruits = [...this.state.fruits]
this.setState({fruits: this.state.fruits[1] +1})
}
render() {
return(
<div>
<h1>Fruit Vendor Stock</h1>
<ReactBootstrap.Table striped bordered hover size="sm">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Stock</th>
<th>Price</th>
<th>Add/Reomve</th>
</tr>
</thead>
<tbody>
{
this.state.fruits.map((fruit, index) => (
<tr>
<th scope="row">{index + 1}</th>
<td>{fruit.name}</td>
<td>{fruit.stock}</td>
<td>{fruit.price}</td>
<td>
<div className="mb2">
<Button className="btn btn-primary btn-sm"
onClick={this.handleClick}
>Add</Button>{' '}
<Button className="btn btn-danger btn-sm"
>Remove</Button>
</div>
</td>
</tr>
))
}
</tbody>
</ReactBootstrap.Table>
</div>
)
};
}
export default FruitTable;
FruitsData.model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const fruits = new Schema({
name: { type: String, required: true },
stock: { type: Number, required: true },
price: { type: Number, required: true },
}, {
});
const Fruits = mongoose.model('Fruits', fruits);
module.exports = Fruits;
-Routes:
const router = require('express').Router();
let Fruit = require('../models/fruit_data');
router.route('/').get((req, res) => {
Fruit.find()
.then(fruits => res.json(fruits))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/add').post((req, res) => {
const name = req.body.name;
const stock = Number(req.body.stock);
const price = Number(req.body.price);
const newFruit = new Fruit({
name,
stock,
price,
});
newFruit.save()
.then(() => res.json('Fruit has been added!'))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/:id').get((req, res) => {
Fruit.findById(req.params.id)
.then(Fruit => res.json(Fruit))
.catch(err => res.status(400).json('Error: ' + err));
});
router.route('/:id').delete((req, res) => {
Fruit.findByIdAndDelete(req.params.id)
.then(() => res.json('Fruit has deleted.'))
.catch(err => res.status(400).json("Error: " + err));
});
router.route('/update/:id').put((req, res, next) => {
Fruit.findByIdAndUpdate(req.params.id, {
$set: req.body
}, (error, data) => {
if(error) {
return next(error);
console.log(error)
} else {
res.json(data)
console.log('Stock has been updated')
}
})
})
module.exports = router;
-Server.js:
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const mongoose = require('mongoose');
require('dotenv').config();
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.json());
const uri = process.env.ATLAS_URI;
mongoose.connect(uri, { useNewUrlParser: true });
const connection = mongoose.connection;
connection.once('open', () => {
console.log("MongoDb database connection established successfully!!")
})
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const fruitsRouter = require('./routes/fruit');
app.use('/fruits', fruitsRouter);
app.listen(port, () => {
console.log(`Server is running on port: ${port}`);
})
-App.js:
import "./App.css";
import React, { Component, useState, useEffect } from "react";
import FruitTable from "./Components/fruitTable";
import "bootstrap/dist/css/bootstrap.min.css";
import { sendEmail } from "./service/emailService";
import axios from 'axios';
function App() {
return (
<div className="App">
<FruitTable />
</div>
);
}
export default App;
The state update in handleClick isn't correct, it is taking the 1th element value, adding 1 to it, and setting this as the this.state.fruits state value. This breaks the state invariant of fruits being an array. This is likely the "crash" you are seeing as a non-array value is attempted to be mapped.
handleClick = () => {
const fruits = [...this.state.fruits]
this.setState({
fruits: this.state.fruits[1] +1 // <-- mutates state invariant!!
})
}
The code also isn't passing a reference to which index or fruit it is trying to update.
According to your schema the fruit items have 3 properties, name, stock, and price. For this solution I'll assume that name is sufficiently unique for identification purposes and that you are incrementing/decrementing the stock quantity.
handleClick = (name, addQuantity = 1) => () => {
this.setState(prevState => ({
fruits: prevState.fruits.map(fruit =>
fruit.name === name
? { ...fruit, stock: fruit.stock + addQuantity}
: fruit
)
}));
}
Now you need to pass the currently mapped fruit item's name property to the handler when mapping.
{this.state.fruits.map((fruit, index) => (
<tr key={fruit.name}>
<th scope="row">{index + 1}</th>
<td>{fruit.name}</td>
<td>{fruit.stock}</td>
<td>{fruit.price}</td>
<td>
<div className="mb2">
<Button
className="btn btn-primary btn-sm"
onClick={this.handleClick(item.name, 1)} // <-- add one
>
Add
</Button>{' '}
<Button
className="btn btn-danger btn-sm"
onClick={this.handleClick(item.name, -1)} // remove one
>
Remove
</Button>
</div>
</td>
</tr>
))}

Connecting two tables with Node.Js Express

I've looked around on the web for solutions but there doesn't seem to be an answer relevant to mine. So I would like some help on this, please. Here I have two tables I need to connect and list on the React file. game table and users table, at the moment I am only able to display game table.
Server/index.js
const express = require("express");
const app = express();
const cors = require("cors");
const pool = require("./db");
//middleware
app.use(cors());
app.use(express.json()); //req.body
app.get("/af", async (req, res) => {
try {
const allTodos = await pool.query("SELECT game.*, users.* FROM users INNER JOIN game ON users.game_code = game.game_code; ");
res.json(allTodos.rows);
} catch (err) {
console.error(err.message);
}
});
Client/List.js
const List = () => {
const [af, setAF] = useState([]);
const getTodos = async() => {
try{
const response = await fetch("http://localhost:5000/af");
const jsonData = await response.json();
setAF(jsonData);
}catch(err){
console.error(err.message);
}
}
useEffect(() => {
getTodos();
}, []);
return(
<Fragment>
{" "}
<table className="table mt-5 text-center">
<thead>
<tr>
<th>game_code</th>
<th>user_code</th>
</tr>
</thead>
<tbody>
{af.map(game => (
<tr key = {game.game}>
<td>{game.game_code}</td>
<td>{game.game_location}</td>
))}
</tbody>
</table>
</Fragment>
export default List;

Resources