Skip to content

Commit

Permalink
add carting functions on user model
Browse files Browse the repository at this point in the history
  • Loading branch information
amitamrutiya committed Nov 15, 2023
1 parent b2096c7 commit 5f5260d
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 10 deletions.
100 changes: 100 additions & 0 deletions backend/controllers/Cart.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
const User = require("../models/User");

exports.addCourseIntoCart = async (req, res) => {
try {
const { courseId, userId } = req.body;
const user = await User.findById(userId);

if (courseId === undefined || userId === undefined) {
return res.status(400).json({
success: false,
message: "courseId or userId is undefined",
});
}

if (!user) {
return res.status(404).json({
success: false,
message: "User not found",
});
}
user.cartAddedCourses.push(courseId);
await user.save();
return res.status(200).json({
success: true,
message: "Course added to cart",
});
} catch (error) {
console.log("Error in addCourseIntoCart: " + error);
return res.status(500).json({
success: false,
message: "Error on addCourseIntoCart controller: " + error,
});
}
};

exports.removeCourseFromCart = async (req, res) => {
const { courseId, userId } = req.body;

if (courseId === undefined || userId === undefined) {
return res.status(400).json({
success: false,
message: "courseId or userId is undefined",
});
}

try {
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({
success: false,
message: "User not found",
});
}
user.cartAddedCourses.pull(courseId);
await user.save();
return res.status(200).json({
success: true,
message: "Course removed from cart",
});
} catch (error) {
console.log("Error in removeFromCart: " + error);
return res.status(500).json({
success: false,
message: "Error on removeFromCart controller: " + error,
});
}
};

