You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
5.5 KiB
JavaScript

const express = require("express");
const app = express();
const cors = require("cors");
const mongoose = require("mongoose");
require("dotenv").config();
const PORT = process.env.PORT || 16749;
const MONGODB_URI = process.env.MONGODB_URI || "";
mongoose.connect(MONGODB_URI, {
// @ts-ignore
useNewUrlParser: true,
useUnifiedTopology: true,
});
const exerciseLogsSchema = new mongoose.Schema({
username: { type: String, required: true },
log: [
{
description: { type: String, required: true },
duration: { type: Number, required: true },
date: { type: Number, required: true },
},
],
});
const exerciseLogs = mongoose.model("ExerciseLogs", exerciseLogsSchema);
app.use(cors());
app.use(express.static("public"));
app.use(express.urlencoded({ extended: false }));
app.get("/", (req, res) => {
res.sendFile(__dirname + "/views/index.html");
});
app.post("/api/users", (req, res) => {
const username = req.body.username;
const exerciseLogsModel = new exerciseLogs({ username: username });
exerciseLogsModel
.save()
.then((user) => {
if (user) return res.json({ username: user.username, _id: user._id });
res.status(500);
res.json({ error: `Error creating user: ${username}` });
})
.catch((err) => {
res.status(500);
return res.json({
error: `Error type 2 while creating user: ${username}`,
});
});
});
app.get("/api/users", (req, res) => {
exerciseLogs
.find()
.select({ username: true, _id: true })
.exec()
.then((users) => {
res.json(users);
})
.catch((err) => {
res.sendStatus(500);
res.json({ error: `Error while retrieving users list:\n${err}` });
});
});
const getDateInTicks = (date) => {
// current time in tick if no date specified
if (!date) date = new Date().getTime();
// Convert String to Number if date specified in ticks
if (!Number.isNaN(Number(date))) date = Number(date);
// get date ticks from ticks Number or date String
date = new Date(date).getTime();
// date will be NaN if invalid date String is provided
return date;
};
app.post("/api/users/:_id/exercises", (req, res) => {
const _id = req.params._id;
const description = req.body.description;
const duration = Number(req.body.duration);
let date = getDateInTicks(req.body.date);
if (Number.isNaN(Number(date))) {
res.status(400);
return res.json({ error: `Input date: '${req.body.date}' is not valid` });
}
exerciseLogs
.findById(_id)
.select({ username: 1 })
.then((user) => {
if (user) {
exerciseLogs
.updateOne(
{ _id: _id },
{
$push: {
log: {
description: description,
duration: duration,
date: date,
},
},
},
{ runValidators: true }
)
.then((excLogs) => {
if (excLogs.modifiedCount) {
res.json({
_id: _id,
username: user.username,
description: description,
duration: duration,
date: new Date(date).toDateString(),
});
} else {
res.json(500);
res.json({
error: `Failed to add exercise logs to database:\n${excLogs}`,
});
}
})
.catch((err) => {
res.status(500);
res.json({
error: `Failed to add exercise logs to database:\n${err}`,
});
});
} else {
res.status(403);
res.json({ error: `No user with id: ${_id} exists` });
}
})
.catch((err) => {
res.status(500);
res.json({ error: "Failed to check user in database" });
});
});
app.get("/api/users/:_id/logs", (req, res) => {
const _id = req.params._id;
const limit = req.query.limit
? Math.trunc(Number(req.query.limit))
: Number.MAX_SAFE_INTEGER;
if (Number.isNaN(limit)) {
res.status(400);
return res.json({
error: `Query key 'limit''s value '${req.query.limit}' is not a number`,
});
}
const from = req.query.from ? getDateInTicks(req.query.from) : 0;
if (Number.isNaN(from)) {
res.status(400);
return res.json({
error: `Query key 'from''s value '${req.query.from}' is invalid for date`,
});
}
const to = req.query.to
? getDateInTicks(req.query.to)
: Number.MAX_SAFE_INTEGER;
if (Number.isNaN(to)) {
res.status(400);
return res.json({
error: `Query key 'to''s value '${req.query.to}' is invalid for date`,
});
}
exerciseLogs
.findById(_id)
.select({ "log._id": false, __v: false })
.then((excLogs) => {
if (excLogs) {
let excLogsJson = excLogs.toJSON();
excLogsJson.log = excLogsJson.log.filter(
(log) => log.date >= from && log.date <= to
);
excLogsJson.log.sort((a, b) => a.date - b.date);
excLogsJson.log = excLogsJson.log.slice(0, limit);
excLogsJson.count = excLogsJson.log.length;
excLogsJson.log = excLogsJson.log.map((log) => {
log.date = new Date(log.date).toDateString();
return log;
});
return res.json(excLogsJson);
}
res.status(400);
res.json({ error: `No user with id: '${_id}' exists` });
})
.catch((err) => {
res.status(400);
res.json({ error: `Input user id: '${_id}' is malformed` });
});
});
const listener = app.listen(PORT, () => {
console.log("Your app is listening on port " + listener.address().port);
});