Skip to content

Commit

Permalink
added project
Browse files Browse the repository at this point in the history
  • Loading branch information
milindkusahu committed Aug 19, 2024
1 parent ec1fef2 commit 57b6316
Show file tree
Hide file tree
Showing 57 changed files with 4,756 additions and 1 deletion.
40 changes: 40 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
.gitattributes merge=copy-merge
.gitignore merge=copy-merge
package.json merge=copy-merge
package-lock.json merge=copy-merge
pnpm-lock.yaml merge=copy-merge
setup.sh merge=copy-merge

# __CRIO__
__CRIO__/metadata.json merge=copy-merge

# backend/
backend/db/products.db merge=copy-merge
backend/routes/auth.js merge=copy-merge
backend/routes/cart.js merge=copy-merge
backend/routes/product.js merge=copy-merge
backend/routes/user.js merge=copy-merge
backend/package.json merge=copy-merge
backend/package-lock.json merge=copy-merge
backend/pnpm-lock.yaml merge=copy-merge

# public/
public/avatar.png merge=copy-merge
public/index.html merge=copy-merge
public/icon.svg merge=copy-merge
public/robots.txt merge=copy-merge
public/favicon.ico merge=copy-merge
public/manifest.json merge=copy-merge

# src/
src/setupTests.js merge=copy-merge


# src/__tests__
src/__tests__/Login.test.js merge=copy-merge
src/__tests__/App.test.js merge=copy-merge
src/__tests__/Register.test.js merge=copy-merge
src/__tests__/Cart.test.js merge=copy-merge
src/__tests__/Checkout.test.js merge=copy-merge
src/__tests__/Products.test.js merge=copy-merge
src/__tests__/ProductCard.test.js merge=copy-merge
29 changes: 29 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

testReport.json
.vercel

package-lock.json
pnpm-lock.yaml
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"liveServer.settings.port": 8083
}
1 change: 0 additions & 1 deletion README.md

This file was deleted.

5 changes: 5 additions & 0 deletions __CRIO__/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"module_id": "ME_QKART_FRONTEND_V2_MODULE_CHECKOUT",
"me_id": "ME_QKART_FRONTEND_V2"
}

4 changes: 4 additions & 0 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
node_modules/
db/users.db
yarn.lock
4 changes: 4 additions & 0 deletions backend/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"port": 8082,
"jwtSecret": "DeveloperSecretForEvaluationDoNotHardCodeLikeThisInRealLifeProductionApplications"
}
6 changes: 6 additions & 0 deletions backend/db.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const nedb = require('nedb');
const users = new nedb({ filename: 'db/users.db', autoload: true })
const products = new nedb({ filename: 'db/products.db', autoload: true });