exports.clearCart = async (req, res) => {
const { userId } = req.body;

if (userId === undefined) {
return res.status(400).json({
success: false,
message: "userId is undefined",
});
}

try {
const user = await User.findById(userId);
if (!user) {
return res.status(404).json({
success: false,
message: "User not found",
});
}
user.cartAddedCourses = [];
await user.save();
return res.status(200).json({
success: true,
message: "Cart cleared",
});
} catch (error) {
console.log("Error in clearCart: " + error);
return res.status(500).json({
success: false,
message: "Error on clearCart controller: " + error,
});
}
};
6 changes: 6 additions & 0 deletions backend/models/User.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ const userSchems = new mongoose.Schema({
ref: "Course",
},
],
cartAddedCourses: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Course",
},
],
image: {
type: String,
required: true,
Expand Down
11 changes: 11 additions & 0 deletions backend/routes/Course.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ const {
getAllRatingAndReview,
} = require("../controllers/RatingAndReview"); // Rating Controllers Import

const {
addCourseIntoCart,
removeCourseFromCart,
clearCart,
} = require("../controllers/Cart"); // Cart Controllers Import

const {
auth,
isInstructor,
Expand Down Expand Up @@ -64,6 +70,11 @@ router.post("/createCategory", auth, isAdmin, createCategory);
router.get("/showAllCategories", showAllCategories);
router.post("/getCategoryPageDetails", categoryPageDetails);

// Cart routes (only by Student)
router.post("/addCourseIntoCart", auth, isStudent, addCourseIntoCart);
router.post("/removeCourseFromCart", auth, isStudent, removeCourseFromCart);
router.post("/clearCart", auth, isStudent, clearCart);

// Rating and Review (only by Student)
router.post("/createRating", auth, isStudent, createRating);
router.get("/getAverageRating", getAverageRating);
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/components/core/Course/CourseDetailsCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { useNavigate } from "react-router-dom";
import { addToCart } from "../../../slices/cartSlice";
import { toast } from "react-hot-toast";
import { ACCOUNT_TYPE } from "../../../utils/constants";
import { addCourseToCart } from "../../../services/operations/courseDetailsAPI";

function CourseDetailsCard({ course, setConfirmationModal, handleBuyCourse }) {
const { user } = useSelector((state) => state.profile);
Expand All @@ -19,13 +20,14 @@ function CourseDetailsCard({ course, setConfirmationModal, handleBuyCourse }) {
toast.success("Link copied to clipboard");
};

const handleAddToCart = () => {
const handleAddToCart = async () => {
if (user && user?.accountType === ACCOUNT_TYPE.INSTRUCTOR) {
toast.error("You are an Instructor. You can't buy a course.");
return;
}
if (token) {
dispatch(addToCart(course));
await addCourseToCart({ courseId: course._id, userId: user._id }, token);
return;
}
setConfirmationModal({
Expand Down
14 changes: 10 additions & 4 deletions frontend/src/components/core/Dashboard/Cart/RenderCartCourses.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,21 @@ import { RiDeleteBin6Line } from "react-icons/ri";
import ReactStars from "react-rating-stars-component";
import { useDispatch, useSelector } from "react-redux";
import { removeFromCart } from "../../../../slices/cartSlice";
import { removeCourseFromCart } from "../../../../services/operations/courseDetailsAPI";

export default function RenderCartCourses() {
const { cart } = useSelector((state) => state.cart);
const { user } = useSelector((state) => state.profile);
const { token } = useSelector((state) => state.auth);
const dispatch = useDispatch();

return (
<div className="flex flex-1 flex-col">
{cart.map((course, indx) => (
<div
key={course._id}
className={`flex w-full flex-wrap items-start justify-between gap-6 ${
indx !== cart.length - 1 && "border-b border-b-richblack-400 pb-6"
} ${indx !== 0 && "mt-6"} `}
className={`flex w-full flex-wrap items-start justify-between gap-6 ${indx !== cart.length - 1 && "border-b border-b-richblack-400 pb-6"
} ${indx !== 0 && "mt-6"} `}
>
<div className="flex flex-1 flex-col gap-4 xl:flex-row">
<img
Expand Down Expand Up @@ -53,7 +55,11 @@ export default function RenderCartCourses() {

<div className="flex flex-col items-end space-y-2">
<button
onClick={() => dispatch(removeFromCart(course._id))}
onClick={() => {
dispatch(removeFromCart(course._id));
removeCourseFromCart({ courseId: course._id, userId: user._id }, token);
}}
// onClick={() => dispatch(removeFromCart(course._id))}
className="flex items-center gap-x-1 rounded-md border border-richblack-600 bg-richblack-700 py-3 px-[12px] text-pink-200"
>
<RiDeleteBin6Line />
Expand Down
8 changes: 8 additions & 0 deletions frontend/src/services/apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,19 @@ export const categories = {
export const catalogData = {
CATALOGPAGEDATA_API: BASE_URL + "/course/getCategoryPageDetails",
};

// CONTACT-US API
export const contactusEndpoint = {
CONTACT_US_API: BASE_URL + "/reach/contact",
};

// CART API
export const cartEndpoints = {
ADD_TO_CART_API: BASE_URL + "/course/addCourseIntoCart",
REMOVE_FROM_CART_API: BASE_URL + "/course/removeCourseFromCart",
CLEAR_CART_API: BASE_URL + "/course/clearCart",
};

// SETTINGS PAGE API
export const settingsEndpoints = {
UPDATE_DISPLAY_PICTURE_API: BASE_URL + "/profile/updateDisplayPicture",
Expand Down
76 changes: 75 additions & 1 deletion frontend/src/services/operations/courseDetailsAPI.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { toast } from "react-hot-toast";
import { apiConnector } from "../apiconnector";
import { courseEndpoints } from "../apis";
import { cartEndpoints, courseEndpoints } from "../apis";

const {
COURSE_DETAILS_API,
Expand All @@ -21,6 +21,8 @@ const {
LECTURE_COMPLETION_API,
} = courseEndpoints;

const { ADD_TO_CART_API, REMOVE_FROM_CART_API, CLEAR_CART_API } = cartEndpoints;

export const getAllCourses = async () => {
const toastId = toast.loading("Loading...");
let result = [];
Expand Down Expand Up @@ -386,3 +388,75 @@ export const createRating = async (data, token) => {
toast.dismiss(toastId);
return success;
};

// add course to cart
export const addCourseToCart = async (data, token) => {
const toastId = toast.loading("Loading...");
let success = false;
try {
const response = await apiConnector("POST", ADD_TO_CART_API, data, {
Authorization: `Bearer ${token}`,
});
console.log("ADD_TO_CART_API API RESPONSE............", response);

if (!response?.data?.success) {
throw new Error("Could Not Add Course To Cart");
}
toast.success("Course Added To Cart");
success = true;
} catch (error) {
success = false;
console.log("ADD_TO_CART_API API ERROR............", error);
toast.error(error.message);
}
toast.dismiss(toastId);
return success;
};

// remove course from cart
export const removeCourseFromCart = async (data, token) => {
const toastId = toast.loading("Loading...");
let success = false;
try {
const response = await apiConnector("POST", REMOVE_FROM_CART_API, data, {
Authorization: `Bearer ${token}`,
});
console.log("REMOVE_FROM_CART_API API RESPONSE............", response);

if (!response?.data?.success) {
throw new Error("Could Not Remove Course From Cart");
}
toast.success("Course Removed From Cart");
success = true;
} catch (error) {
success = false;
console.log("REMOVE_FROM_CART_API API ERROR............", error);
toast.error(error.message);
}
toast.dismiss(toastId);
return success;
};

// clear cart
export const clearCart = async (data, token) => {
const toastId = toast.loading("Loading...");
let success = false;
try {
const response = await apiConnector("POST", CLEAR_CART_API, data, {
Authorization: `Bearer ${token}`,
});
console.log("CLEAR_CART_API API RESPONSE............", response);

if (!response?.data?.success) {
throw new Error("Could Not Clear Cart");
}
toast.success("Cart Cleared");
success = true;
} catch (error) {
success = false;
console.log("CLEAR_CART_API API ERROR............", error);
toast.error(error.message);
}
toast.dismiss(toastId);
return success;
};
4 changes: 0 additions & 4 deletions frontend/src/slices/cartSlice.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ const cartSlice = createSlice({
localStorage.setItem("cart", JSON.stringify(state.cart)); // Update to localstorage
localStorage.setItem("total", JSON.stringify(state.total));
localStorage.setItem("totalItems", JSON.stringify(state.totalItems));

toast.success("Course added to cart"); // show toast
},

removeFromCart: (state, action) => {
Expand All @@ -52,8 +50,6 @@ const cartSlice = createSlice({
localStorage.setItem("cart", JSON.stringify(state.cart)); // Update to localstorage
localStorage.setItem("total", JSON.stringify(state.total));
localStorage.setItem("totalItems", JSON.stringify(state.totalItems));

toast.success("Course removed from cart"); // show toast
}
},

Expand Down

0 comments on commit 5f5260d

Please sign in to comment.