module.exports.users = users
module.exports.products = products
12 changes: 12 additions & 0 deletions backend/db/products.db
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{"name":"UNIFACTOR Mens Running Shoes","category":"Fashion","cost":50,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/42d4d057-8704-4174-8d74-e5e9052677c6.png","_id":"BW0jAAeDJmlZCF8i"}
{"name":"YONEX Smash Badminton Racquet","category":"Sports","cost":100,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/64b930f7-3c82-4a29-a433-dbc6f1493578.png","_id":"KCRwjF7lN97HnEaY"}
{"name":"Tan Leatherette Weekender Duffle","category":"Fashion","cost":150,"rating":4,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/ff071a1c-1099-48f9-9b03-f858ccc53832.png","_id":"PmInA797xJhMIPti"}
{"name":"The Minimalist Slim Leather Watch","category":"Electronics","cost":60,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/5b478a4a-bf81-467c-964c-1881887799b7.png","_id":"TwMM4OAhmK0VQ93S"}
{"name":"Atomberg 1200mm BLDC motor","category":"Home & Kitchen","cost":80,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/e8e0832c-8f16-4468-95a0-8aaed387a169.png","_id":"a4sLtEcMpzabRyfx"}
{"name":"Bonsai Spirit Tree Table Lamp","category":"Home & Kitchen","cost":80,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/b49ee2dc-6458-42de-851d-b014ac24cd8e.png","_id":"upLK9JbQ4rMhTwt4"}
{"name":"Stylecon 9 Seater RHS Sofa Set ","category":"Home & Kitchen","cost":650,"rating":3,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/7ad56699-20c9-4778-a783-4021e5f0864c.png","_id":"v4sLtEcMpzabRyf"}
{"name":"Diamond Pendant (0.01 ct, IJ-SI)","category":"Fashion","cost":1000,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/95d6d42d-3a37-4efb-ad10-3bcbbb599856.png","_id":"v4sLtEcMpzabRyfx"}
{"name":"Apple iPad Pro with Apple M1 chip","category":"Electronics","cost":900,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/82ac2e7b-e4dd-4a5b-8dbc-3260225d7eb2.png","_id":"w4sLtEcMpzabRyfx"}
{"name":"OnePlus (55 inches) Q1 Series 4K","category":"Electronics","cost":1200,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/a9ca1e8b-8783-4be3-83f8-d06409016e15.png","_id":"x4sLtEcMpzabRyfx"}
{"name":"Thinking, Fast and Slow","category":"Books","cost":15,"rating":5,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/cdb64440-5e95-4aaa-858b-8c12ee316d93.png","_id":"y4sLtEcMpzabRyfx"}
{"name":"GREY DOUBLE BUTTON BLAZER","category":"Fashion","cost":75,"rating":4,"image":"https://crio-directus-assets.s3.ap-south-1.amazonaws.com/869ec5e2-52d2-4b8e-bc6b-57eace9ab39e.png","_id":"z4sLtEcMpzabRyfx"}
23 changes: 23 additions & 0 deletions backend/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
const express = require('express');
const cors = require('cors');
const config = require('./config.json');
const app = express();

app.use(cors());
app.use(express.json());

const authRouter = require('./routes/auth')
const productRouter = require('./routes/product')
const cartRouter = require('./routes/cart')
const userRouter = require('./routes/user')

app.use('/api/v1/auth', authRouter);
app.use('/api/v1/products', productRouter);
app.use('/api/v1/cart', cartRouter);
app.use('/api/v1/user', userRouter);

const port = process.env.PORT || config.port
app.listen(port, () => {
console.log(`QKart Backend running at port ${port}`);
});

18 changes: 18 additions & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "react-me-backend",
"version": "0.1.0",
"private": true,
"scripts": {
"start": "node index.js"
},
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"jsonwebtoken": "^8.5.1",
"nanoid": "^3.1.12",
"nedb": "^1.8.0",
"@testing-library/dom": "^8.13.0",
"typescript": "^3.2.1",
"@babel/core": "^7.17.10"
}
}
89 changes: 89 additions & 0 deletions backend/routes/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
var express = require("express");
var router = express.Router();
const { handleError } = require("../utils");
var { users } = require("../db");
const crypto = require("crypto");
const jwt = require("jsonwebtoken");
const config = require("../config.json");

router.post("/register", (req, res) => {
console.log(`GET request to "/auth/register" received for user}`);

users.findOne({ username: req.body.username }, (err, user) => {
if (err) {
return handleError(res, err);
}
if (user) {
return res.status(400).json({
success: false,
message: "Username already exists",
});
}
// if (req.body.username.length < 6 || req.body.username.length > 32) {
// return res.status(400).json({
// success: false,
// message:
// 'Username must be between 6 and 32 characters in length'
// });
// }
// if (req.body.password.length < 6 || req.body.password.length > 32) {
// return res.status(400).json({
// success: false,
// message:
// 'Password must be between 6 and 32 characters in length'
// });
// }
users.insert({
username: req.body.username,
password: sha256(req.body.password),
balance: 5000,
cart: [],
addresses: [],
});

console.log(`Registered user: ${req.body.username}`);

return res.status(201).json({
success: true,
});
});
});

router.post("/login", (req, res) => {
console.log(`POST request to "/auth/login" received`);

users.findOne({ username: req.body.username }, (err, user) => {
if (err) {
return handleError(res, err);
}
if (!user) {
return res.status(400).json({
success: false,
message: "Username does not exist",
});
}
if (user.password !== sha256(req.body.password)) {
return res.status(400).json({
success: false,
message: "Password is incorrect",
});
}
const token = jwt.sign({ username: user.username }, config.jwtSecret, {
expiresIn: "6h",
});

console.log(`Logged in as user: ${req.body.username}`);

return res.status(201).json({
success: true,
token: token,
username: user.username,
balance: user.balance,
});
});
});

const sha256 = (input) =>
crypto.createHash("sha256").update(input, "utf8").digest("hex");

module.exports = router;
119 changes: 119 additions & 0 deletions backend/routes/cart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
var express = require("express");
var router = express.Router();
const { handleError, verifyAuth, getProduct } = require("../utils");
var { users, products } = require("../db");

// Cart Controller
router.get("/", verifyAuth, (req, res) => {
console.log(`GET request to "/cart" received`);

return res.status(200).json(req.user.cart);
});

router.post("/", verifyAuth, async (req, res) => {
console.log(`POST request to "/cart" received`);

products.findOne({ _id: req.body.productId }, async (err, product) => {
if (err) {
return handleError(res, err);
}
if (!product) {
return res
.status(404)
.json({ success: false, message: "Product doesn't exist" });
}

const index = await req.user.cart.findIndex(
(element) => element.productId === req.body.productId
);

if (index === -1) {
req.user.cart.push({
productId: req.body.productId,
qty: req.body.qty,
});
} else if (req.body.qty === 0) {
// delete
req.user.cart.splice(index, 1);
} else {
//modify
req.user.cart[index].qty = req.body.qty;
}
users.update(
{ _id: req.user._id },
{ $set: { cart: req.user.cart } },
{},
(err) => {
if (err) {
handleError(res, err);
}

console.log(
`User ${req.user.username}'s cart updated to`,
req.user.cart
);

return res.status(200).json(req.user.cart);
}
);
});
});

router.post("/checkout", verifyAuth, async (req, res) => {
console.log(
`POST request received to "/cart/checkout": ${req.user.username}`
);

let total = 0;
for (let element of req.user.cart) {
try {
const product = await getProduct(element.productId);
if (product == null) {
throw new Error("Invalid product in cart. ");
}
total = total + element.qty * product.cost;
} catch (error) {
handleError(res, error);
}
}
if (total === 0) {
return res.status(400).json({ success: false, message: "Cart is empty" });
}
if (req.user.balance < total) {
return res.status(400).json({
success: false,
message: "Wallet balance not sufficient to place order",
});
}
if (!req.body.addressId) {
return res.status(400).json({
success: false,
message: "Address not set",
});
}
const addressIndex = await req.user.addresses.findIndex(
(element) => element._id === req.body.addressId
);
if (addressIndex === -1) {
return res
.status(404)
.json({ success: false, message: "Bad address specified" });
}
req.user.balance -= total;
console.log("Mock order placed");
console.log("Cart", req.user.cart);
console.log("Total cost", total);
console.log("Address", req.user.addresses[addressIndex]);
// Now clear cart
req.user.cart = [];
users.update({ _id: req.user._id }, req.user, {}, (err) => {
if (err) {
handleError(res, err);
}
return res.status(200).json({
success: true,
});
});
});

module.exports = router;
Loading

0 comments on commit 57b6316

Please sign in to comment.