Repository: sangammukherjee/NextJS-Ecommerce-2023
Branch: master
Commit: 82c64f9440d9
Files: 76
Total size: 148.9 KB
Directory structure:
gitextract_v8_ctk5n/
├── .gitignore
├── README.md
├── jsconfig.json
├── next.config.js
├── package.json
├── postcss.config.js
├── src/
│ ├── app/
│ │ ├── account/
│ │ │ └── page.js
│ │ ├── admin-view/
│ │ │ ├── add-product/
│ │ │ │ └── page.js
│ │ │ ├── all-products/
│ │ │ │ └── page.js
│ │ │ └── page.js
│ │ ├── api/
│ │ │ ├── address/
│ │ │ │ ├── add-new-address/
│ │ │ │ │ └── route.js
│ │ │ │ ├── delete-address/
│ │ │ │ │ └── route.js
│ │ │ │ ├── get-all-address/
│ │ │ │ │ └── route.js
│ │ │ │ └── update-address/
│ │ │ │ └── route.js
│ │ │ ├── admin/
│ │ │ │ ├── add-product/
│ │ │ │ │ └── route.js
│ │ │ │ ├── all-products/
│ │ │ │ │ └── route.js
│ │ │ │ ├── delete-product/
│ │ │ │ │ └── route.js
│ │ │ │ ├── orders/
│ │ │ │ │ ├── get-all-orders/
│ │ │ │ │ │ └── route.js
│ │ │ │ │ └── update-order/
│ │ │ │ │ └── route.js
│ │ │ │ ├── product-by-category/
│ │ │ │ │ └── route.js
│ │ │ │ ├── product-by-id/
│ │ │ │ │ └── route.js
│ │ │ │ └── update-product/
│ │ │ │ └── route.js
│ │ │ ├── cart/
│ │ │ │ ├── add-to-cart/
│ │ │ │ │ └── route.js
│ │ │ │ ├── all-cart-items/
│ │ │ │ │ └── route.js
│ │ │ │ └── delete-from-cart/
│ │ │ │ └── route.js
│ │ │ ├── login/
│ │ │ │ └── route.js
│ │ │ ├── order/
│ │ │ │ ├── create-order/
│ │ │ │ │ └── route.js
│ │ │ │ ├── get-all-orders/
│ │ │ │ │ └── route.js
│ │ │ │ └── order-details/
│ │ │ │ └── route.js
│ │ │ ├── register/
│ │ │ │ └── route.js
│ │ │ └── stripe/
│ │ │ └── route.js
│ │ ├── cart/
│ │ │ └── page.js
│ │ ├── checkout/
│ │ │ └── page.js
│ │ ├── globals.css
│ │ ├── layout.js
│ │ ├── login/
│ │ │ └── page.js
│ │ ├── orders/
│ │ │ ├── [order-details]/
│ │ │ │ └── page.js
│ │ │ └── page.js
│ │ ├── page.js
│ │ ├── product/
│ │ │ ├── [details]/
│ │ │ │ └── page.js
│ │ │ └── listing/
│ │ │ ├── all-products/
│ │ │ │ └── page.js
│ │ │ ├── kids/
│ │ │ │ └── page.js
│ │ │ ├── men/
│ │ │ │ └── page.js
│ │ │ └── women/
│ │ │ └── page.js
│ │ ├── register/
│ │ │ └── page.js
│ │ └── unauthorized-page/
│ │ └── page.js
│ ├── components/
│ │ ├── CartModal/
│ │ │ └── index.js
│ │ ├── CommonCart/
│ │ │ └── index.js
│ │ ├── CommonDetails/
│ │ │ └── index.js
│ │ ├── CommonListing/
│ │ │ ├── ProductButtons/
│ │ │ │ └── index.js
│ │ │ ├── ProductTile/
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── CommonModal/
│ │ │ └── index.js
│ │ ├── FormElements/
│ │ │ ├── InputComponent/
│ │ │ │ └── index.js
│ │ │ ├── SelectComponent/
│ │ │ │ └── index.js
│ │ │ └── TileComponent/
│ │ │ └── index.js
│ │ ├── Loader/
│ │ │ └── componentlevel/
│ │ │ └── index.js
│ │ ├── Navbar/
│ │ │ └── index.js
│ │ └── Notification/
│ │ └── index.js
│ ├── context/
│ │ └── index.js
│ ├── database/
│ │ └── index.js
│ ├── middleware/
│ │ └── AuthUser.js
│ ├── models/
│ │ ├── address.js
│ │ ├── cart.js
│ │ ├── order.js
│ │ ├── product.js
│ │ └── user.js
│ ├── services/
│ │ ├── address/
│ │ │ └── index.js
│ │ ├── cart/
│ │ │ └── index.js
│ │ ├── login/
│ │ │ └── index.js
│ │ ├── order/
│ │ │ └── index.js
│ │ ├── product/
│ │ │ └── index.js
│ │ ├── register/
│ │ │ └── index.js
│ │ └── stripe/
│ │ └── index.js
│ └── utils/
│ └── index.js
└── tailwind.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
================================================
FILE: README.md
================================================
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.js`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
================================================
FILE: jsconfig.json
================================================
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"]
}
}
}
================================================
FILE: next.config.js
================================================
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = nextConfig
================================================
FILE: package.json
================================================
{
"name": "ecommerce",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@headlessui/react": "^1.7.15",
"@stripe/stripe-js": "^1.54.1",
"autoprefixer": "10.4.14",
"bcryptjs": "^2.4.3",
"firebase": "^10.0.0",
"joi": "^17.9.2",
"js-cookie": "^3.0.5",
"jsonwebtoken": "^9.0.1",
"mongoose": "^7.3.2",
"next": "13.4.9",
"postcss": "8.4.25",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-spinners": "^0.13.8",
"react-toastify": "^9.1.3",
"stripe": "^12.12.0",
"tailwindcss": "3.3.2"
},
"devDependencies": {
"encoding": "^0.1.13"
}
}
================================================
FILE: postcss.config.js
================================================
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
================================================
FILE: src/app/account/page.js
================================================
"use client";
import InputComponent from "@/components/FormElements/InputComponent";
import ComponentLevelLoader from "@/components/Loader/componentlevel";
import Notification from "@/components/Notification";
import { GlobalContext } from "@/context";
import {
addNewAddress,
deleteAddress,
fetchAllAddresses,
updateAddress,
} from "@/services/address";
import { addNewAddressFormControls } from "@/utils";
import { useRouter } from "next/navigation";
import { useContext, useEffect, useState } from "react";
import { PulseLoader } from "react-spinners";
import { toast } from "react-toastify";
export default function Account() {
const {
user,
addresses,
setAddresses,
addressFormData,
setAddressFormData,
componentLevelLoader,
setComponentLevelLoader,
pageLevelLoader,
setPageLevelLoader,
} = useContext(GlobalContext);
const [showAddressForm, setShowAddressForm] = useState(false);
const [currentEditedAddressId, setCurrentEditedAddressId] = useState(null);
const router = useRouter()
async function extractAllAddresses() {
setPageLevelLoader(true);
const res = await fetchAllAddresses(user?._id);
if (res.success) {
setPageLevelLoader(false);
setAddresses(res.data);
}
}
async function handleAddOrUpdateAddress() {
setComponentLevelLoader({ loading: true, id: "" });
const res =
currentEditedAddressId !== null
? await updateAddress({
...addressFormData,
_id: currentEditedAddressId,
})
: await addNewAddress({ ...addressFormData, userID: user?._id });
console.log(res);
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setAddressFormData({
fullName: "",
city: "",
country: "",
postalCode: "",
address: "",
});
extractAllAddresses();
setCurrentEditedAddressId(null);
} else {
setComponentLevelLoader({ loading: false, id: "" });
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setAddressFormData({
fullName: "",
city: "",
country: "",
postalCode: "",
address: "",
});
}
}
function handleUpdateAddress(getCurrentAddress) {
setShowAddressForm(true);
setAddressFormData({
fullName: getCurrentAddress.fullName,
city: getCurrentAddress.city,
country: getCurrentAddress.country,
postalCode: getCurrentAddress.postalCode,
address: getCurrentAddress.address,
});
setCurrentEditedAddressId(getCurrentAddress._id);
}
async function handleDelete(getCurrentAddressID) {
setComponentLevelLoader({ loading: true, id: getCurrentAddressID });
const res = await deleteAddress(getCurrentAddressID);
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
extractAllAddresses();
} else {
setComponentLevelLoader({ loading: false, id: "" });
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
}
}
useEffect(() => {
if (user !== null) extractAllAddresses();
}, [user]);
return (
{/* we have render random user image here */}
{user?.name}
{user?.email}
{user?.role}
Your Addresses :
{pageLevelLoader ? (
) : (
{addresses && addresses.length ? (
addresses.map((item) => (
Name : {item.fullName}
Address : {item.address}
City : {item.city}
Country : {item.country}
PostalCode : {item.postalCode}
))
) : (
No address found ! Please add a new address below
)}
)}
{showAddressForm ? (
{addNewAddressFormControls.map((controlItem) => (
setAddressFormData({
...addressFormData,
[controlItem.id]: event.target.value,
})
}
/>
))}
) : null}
);
}
================================================
FILE: src/app/admin-view/add-product/page.js
================================================
"use client";
import InputComponent from "@/components/FormElements/InputComponent";
import SelectComponent from "@/components/FormElements/SelectComponent";
import TileComponent from "@/components/FormElements/TileComponent";
import ComponentLevelLoader from "@/components/Loader/componentlevel";
import Notification from "@/components/Notification";
import { GlobalContext } from "@/context";
import { addNewProduct, updateAProduct } from "@/services/product";
import {
AvailableSizes,
adminAddProductformControls,
firebaseConfig,
firebaseStroageURL,
} from "@/utils";
import { initializeApp } from "firebase/app";
import {
getDownloadURL,
getStorage,
ref,
uploadBytesResumable,
} from "firebase/storage";
import { useRouter } from "next/navigation";
import { useContext, useEffect, useState } from "react";
import { toast } from "react-toastify";
import { resolve } from "styled-jsx/css";
const app = initializeApp(firebaseConfig);
const storage = getStorage(app, firebaseStroageURL);
const createUniqueFileName = (getFile) => {
const timeStamp = Date.now();
const randomStringValue = Math.random().toString(36).substring(2, 12);
return `${getFile.name}-${timeStamp}-${randomStringValue}`;
};
async function helperForUPloadingImageToFirebase(file) {
const getFileName = createUniqueFileName(file);
const storageReference = ref(storage, `ecommerce/${getFileName}`);
const uploadImage = uploadBytesResumable(storageReference, file);
return new Promise((resolve, reject) => {
uploadImage.on(
"state_changed",
(snapshot) => {},
(error) => {
console.log(error);
reject(error);
},
() => {
getDownloadURL(uploadImage.snapshot.ref)
.then((downloadUrl) => resolve(downloadUrl))
.catch((error) => reject(error));
}
);
});
}
const initialFormData = {
name: "",
price: 0,
description: "",
category: "men",
sizes: [],
deliveryInfo: "",
onSale: "no",
imageUrl: "",
priceDrop: 0,
};
export default function AdminAddNewProduct() {
const [formData, setFormData] = useState(initialFormData);
const {
componentLevelLoader,
setComponentLevelLoader,
currentUpdatedProduct,
setCurrentUpdatedProduct,
} = useContext(GlobalContext);
console.log(currentUpdatedProduct);
const router = useRouter();
useEffect(() => {
if (currentUpdatedProduct !== null) setFormData(currentUpdatedProduct);
}, [currentUpdatedProduct]);
async function handleImage(event) {
const extractImageUrl = await helperForUPloadingImageToFirebase(
event.target.files[0]
);
if (extractImageUrl !== "") {
setFormData({
...formData,
imageUrl: extractImageUrl,
});
}
}
function handleTileClick(getCurrentItem) {
let cpySizes = [...formData.sizes];
const index = cpySizes.findIndex((item) => item.id === getCurrentItem.id);
if (index === -1) {
cpySizes.push(getCurrentItem);
} else {
cpySizes = cpySizes.filter((item) => item.id !== getCurrentItem.id);
}
setFormData({
...formData,
sizes: cpySizes,
});
}
async function handleAddProduct() {
setComponentLevelLoader({ loading: true, id: "" });
const res =
currentUpdatedProduct !== null
? await updateAProduct(formData)
: await addNewProduct(formData);
console.log(res);
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setFormData(initialFormData);
setCurrentUpdatedProduct(null)
setTimeout(() => {
router.push("/admin-view/all-products");
}, 1000);
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: "" });
setFormData(initialFormData);
}
}
console.log(formData);
return (
);
}
================================================
FILE: src/app/admin-view/all-products/page.js
================================================
import CommonListing from "@/components/CommonListing";
import { getAllAdminProducts } from "@/services/product";
export default async function AdminAllProducts() {
const allAdminProducts = await getAllAdminProducts()
return
}
================================================
FILE: src/app/admin-view/page.js
================================================
"use client";
import ComponentLevelLoader from "@/components/Loader/componentlevel";
import { GlobalContext } from "@/context";
import { getAllOrdersForAllUsers, updateStatusOfOrder } from "@/services/order";
import { useContext, useEffect } from "react";
import { PulseLoader } from "react-spinners";
export default function AdminView() {
const {
allOrdersForAllUsers,
setAllOrdersForAllUsers,
user,
pageLevelLoader,
setPageLevelLoader,
componentLevelLoader,
setComponentLevelLoader,
} = useContext(GlobalContext);
async function extractAllOrdersForAllUsers() {
setPageLevelLoader(true);
const res = await getAllOrdersForAllUsers();
console.log(res);
if (res.success) {
setPageLevelLoader(false);
setAllOrdersForAllUsers(
res.data && res.data.length
? res.data.filter((item) => item.user._id !== user._id)
: []
);
} else {
setPageLevelLoader(false);
}
}
useEffect(() => {
if (user !== null) extractAllOrdersForAllUsers();
}, [user]);
console.log(allOrdersForAllUsers);
async function handleUpdateOrderStatus(getItem) {
setComponentLevelLoader({ loading: true, id: getItem._id });
const res = await updateStatusOfOrder({
...getItem,
isProcessing: false,
});
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
extractAllOrdersForAllUsers();
} else {
setComponentLevelLoader({ loading: true, id: "" });
}
}
if (pageLevelLoader) {
return (
);
}
return (
{allOrdersForAllUsers && allOrdersForAllUsers.length ? (
) : null}
);
}
================================================
FILE: src/app/api/address/add-new-address/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Address from "@/models/address";
import Joi from "joi";
import { NextResponse } from "next/server";
const AddNewAddress = Joi.object({
fullName: Joi.string().required(),
address: Joi.string().required(),
city: Joi.string().required(),
country: Joi.string().required(),
postalCode: Joi.string().required(),
userID: Joi.string().required(),
});
export const dynamic = "force-dynamic";
export async function POST(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const data = await req.json();
const { fullName, address, city, country, postalCode, userID } = data;
const { error } = AddNewAddress.validate({
fullName,
address,
city,
country,
postalCode,
userID,
});
if (error) {
return NextResponse.json({
success: false,
message: error.details[0].message,
});
}
const newlyAddedAddress = await Address.create(data);
if (newlyAddedAddress) {
return NextResponse.json({
success: true,
message: "Address added successfully",
});
} else {
return NextResponse.json({
success: false,
message: "failed to add an address ! Please try again later",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/address/delete-address/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Address from "@/models/address";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function DELETE(req) {
try {
await connectToDB();
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id) {
return NextResponse.json({
success: false,
message: "Address ID is required",
});
}
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const deletedAddress = await Address.findByIdAndDelete(id);
if (deletedAddress) {
return NextResponse.json({
success: true,
message: "Address is deleted successfully",
});
} else {
return NextResponse.json({
success: false,
message: "failed to delete address ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/address/get-all-address/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Address from "@/models/address";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id) {
return NextResponse.json({
success: false,
message: "You are not logged In",
});
}
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const getAllAddresses = await Address.find({ userID: id });
if (getAllAddresses) {
return NextResponse.json({
success: true,
data: getAllAddresses,
});
} else {
return NextResponse.json({
success: false,
message: "failed to get addresses ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/address/update-address/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Address from "@/models/address";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function PUT(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const data = await req.json();
const { _id, fullName, city, address, country, postalCode } = data;
const updateAddress = await Address.findOneAndUpdate(
{
_id: _id,
},
{ fullName, city, address, country, postalCode },
{ new: true }
);
if (updateAddress) {
return NextResponse.json({
success: true,
message: "Address updated successfully!",
});
} else {
return NextResponse.json({
success: false,
message: "failed to update address ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/add-product/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Product from "@/models/product";
import Joi from "joi";
import { NextResponse } from "next/server";
const AddNewProductSchema = Joi.object({
name: Joi.string().required(),
description: Joi.string().required(),
price: Joi.number().required(),
category: Joi.string().required(),
sizes: Joi.array().required(),
deliveryInfo: Joi.string().required(),
onSale: Joi.string().required(),
priceDrop: Joi.number().required(),
imageUrl: Joi.string().required(),
});
export const dynamic = "force-dynamic";
export async function POST(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req)
console.log(isAuthUser , 'sangam');
if (isAuthUser?.role === "admin") {
const extractData = await req.json();
const {
name,
description,
price,
imageUrl,
category,
sizes,
deliveryInfo,
onSale,
priceDrop,
} = extractData;
const { error } = AddNewProductSchema.validate({
name,
description,
price,
imageUrl,
category,
sizes,
deliveryInfo,
onSale,
priceDrop,
});
if (error) {
return NextResponse.json({
success: false,
message: error.details[0].message,
});
}
const newlyCreatedProduct = await Product.create(extractData);
if (newlyCreatedProduct) {
return NextResponse.json({
success: true,
message: "Product added successfully",
});
} else {
return NextResponse.json({
success: false,
message: "Failed to add the product ! please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not autorized !",
});
}
} catch (error) {
console.log(error);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/all-products/route.js
================================================
import connectToDB from "@/database";
import Product from "@/models/product";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const extractAllproducts = await Product.find({});
if (extractAllproducts) {
return NextResponse.json({
success: true,
data: extractAllproducts,
});
} else {
return NextResponse.json({
success: false,
status: 204,
message: "No Products found",
});
}
} catch (error) {
console.log(error);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/delete-product/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Product from "@/models/product";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function DELETE(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser?.role === "admin") {
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id)
return NextResponse.json({
success: false,
message: "Product ID is required",
});
const deletedProduct = await Product.findByIdAndDelete(id);
if (deletedProduct) {
return NextResponse.json({
success: true,
message: "Product deleted successfully",
});
} else {
return NextResponse.json({
success: false,
message: "Failed to delete the product ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(error);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/orders/get-all-orders/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Order from "@/models/order";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser?.role === "admin") {
const getAllOrders = await Order.find({})
.populate("orderItems.product")
.populate("user");
if (getAllOrders) {
return NextResponse.json({
success: true,
data: getAllOrders,
});
} else {
return NextResponse.json({
success: false,
message:
"failed to fetch the orders ! Please try again after some time.",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not autorized !",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/orders/update-order/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Order from "@/models/order";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function PUT(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
const data = await req.json();
if (isAuthUser?.role === "admin") {
const {
_id,
shippingAddress,
orderItems,
paymentMethod,
isPaid,
paidAt,
isProcessing,
} = data;
const updateOrder = await Order.findOneAndUpdate(
{ _id: _id },
{
shippingAddress,
orderItems,
paymentMethod,
isPaid,
paidAt,
isProcessing,
},
{ new: true }
);
if (updateOrder) {
return NextResponse.json({
success: true,
message: "Order status updated successfully! ",
});
} else {
return NextResponse.json({
success: true,
message: "failed to update the status of order",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not autorized !",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/product-by-category/route.js
================================================
import connectToDB from "@/database";
import Product from "@/models/product";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
const getData = await Product.find({ category: id });
if (getData) {
return NextResponse.json({
success: true,
data: getData,
});
} else {
return NextResponse.json({
success: false,
status: 204,
message: "No Products found !",
});
}
} catch (e) {
console.log(error);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/product-by-id/route.js
================================================
import connectToDB from "@/database";
import Product from "@/models/product";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const { searchParams } = new URL(req.url);
const productId = searchParams.get("id");
if (!productId) {
return NextResponse.json({
success: false,
status: 400,
message: "Product id is required",
});
}
const getData = await Product.find({ _id: productId });
if (getData && getData.length) {
return NextResponse.json({ success: true, data: getData[0] });
} else {
return NextResponse.json({
success: false,
status: 204,
message: "No Product found",
});
}
} catch (error) {
console.log(error);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/admin/update-product/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Product from "@/models/product";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function PUT(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser?.role === "admin") {
const extractData = await req.json();
const {
_id,
name,
price,
description,
category,
sizes,
deliveryInfo,
onSale,
priceDrop,
imageUrl,
} = extractData;
const updatedProduct = await Product.findOneAndUpdate(
{
_id: _id,
},
{
name,
price,
description,
category,
sizes,
deliveryInfo,
onSale,
priceDrop,
imageUrl,
},
{ new: true }
);
if (updatedProduct) {
return NextResponse.json({
success: true,
message: "Product updated successfully",
});
} else {
return NextResponse.json({
success: false,
message: "Failed to update the product ! Please try again later",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(error);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/cart/add-to-cart/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Cart from "@/models/cart";
import Joi from "joi";
import { NextResponse } from "next/server";
const AddToCart = Joi.object({
userID: Joi.string().required(),
productID: Joi.string().required(),
});
export const dynamic = "force-dynamic";
export async function POST(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const data = await req.json();
const {productID , userID} = data;
const { error } = AddToCart.validate({ userID, productID });
if (error) {
return NextResponse.json({
success: false,
message: error.details[0].message,
});
}
console.log(productID, userID);
const isCurrentCartItemAlreadyExists = await Cart.find({
productID: productID,
userID: userID,
});
console.log(isCurrentCartItemAlreadyExists);
if (isCurrentCartItemAlreadyExists?.length > 0) {
return NextResponse.json({
success: false,
message:
"Product is already added in cart! Please add different product",
});
}
const saveProductToCart = await Cart.create(data);
console.log(saveProductToCart);
if (saveProductToCart) {
return NextResponse.json({
success: true,
message: "Product is added to cart !",
});
} else {
return NextResponse.json({
success: false,
message: "failed to add the product to cart ! Please try again.",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/cart/all-cart-items/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Cart from "@/models/cart";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id)
return NextResponse.json({
success: false,
message: "Please login in!",
});
const extractAllCartItems = await Cart.find({ userID: id }).populate(
"productID"
);
if (extractAllCartItems) {
return NextResponse.json({ success: true, data: extractAllCartItems });
} else {
return NextResponse.json({
success: false,
message: "No Cart items are found !",
status: 204,
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (e) {
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again",
});
}
}
================================================
FILE: src/app/api/cart/delete-from-cart/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Cart from "@/models/cart";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function DELETE(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id)
return NextResponse.json({
success: false,
message: "Cart Item ID is required",
});
const deleteCartItem = await Cart.findByIdAndDelete(id);
if (deleteCartItem) {
return NextResponse.json({
success: true,
message: "Cart Item deleted successfully",
});
} else {
return NextResponse.json({
success: false,
message: "Failed to delete Cart item ! Please try again.",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authenticated",
});
}
} catch (error) {
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again",
});
}
}
================================================
FILE: src/app/api/login/route.js
================================================
import connectToDB from "@/database";
import User from "@/models/user";
import { compare } from "bcryptjs";
import Joi from "joi";
import jwt from "jsonwebtoken";
import { NextResponse } from "next/server";
const schema = Joi.object({
email: Joi.string().email().required(),
password: Joi.string().required(),
});
export const dynamic = "force-dynamic";
export async function POST(req) {
await connectToDB();
const { email, password } = await req.json();
const { error } = schema.validate({ email, password });
if (error) {
return NextResponse.json({
success: false,
message: error.details[0].message,
});
}
try {
const checkUser = await User.findOne({ email });
if (!checkUser) {
return NextResponse.json({
success: false,
message: "Account not found with this email",
});
}
const checkPassword = await compare(password, checkUser.password);
if (!checkPassword) {
return NextResponse.json({
success: false,
message: "Incorrect password. Please try again !",
});
}
const token = jwt.sign(
{
id: checkUser._id,
email: checkUser?.email,
role: checkUser?.role,
},
"default_secret_key",
{ expiresIn: "1d" }
);
const finalData = {
token,
user: {
email: checkUser.email,
name: checkUser.name,
_id: checkUser._id,
role: checkUser.role,
},
};
return NextResponse.json({
success: true,
message: "Login successfull!",
finalData,
});
} catch (e) {
console.log("Error while logging In. Please try again");
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/order/create-order/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Cart from "@/models/cart";
import Order from "@/models/order";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function POST(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const data = await req.json();
const { user } = data;
const saveNewOrder = await Order.create(data);
if (saveNewOrder) {
await Cart.deleteMany({ userID: user });
return NextResponse.json({
success: true,
message: "Products are on the way !",
});
} else {
return NextResponse.json({
success: false,
message: "Failed to create a order ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authticated",
});
}
} catch (e) {
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/order/get-all-orders/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Order from "@/models/order";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
const extractAllOrders = await Order.find({ user: id }).populate(
"orderItems.product"
);
if (extractAllOrders) {
return NextResponse.json({
success: true,
data: extractAllOrders,
});
} else {
return NextResponse.json({
success: false,
message: "Failed to get all orders ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authticated",
});
}
} catch (e) {
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/order/order-details/route.js
================================================
import connectToDB from "@/database";
import AuthUser from "@/middleware/AuthUser";
import Order from "@/models/order";
import { NextResponse } from "next/server";
export const dynamic = "force-dynamic";
export async function GET(req) {
try {
await connectToDB();
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const { searchParams } = new URL(req.url);
const id = searchParams.get("id");
if (!id)
return NextResponse.json({
success: false,
message: "Product ID is required",
});
const extractOrderDetails = await Order.findById(id).populate(
"orderItems.product"
);
if (extractOrderDetails) {
return NextResponse.json({
success: true,
data: extractOrderDetails,
});
} else {
return NextResponse.json({
success: false,
message: "Failed to get order details ! Please try again",
});
}
} else {
return NextResponse.json({
success: false,
message: "You are not authticated",
});
}
} catch (e) {
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/register/route.js
================================================
import connectToDB from "@/database";
import User from "@/models/user";
import { hash } from "bcryptjs";
import Joi from "joi";
import { NextResponse } from "next/server";
const schema = Joi.object({
name: Joi.string().required(),
email: Joi.string().email().required(),
password: Joi.string().min(6).required(),
role: Joi.string().required(),
});
export const dynamic = "force-dynamic";
export async function POST(req) {
await connectToDB();
const { name, email, password, role } = await req.json();
//validate the schema
const { error } = schema.validate({ name, email, password, role });
if (error) {
console.log(error);
return NextResponse.json({
success: false,
message: error.details[0].message,
});
}
try {
//check if the user is exists or not
const isUserAlreadyExists = await User.findOne({ email });
if (isUserAlreadyExists) {
return NextResponse.json({
success: false,
message: "User is already exists. Please try with different email.",
});
} else {
const hashPassword = await hash(password, 12);
const newlyCreatedUser = await User.create({
name,
email,
password: hashPassword,
role,
});
if (newlyCreatedUser) {
return NextResponse.json({
success: true,
message: "Account created successfully.",
});
}
}
} catch (error) {
console.log("Error while new user registration. Please try again");
return NextResponse.json({
success: false,
message: "Something went wrong ! Please try again later",
});
}
}
================================================
FILE: src/app/api/stripe/route.js
================================================
import AuthUser from "@/middleware/AuthUser";
import { NextResponse } from "next/server";
const stripe = require("stripe")(
"sk_test_51NMv6ZSC6E6fnyMeTYV3h3Xge6Tot3xYQVEO6KMpiB5A6bKIrRS9YymIBEupAFqF0XM274IwwU2Zq7EXx1Pn8LiA00SyPEZqk9"
);
export const dynamic = "force-dynamic";
export async function POST(req) {
try {
const isAuthUser = await AuthUser(req);
if (isAuthUser) {
const res = await req.json();
const session = await stripe.checkout.sessions.create({
payment_method_types: ["card"],
line_items: res,
mode: "payment",
success_url: "http://localhost:3000/checkout" + "?status=success",
cancel_url: "http://localhost:3000/checkout" + "?status=cancel",
});
return NextResponse.json({
success: true,
id: session.id,
});
} else {
return NextResponse.json({
success: true,
message: "You are not authenticated",
});
}
} catch (e) {
console.log(e);
return NextResponse.json({
status: 500,
success: false,
message: "Something went wrong ! Please try again",
});
}
}
================================================
FILE: src/app/cart/page.js
================================================
"use client";
import CommonCart from "@/components/CommonCart";
import { GlobalContext } from "@/context";
import { deleteFromCart, getAllCartItems } from "@/services/cart";
import { useContext, useEffect } from "react";
import { PulseLoader } from "react-spinners";
import { toast } from "react-toastify";
export default function Cart() {
const {
user,
setCartItems,
cartItems,
pageLevelLoader,
setPageLevelLoader,
setComponentLevelLoader,
componentLevelLoader,
} = useContext(GlobalContext);
async function extractAllCartItems() {
setPageLevelLoader(true);
const res = await getAllCartItems(user?._id);
if (res.success) {
const updatedData =
res.data && res.data.length
? res.data.map((item) => ({
...item,
productID: {
...item.productID,
price:
item.productID.onSale === "yes"
? parseInt(
(
item.productID.price -
item.productID.price * (item.productID.priceDrop / 100)
).toFixed(2)
)
: item.productID.price,
},
}))
: [];
setCartItems(updatedData);
setPageLevelLoader(false);
localStorage.setItem("cartItems", JSON.stringify(updatedData));
}
console.log(res);
}
useEffect(() => {
if (user !== null) extractAllCartItems();
}, [user]);
async function handleDeleteCartItem(getCartItemID) {
setComponentLevelLoader({ loading: true, id: getCartItemID });
const res = await deleteFromCart(getCartItemID);
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
extractAllCartItems();
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: getCartItemID });
}
}
if (pageLevelLoader) {
return (
);
}
return (
);
}
================================================
FILE: src/app/checkout/page.js
================================================
"use client";
import Notification from "@/components/Notification";
import { GlobalContext } from "@/context";
import { fetchAllAddresses } from "@/services/address";
import { createNewOrder } from "@/services/order";
import { callStripeSession } from "@/services/stripe";
import { loadStripe } from "@stripe/stripe-js";
import { useRouter, useSearchParams } from "next/navigation";
import { useContext, useEffect, useState } from "react";
import { PulseLoader } from "react-spinners";
import { toast } from "react-toastify";
export default function Checkout() {
const {
cartItems,
user,
addresses,
setAddresses,
checkoutFormData,
setCheckoutFormData,
} = useContext(GlobalContext);
const [selectedAddress, setSelectedAddress] = useState(null);
const [isOrderProcessing, setIsOrderProcessing] = useState(false);
const [orderSuccess, setOrderSuccess] = useState(false);
const router = useRouter();
const params = useSearchParams();
const publishableKey =
"pk_test_51NMv6ZSC6E6fnyMeRIEb9oEXdGRCC9yrBTT4xWHgcjWOuFcqFiAHErvaS50K1hl5t5WJXVGfLLWxvb705IWJhA3300yCcrMnlM";
const stripePromise = loadStripe(publishableKey);
console.log(cartItems);
async function getAllAddresses() {
const res = await fetchAllAddresses(user?._id);
if (res.success) {
setAddresses(res.data);
}
}
useEffect(() => {
if (user !== null) getAllAddresses();
}, [user]);
useEffect(() => {
async function createFinalOrder() {
const isStripe = JSON.parse(localStorage.getItem("stripe"));
if (
isStripe &&
params.get("status") === "success" &&
cartItems &&
cartItems.length > 0
) {
setIsOrderProcessing(true);
const getCheckoutFormData = JSON.parse(
localStorage.getItem("checkoutFormData")
);
const createFinalCheckoutFormData = {
user: user?._id,
shippingAddress: getCheckoutFormData.shippingAddress,
orderItems: cartItems.map((item) => ({
qty: 1,
product: item.productID,
})),
paymentMethod: "Stripe",
totalPrice: cartItems.reduce(
(total, item) => item.productID.price + total,
0
),
isPaid: true,
isProcessing: true,
paidAt: new Date(),
};
const res = await createNewOrder(createFinalCheckoutFormData);
if (res.success) {
setIsOrderProcessing(false);
setOrderSuccess(true);
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
} else {
setIsOrderProcessing(false);
setOrderSuccess(false);
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
}
}
}
createFinalOrder();
}, [params.get("status"), cartItems]);
function handleSelectedAddress(getAddress) {
if (getAddress._id === selectedAddress) {
setSelectedAddress(null);
setCheckoutFormData({
...checkoutFormData,
shippingAddress: {},
});
return;
}
setSelectedAddress(getAddress._id);
setCheckoutFormData({
...checkoutFormData,
shippingAddress: {
...checkoutFormData.shippingAddress,
fullName: getAddress.fullName,
city: getAddress.city,
country: getAddress.country,
postalCode: getAddress.postalCode,
address: getAddress.address,
},
});
}
async function handleCheckout() {
const stripe = await stripePromise;
const createLineItems = cartItems.map((item) => ({
price_data: {
currency: "usd",
product_data: {
images: [item.productID.imageUrl],
name: item.productID.name,
},
unit_amount: item.productID.price * 100,
},
quantity: 1,
}));
const res = await callStripeSession(createLineItems);
setIsOrderProcessing(true);
localStorage.setItem("stripe", true);
localStorage.setItem("checkoutFormData", JSON.stringify(checkoutFormData));
const { error } = await stripe.redirectToCheckout({
sessionId: res.id,
});
console.log(error);
}
console.log(checkoutFormData);
useEffect(() => {
if (orderSuccess) {
setTimeout(() => {
// setOrderSuccess(false);
router.push("/orders");
}, [2000]);
}
}, [orderSuccess]);
if (orderSuccess) {
return (
Your payment is successfull and you will be redirected to
orders page in 2 seconds !
);
}
if (isOrderProcessing) {
return (
);
}
return (
Cart Summary
{cartItems && cartItems.length ? (
cartItems.map((item) => (
{item && item.productID && item.productID.name}
{item && item.productID && item.productID.price}
))
) : (
Your cart is empty
)}
Shipping address details
Complete your order by selecting address below
{addresses && addresses.length ? (
addresses.map((item) => (
handleSelectedAddress(item)}
key={item._id}
className={`border p-6 ${
item._id === selectedAddress ? "border-red-900" : ""
}`}
>
Name : {item.fullName}
Address : {item.address}
City : {item.city}
Country : {item.country}
PostalCode : {item.postalCode}
))
) : (
No addresses added
)}
Subtotal
$
{cartItems && cartItems.length
? cartItems.reduce(
(total, item) => item.productID.price + total,
0
)
: "0"}
Total
$
{cartItems && cartItems.length
? cartItems.reduce(
(total, item) => item.productID.price + total,
0
)
: "0"}
);
}
================================================
FILE: src/app/globals.css
================================================
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}
@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}
body {
color: rgb(var(--foreground-rgb));
min-height: 100vh;
height: 100%;
}
body::-webkit-scrollbar {
width: 5px;
}
body::-webkit-scrollbar-track {
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
body::-webkit-scrollbar-thumb {
background-color: darkgrey;
outline: 1px solid slategrey;
}
================================================
FILE: src/app/layout.js
================================================
import GlobalState from '@/context'
import './globals.css'
import { Inter } from 'next/font/google'
import Navbar from '@/components/Navbar'
const inter = Inter({ subsets: ['latin'] })
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({ children }) {
return (
{children}
)
}
================================================
FILE: src/app/login/page.js
================================================
"use client";
import InputComponent from "@/components/FormElements/InputComponent";
import ComponentLevelLoader from "@/components/Loader/componentlevel";
import Notification from "@/components/Notification";
import { GlobalContext } from "@/context";
import { login } from "@/services/login";
import { loginFormControls } from "@/utils";
import Cookies from "js-cookie";
import { useRouter } from "next/navigation";
import { useContext, useEffect, useState } from "react";
import { toast } from "react-toastify";
const initialFormdata = {
email: "",
password: "",
};
export default function Login() {
const [formData, setFormData] = useState(initialFormdata);
const {
isAuthUser,
setIsAuthUser,
user,
setUser,
componentLevelLoader,
setComponentLevelLoader,
} = useContext(GlobalContext);
const router = useRouter();
console.log(formData);
function isValidForm() {
return formData &&
formData.email &&
formData.email.trim() !== "" &&
formData.password &&
formData.password.trim() !== ""
? true
: false;
}
async function handleLogin() {
setComponentLevelLoader({ loading: true, id: "" });
const res = await login(formData);
console.log(res);
if (res.success) {
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setIsAuthUser(true);
setUser(res?.finalData?.user);
setFormData(initialFormdata);
Cookies.set("token", res?.finalData?.token);
localStorage.setItem("user", JSON.stringify(res?.finalData?.user));
setComponentLevelLoader({ loading: false, id: "" });
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setIsAuthUser(false);
setComponentLevelLoader({ loading: false, id: "" });
}
}
console.log(isAuthUser, user);
useEffect(() => {
if (isAuthUser) router.push("/");
}, [isAuthUser]);
return (
Login
{loginFormControls.map((controlItem) =>
controlItem.componentType === "input" ? (
{
setFormData({
...formData,
[controlItem.id]: event.target.value,
});
}}
/>
) : null
)}
New to website ?
);
}
================================================
FILE: src/app/orders/[order-details]/page.js
================================================
"use client";
import { GlobalContext } from "@/context";
import { getOrderDetails } from "@/services/order";
import { useParams, useRouter } from "next/navigation";
import { useContext, useEffect } from "react";
import { PulseLoader } from "react-spinners";
export default function OrderDetails() {
const {
pageLevelLoader,
setPageLevelLoader,
orderDetails,
setOrderDetails,
user,
} = useContext(GlobalContext);
const params = useParams();
const router = useRouter()
async function extractOrderDetails() {
setPageLevelLoader(true);
const res = await getOrderDetails(params["order-details"]);
if (res.success) {
setPageLevelLoader(false);
setOrderDetails(res.data);
} else {
setPageLevelLoader(false);
}
console.log(res);
}
useEffect(() => {
extractOrderDetails();
}, []);
if (pageLevelLoader) {
return (
);
}
return (
Order #{orderDetails && orderDetails._id}
{orderDetails &&
orderDetails.createdAt &&
orderDetails.createdAt.split("T")[0]}{" "}
|{" "}
{orderDetails &&
orderDetails.createdAt &&
orderDetails.createdAt.split("T")[1].split(".")[0]}
Your order summary
{orderDetails &&
orderDetails.orderItems &&
orderDetails.orderItems.length
? orderDetails.orderItems.map((item) => (
{item && item.product && item.product.name}
${item && item.product && item.product.price}
))
: null}
Summary
Subtotal
${orderDetails && orderDetails.totalPrice}
Subtotal
${orderDetails && orderDetails.totalPrice}
Customer Details
Name: {user?.name}
Email: {user?.email}
Shipping Address
Address :{" "}
{orderDetails && orderDetails.shippingAddress.address}
City :{orderDetails && orderDetails.shippingAddress.city}
Country :{" "}
{orderDetails && orderDetails.shippingAddress.country}
Postal Code :{" "}
{orderDetails && orderDetails.shippingAddress.postalCode}
);
}
================================================
FILE: src/app/orders/page.js
================================================
"use client";
import Notification from "@/components/Notification";
import { GlobalContext } from "@/context";
import { getAllOrdersForUser } from "@/services/order";
import { useRouter } from "next/navigation";
import { useContext, useEffect } from "react";
import { PulseLoader } from "react-spinners";
import { toast } from "react-toastify";
export default function Orders() {
const {
user,
pageLevelLoader,
setPageLevelLoader,
allOrdersForUser,
setAllOrdersForUser,
} = useContext(GlobalContext);
const router = useRouter();
async function extractAllOrders() {
setPageLevelLoader(true);
const res = await getAllOrdersForUser(user?._id);
if (res.success) {
setPageLevelLoader(false);
setAllOrdersForUser(res.data);
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
} else {
setPageLevelLoader(false);
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
}
}
useEffect(() => {
if (user !== null) extractAllOrders();
}, [user]);
console.log(allOrdersForUser);
if (pageLevelLoader) {
return (
);
}
return (
{allOrdersForUser && allOrdersForUser.length ? (
) : null}
);
}
================================================
FILE: src/app/page.js
================================================
"use client";
import { GlobalContext } from "@/context";
import { getAllAdminProducts } from "@/services/product";
import { useRouter } from "next/navigation";
import { useContext, useEffect, useState } from "react";
export default function Home() {
const { isAuthUser } = useContext(GlobalContext);
const [products, setProducts] = useState([]);
const router = useRouter();
async function getListOfProducts() {
const res = await getAllAdminProducts();
if (res.success) {
setProducts(res.data);
}
}
useEffect(() => {
getListOfProducts();
}, []);
console.log(products);
return (
Best Fashion Collection
Quisquemos sodales suscipit tortor ditaemcos condimentum de cosmo
lacus meleifend menean diverra loremous.
Summer Sale Collection
{products && products.length
? products
.filter((item) => item.onSale === "yes")
.splice(0, 2)
.map((productItem) => (
-
router.push(`/product/${productItem._id}`)
}
className="cursor-pointer"
key={productItem._id}
>
{productItem.name}
${productItem.price}{" "}
{`(-${productItem.priceDrop}%) Off`}
))
: null}
SHOP BY CATEGORY
-
KIDS
-
WOMEN
-
MEN
);
}
================================================
FILE: src/app/product/[details]/page.js
================================================
import CommonDetails from "@/components/CommonDetails";
import { productById } from "@/services/product";
export default async function ProductDetails({ params }) {
const productDetailsData = await productById(params.details);
console.log(productDetailsData, "sangam");
return ;
}
================================================
FILE: src/app/product/listing/all-products/page.js
================================================
import CommonListing from "@/components/CommonListing";
import { getAllAdminProducts } from "@/services/product";
export default async function AllProducts() {
const getAllProducts = await getAllAdminProducts();
return ;
}
================================================
FILE: src/app/product/listing/kids/page.js
================================================
import CommonListing from "@/components/CommonListing";
import { productByCategory } from "@/services/product";
export default async function KidsAllProducts() {
const getAllProducts = await productByCategory("kids");
return ;
}
================================================
FILE: src/app/product/listing/men/page.js
================================================
import CommonListing from "@/components/CommonListing";
import { productByCategory } from "@/services/product";
export default async function MenAllProducts() {
const getAllProducts = await productByCategory("men");
return ;
}
================================================
FILE: src/app/product/listing/women/page.js
================================================
import CommonListing from "@/components/CommonListing";
import { productByCategory } from "@/services/product";
export default async function WomenAllProducts() {
const getAllProducts = await productByCategory("women");
return ;
}
================================================
FILE: src/app/register/page.js
================================================
"use client";
import InputComponent from "@/components/FormElements/InputComponent";
import SelectComponent from "@/components/FormElements/SelectComponent";
import ComponentLevelLoader from "@/components/Loader/componentlevel";
import Notification from "@/components/Notification";
import { GlobalContext } from "@/context";
import { registerNewUser } from "@/services/register";
import { registrationFormControls } from "@/utils";
import { useRouter } from "next/navigation";
import { useContext, useEffect, useState } from "react";
import { toast } from "react-toastify";
const initialFormData = {
name: "",
email: "",
password: "",
role: "customer",
};
export default function Register() {
const [formData, setFormData] = useState(initialFormData);
const [isRegistered, setIsRegistered] = useState(false);
const { pageLevelLoader, setPageLevelLoader , isAuthUser } = useContext(GlobalContext);
const router = useRouter()
console.log(formData);
function isFormValid() {
return formData &&
formData.name &&
formData.name.trim() !== "" &&
formData.email &&
formData.email.trim() !== "" &&
formData.password &&
formData.password.trim() !== ""
? true
: false;
}
console.log(isFormValid());
async function handleRegisterOnSubmit() {
setPageLevelLoader(true);
const data = await registerNewUser(formData);
if (data.success) {
toast.success(data.message, {
position: toast.POSITION.TOP_RIGHT,
});
setIsRegistered(true);
setPageLevelLoader(false);
setFormData(initialFormData);
} else {
toast.error(data.message, {
position: toast.POSITION.TOP_RIGHT,
});
setPageLevelLoader(false);
setFormData(initialFormData);
}
console.log(data);
}
useEffect(() => {
if (isAuthUser) router.push("/");
}, [isAuthUser]);
return (
{isRegistered
? "Registration Successfull !"
: "Sign up for an account"}
{isRegistered ? (
) : (
{registrationFormControls.map((controlItem) =>
controlItem.componentType === "input" ? (
{
setFormData({
...formData,
[controlItem.id]: event.target.value,
});
}}
value={formData[controlItem.id]}
/>
) : controlItem.componentType === "select" ? (
{
setFormData({
...formData,
[controlItem.id]: event.target.value,
});
}}
value={formData[controlItem.id]}
/>
) : null
)}
)}
);
}
================================================
FILE: src/app/unauthorized-page/page.js
================================================
"use client";
export default function Unauthorized() {
return (
You don't have access to view this page!
);
}
================================================
FILE: src/components/CartModal/index.js
================================================
"use client";
import { Fragment, useContext, useEffect } from "react";
import CommonModal from "../CommonModal";
import { GlobalContext } from "@/context";
import { deleteFromCart, getAllCartItems } from "@/services/cart";
import { toast } from "react-toastify";
import ComponentLevelLoader from "../Loader/componentlevel";
import { useRouter } from "next/navigation";
export default function CartModal() {
const {
showCartModal,
setShowCartModal,
cartItems,
setCartItems,
user,
setComponentLevelLoader,
componentLevelLoader,
} = useContext(GlobalContext);
const router = useRouter();
async function extractAllCartItems() {
const res = await getAllCartItems(user?._id);
if (res.success) {
const updatedData =
res.data && res.data.length
? res.data.map((item) => ({
...item,
productID: {
...item.productID,
price:
item.productID.onSale === "yes"
? parseInt(
(
item.productID.price -
item.productID.price * (item.productID.priceDrop / 100)
).toFixed(2)
)
: item.productID.price,
},
}))
: [];
setCartItems(updatedData);
localStorage.setItem("cartItems", JSON.stringify(updatedData));
}
console.log(res);
}
useEffect(() => {
if (user !== null) extractAllCartItems();
}, [user]);
async function handleDeleteCartItem(getCartItemID) {
setComponentLevelLoader({ loading: true, id: getCartItemID });
const res = await deleteFromCart(getCartItemID);
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
extractAllCartItems();
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: getCartItemID });
}
}
return (
{cartItems.map((cartItem) => (
$
{cartItem &&
cartItem.productID &&
cartItem.productID.price}
))}
) : null
}
buttonComponent={
}
/>
);
}
================================================
FILE: src/components/CommonCart/index.js
================================================
"use client";
import { useRouter } from "next/navigation";
import ComponentLevelLoader from "../Loader/componentlevel";
export default function CommonCart({
cartItems = [],
handleDeleteCartItem,
componentLevelLoader,
}) {
const router = useRouter()
return (
{cartItems && cartItems.length ? (
{cartItems.map((cartItem) => (
-
{cartItem &&
cartItem.productID &&
cartItem.productID.name}
$
{cartItem &&
cartItem.productID &&
cartItem.productID.price}
))}
) : (
Your cart is Empty !
)}
Subtotal
$
{cartItems && cartItems.length
? cartItems.reduce(
(total, item) => item.productID.price + total,
0
)
: "0"}
Total
$
{cartItems && cartItems.length
? cartItems.reduce(
(total, item) => item.productID.price + total,
0
)
: "0"}
);
}
================================================
FILE: src/components/CommonDetails/index.js
================================================
"use client";
import { GlobalContext } from "@/context";
import { useContext } from "react";
import { toast } from "react-toastify";
import ComponentLevelLoader from "../Loader/componentlevel";
import { addToCart } from "@/services/cart";
import Notification from "../Notification";
export default function CommonDetails({ item }) {
const {
setComponentLevelLoader,
componentLevelLoader,
user,
setShowCartModal,
} = useContext(GlobalContext);
async function handleAddToCart(getItem) {
setComponentLevelLoader({ loading: true, id: "" });
const res = await addToCart({ productID: getItem._id, userID: user._id });
if (res.success) {
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: "" });
setShowCartModal(true);
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: "" });
setShowCartModal(true);
}
}
return (
{item && item.name}
${item && item.price}
{item.onSale === "yes" ? (
{`$${(
item.price -
item.price * (item.priceDrop / 100)
).toFixed(2)}`}
) : null}
-
{item && item.deliveryInfo}
-
{"Cancel anytime"}
{item && item.description}
);
}
================================================
FILE: src/components/CommonListing/ProductButtons/index.js
================================================
"use client";
import ComponentLevelLoader from "@/components/Loader/componentlevel";
import { GlobalContext } from "@/context";
import { addToCart } from "@/services/cart";
import { deleteAProduct } from "@/services/product";
import { usePathname, useRouter } from "next/navigation";
import { useContext } from "react";
import { toast } from "react-toastify";
export default function ProductButton({ item }) {
const pathName = usePathname();
const {
setCurrentUpdatedProduct,
setComponentLevelLoader,
componentLevelLoader,
user,
showCartModal, setShowCartModal
} = useContext(GlobalContext);
const router = useRouter();
const isAdminView = pathName.includes("admin-view");
async function handleDeleteProduct(item) {
setComponentLevelLoader({ loading: true, id: item._id });
const res = await deleteAProduct(item._id);
if (res.success) {
setComponentLevelLoader({ loading: false, id: "" });
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
router.refresh();
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: "" });
}
}
async function handleAddToCart(getItem) {
setComponentLevelLoader({ loading: true, id: getItem._id });
const res = await addToCart({ productID: getItem._id, userID: user._id });
if (res.success) {
toast.success(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: "" });
setShowCartModal(true);
} else {
toast.error(res.message, {
position: toast.POSITION.TOP_RIGHT,
});
setComponentLevelLoader({ loading: false, id: "" });
setShowCartModal(true)
}
console.log(res);
}
return isAdminView ? (
<>
>
) : (
<>
>
);
}
================================================
FILE: src/components/CommonListing/ProductTile/index.js
================================================
"use client";
import { useRouter } from "next/navigation";
export default function ProductTile({ item }) {
const router = useRouter();
return (
router.push(`/product/${item._id}`)}>
{item.onSale === "yes" ? (
) : null}
{`$ ${item.price}`}
{item.onSale === "yes" ? (
{`$ ${(
item.price -
item.price * (item.priceDrop / 100)
).toFixed(2)}`}
) : null}
{item.onSale === "yes" ? (
{`-(${item.priceDrop}%)off`}
) : null}
{item.name}
);
}
================================================
FILE: src/components/CommonListing/index.js
================================================
"use client";
import { useRouter } from "next/navigation";
import ProductButton from "./ProductButtons";
import ProductTile from "./ProductTile";
import { useEffect } from "react";
import Notification from "../Notification";
export default function CommonListing({ data }) {
const router = useRouter();
useEffect(() => {
router.refresh();
}, []);
return (
{data && data.length
? data.map((item) => (
))
: null}
);
}
================================================
FILE: src/components/CommonModal/index.js
================================================
"use client";
import { Dialog, Transition } from "@headlessui/react";
import { Fragment } from "react";
export default function CommonModal({
modalTitle,
mainContent,
showButtons,
buttonComponent,
show,
setShow,
showModalTitle
}) {
return (
);
}
================================================
FILE: src/components/FormElements/InputComponent/index.js
================================================
export default function InputComponent({
label,
placeholder,
onChange,
value,
type,
}) {
return (
);
}
================================================
FILE: src/components/FormElements/SelectComponent/index.js
================================================
export default function SelectComponent({
label,
value,
onChange,
options = [],
}) {
return (
{label}
);
}
================================================
FILE: src/components/FormElements/TileComponent/index.js
================================================
export default function TileComponent({ data, selected = [], onClick }) {
return data && data.length ? (
{data.map((dataItem) => (
))}
) : null;
}
================================================
FILE: src/components/Loader/componentlevel/index.js
================================================
"use client";
import { PulseLoader } from "react-spinners";
export default function ComponentLevelLoader({ text, color, loading, size }) {
return (
{text}
);
}
================================================
FILE: src/components/Navbar/index.js
================================================
"use client";
import { GlobalContext } from "@/context";
import { adminNavOptions, navOptions } from "@/utils";
import { Fragment, useContext, useEffect } from "react";
import CommonModal from "../CommonModal";
import Cookies from "js-cookie";
import { usePathname, useRouter } from "next/navigation";
import CartModal from "../CartModal";
function NavItems({ isModalView = false, isAdminView, router }) {
return (
{isAdminView
? adminNavOptions.map((item) => (
- router.push(item.path)}
>
{item.label}
))
: navOptions.map((item) => (
- router.push(item.path)}
>
{item.label}
))}
);
}
export default function Navbar() {
const { showNavModal, setShowNavModal } = useContext(GlobalContext);
const {
user,
isAuthUser,
setIsAuthUser,
setUser,
currentUpdatedProduct,
setCurrentUpdatedProduct,
showCartModal,
setShowCartModal
} = useContext(GlobalContext);
const pathName = usePathname();
const router = useRouter();
console.log(currentUpdatedProduct, "navbar");
useEffect(() => {
if (
pathName !== "/admin-view/add-product" &&
currentUpdatedProduct !== null
)
setCurrentUpdatedProduct(null);
}, [pathName]);
function handleLogout() {
setIsAuthUser(false);
setUser(null);
Cookies.remove("token");
localStorage.clear();
router.push("/");
}
const isAdminView = pathName.includes("admin-view");
return (
<>
}
show={showNavModal}
setShow={setShowNavModal}
/>
{showCartModal && }
>
);
}
================================================
FILE: src/components/Notification/index.js
================================================
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
export default function Notification() {
return (
);
}
================================================
FILE: src/context/index.js
================================================
"use client";
import Cookies from "js-cookie";
import { usePathname, useRouter } from "next/navigation";
import { createContext, useEffect, useState } from "react";
export const GlobalContext = createContext(null);
export const initialCheckoutFormData = {
shippingAddress: {},
paymentMethod: "",
totalPrice: 0,
isPaid: false,
paidAt: new Date(),
isProcessing: true,
};
const protectedRoutes = ["cart", "checkout", "account", "orders", "admin-view"];
const protectedAdminRoutes = [
"/admin-view",
"/admin-view/add-product",
"/admin-view/all-products",
];
export default function GlobalState({ children }) {
const [showNavModal, setShowNavModal] = useState(false);
const [pageLevelLoader, setPageLevelLoader] = useState(true);
const [componentLevelLoader, setComponentLevelLoader] = useState({
loading: false,
id: "",
});
const [isAuthUser, setIsAuthUser] = useState(null);
const [user, setUser] = useState(null);
const [currentUpdatedProduct, setCurrentUpdatedProduct] = useState(null);
const [showCartModal, setShowCartModal] = useState(false);
const [cartItems, setCartItems] = useState([]);
const [addresses, setAddresses] = useState([]);
const [addressFormData, setAddressFormData] = useState({
fullName: "",
city: "",
country: "",
postalCode: "",
address: "",
});
const [checkoutFormData, setCheckoutFormData] = useState(
initialCheckoutFormData
);
const [allOrdersForUser, setAllOrdersForUser] = useState([]);
const [orderDetails, setOrderDetails] = useState(null);
const [allOrdersForAllUsers, setAllOrdersForAllUsers] = useState([]);
const router = useRouter();
const pathName = usePathname();
useEffect(() => {
if (Cookies.get("token") !== undefined) {
setIsAuthUser(true);
const userData = JSON.parse(localStorage.getItem("user")) || {};
const getCartItems = JSON.parse(localStorage.getItem("cartItems")) || [];
setUser(userData);
setCartItems(getCartItems);
} else {
setIsAuthUser(false);
setUser({}); //unauthenticated user
}
}, [Cookies]);
useEffect(() => {
if (
pathName !== "/register" &&
!pathName.includes("product") &&
pathName !== "/" &&
user &&
Object.keys(user).length === 0 &&
protectedRoutes.includes(pathName) > -1
)
router.push("/login");
}, [user, pathName]);
useEffect(() => {
if (
user !== null &&
user &&
Object.keys(user).length > 0 &&
user?.role !== "admin" &&
protectedAdminRoutes.indexOf(pathName) > -1
)
router.push("/unauthorized-page");
}, [user, pathName]);
return (
{children}
);
}
================================================
FILE: src/database/index.js
================================================
import mongoose from "mongoose";
const configOptions = {
useNewUrlParser: true,
useUnifiedTopology: true,
};
const connectToDB = async () => {
const connectionUrl =
"your-mongodb-url";
mongoose
.connect(connectionUrl, configOptions)
.then(() => console.log("Ecommerce database connected successfully!"))
.catch((err) =>
console.log(`Getting Error from DB connection ${err.message}`)
);
};
export default connectToDB;
================================================
FILE: src/middleware/AuthUser.js
================================================
import jwt from "jsonwebtoken";
export const dynamic = "force-dynamic";
const AuthUser = async (req) => {
const token = req.headers.get("Authorization")?.split(" ")[1];
if (!token) return false;
try {
const extractAuthUserInfo = jwt.verify(token, "default_secret_key");
if (extractAuthUserInfo) return extractAuthUserInfo;
} catch (e) {
console.log(e);
return false;
}
};
export default AuthUser;
================================================
FILE: src/models/address.js
================================================
import mongoose from "mongoose";
const NewAddressSchema = new mongoose.Schema(
{
userID: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
fullName: String,
address: String,
city: String,
country: String,
postalCode: String,
},
{ timestamps: true }
);
const Address =
mongoose.models.Address || mongoose.model("Address", NewAddressSchema);
export default Address;
================================================
FILE: src/models/cart.js
================================================
import mongoose from "mongoose";
const CartSchema = new mongoose.Schema(
{
userID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
productID: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Products',
},
quantity: {
type: Number,
required: true,
default: 1,
},
},
{ timestamps: true }
);
const Cart = mongoose.models.Cart || mongoose.model("Cart", CartSchema);
export default Cart;
================================================
FILE: src/models/order.js
================================================
import mongoose from "mongoose";
import Product from "./product";
import User from "./user";
const OrderSchema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
required: true,
},
orderItems: [
{
qty: { type: Number, required: true },
product: {
type: mongoose.Schema.Types.ObjectId,
ref: "Products",
},
},
],
shippingAddress: {
fullName: { type: String, required: true },
address: { type: String, required: true },
city: { type: String, required: true },
country: { type: String, required: true },
postalCode: { type: String, required: true },
},
paymentMethod: { type: String, required: true, default: "Stripe" },
totalPrice: { type: Number, required: true },
isPaid: { type: Boolean, required: true },
paidAt: { type: Date, required: true },
isProcessing: { type: Boolean, required: true },
},
{ timestamps: true }
);
const Order = mongoose.models.Order || mongoose.model("Order", OrderSchema);
export default Order;
================================================
FILE: src/models/product.js
================================================
import mongoose from "mongoose";
const ProductSchema = new mongoose.Schema(
{
name: String,
description: String,
price: Number,
category: String,
sizes: Array,
deliveryInfo: String,
onSale: String,
priceDrop: Number,
imageUrl: String,
},
{ timestamps: true }
);
const Product =
mongoose.models.Products || mongoose.model("Products", ProductSchema);
export default Product;
================================================
FILE: src/models/user.js
================================================
import mongoose from "mongoose";
const UserSchema = new mongoose.Schema({
name: String,
email: String,
password: String,
role: String,
});
const User = mongoose.models.User || mongoose.model("User", UserSchema);
export default User;
================================================
FILE: src/services/address/index.js
================================================
import Cookies from "js-cookie";
export const addNewAddress = async (formData) => {
try {
const res = await fetch("/api/address/add-new-address", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const fetchAllAddresses = async (id) => {
try {
const res = await fetch(`/api/address/get-all-address?id=${id}`, {
method: "GET",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const updateAddress = async (formData) => {
try {
const res = await fetch("/api/address/update-address", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const deleteAddress = async (id) => {
try {
const res = await fetch(`/api/address/delete-address?id=${id}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
================================================
FILE: src/services/cart/index.js
================================================
import Cookies from "js-cookie";
export const addToCart = async (formData) => {
try {
const res = await fetch("/api/cart/add-to-cart", {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const getAllCartItems = async (id) => {
try {
const res = await fetch(`http://localhost:3000/api/cart/all-cart-items?id=${id}`, {
method: "GET",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const deleteFromCart = async (id) => {
try {
const res = await fetch(`/api/cart/delete-from-cart?id=${id}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
================================================
FILE: src/services/login/index.js
================================================
export const login = async (formData) => {
try {
const response = await fetch("/api/login", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(formData),
});
const data = await response.json();
return data;
} catch (error) {
console.log(error);
}
};
================================================
FILE: src/services/order/index.js
================================================
import Cookies from "js-cookie";
export const createNewOrder = async (formData) => {
try {
const res = await fetch("/api/order/create-order", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const getAllOrdersForUser = async (id) => {
try {
const res = await fetch(`/api/order/get-all-orders?id=${id}`, {
method: "GET",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const getOrderDetails = async (id) => {
try {
const res = await fetch(`/api/order/order-details?id=${id}`, {
method: "GET",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const getAllOrdersForAllUsers = async () => {
try {
const res = await fetch(`/api/admin/orders/get-all-orders`, {
method: "GET",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const updateStatusOfOrder = async (formData) => {
try {
const res = await fetch(`/api/admin/orders/update-order`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
================================================
FILE: src/services/product/index.js
================================================
//add a new product service
import Cookies from "js-cookie";
export const addNewProduct = async (formData) => {
try {
const response = await fetch("/api/admin/add-product", {
method: "POST",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await response.json();
return data;
} catch (error) {
console.log(error);
}
};
export const getAllAdminProducts = async () => {
try {
const res = await fetch("http://localhost:3000/api/admin/all-products", {
method: "GET",
cache: "no-store",
});
const data = await res.json();
return data;
} catch (error) {
console.log(error);
}
};
export const updateAProduct = async (formData) => {
try {
const res = await fetch("/api/admin/update-product", {
method: "PUT",
headers: {
"content-type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
cache: "no-store",
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const deleteAProduct = async (id) => {
try {
const res = await fetch(`/api/admin/delete-product?id=${id}`, {
method: "DELETE",
headers: {
Authorization: `Bearer ${Cookies.get("token")}`,
},
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const productByCategory = async (id) => {
try {
const res = await fetch(
`http://localhost:3000/api/admin/product-by-category?id=${id}`,
{
method: "GET",
cache: "no-store",
}
);
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
export const productById = async (id) => {
try {
const res = await fetch(
`http://localhost:3000/api/admin/product-by-id?id=${id}`,
{
method: "GET",
cache: "no-store",
}
);
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
================================================
FILE: src/services/register/index.js
================================================
export const registerNewUser = async (formData) => {
try {
const response = await fetch("/api/register", {
method: "POST",
headers: {
"content-type": "application/json",
},
body: JSON.stringify(formData),
});
const finalData = await response.json();
return finalData;
} catch (e) {
console.log("error", e);
}
};
================================================
FILE: src/services/stripe/index.js
================================================
import Cookies from "js-cookie";
export const callStripeSession = async (formData) => {
try {
const res = await fetch("/api/stripe", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${Cookies.get("token")}`,
},
body: JSON.stringify(formData),
});
const data = await res.json();
return data;
} catch (e) {
console.log(e);
}
};
================================================
FILE: src/utils/index.js
================================================
export const navOptions = [
{
id: "home",
label: "Home",
path: "/",
},
{
id: "listing",
label: "All Products",
path: "/product/listing/all-products",
},
{
id: "listingMen",
label: "Men",
path: "/product/listing/men",
},
{
id: "listingWomen",
label: "Women",
path: "/product/listing/women",
},
{
id: "listingKids",
label: "kids",
path: "/product/listing/kids",
},
];
export const adminNavOptions = [
{
id: "adminListing",
label: "Manage All Products",
path: "/admin-view/all-products",
},
{
id: "adminNewProduct",
label: "Add New Product",
path: "/admin-view/add-product",
},
];
export const registrationFormControls = [
{
id: "name",
type: "text",
placeholder: "Enter your name",
label: "Name",
componentType: "input",
},
{
id: "email",
type: "email",
placeholder: "Enter your email",
label: "Email",
componentType: "input",
},
{
id: "password",
type: "password",
placeholder: "Enter your password",
label: "Password",
componentType: "input",
},
{
id: "role",
type: "",
placeholder: "",
label: "Role",
componentType: "select",
options: [
{
id: "admin",
label: "Admin",
},
{
id: "customer",
label: "customer",
},
],
},
];
export const loginFormControls = [
{
id: "email",
type: "email",
placeholder: "Enter your email",
label: "Email",
componentType: "input",
},
{
id: "password",
type: "password",
placeholder: "Enter your password",
label: "Password",
componentType: "input",
},
];
export const adminAddProductformControls = [
{
id: "name",
type: "text",
placeholder: "Enter name",
label: "Name",
componentType: "input",
},
{
id: "price",
type: "number",
placeholder: "Enter price",
label: "Price",
componentType: "input",
},
{
id: "description",
type: "text",
placeholder: "Enter description",
label: "Description",
componentType: "input",
},
{
id: "category",
type: "",
placeholder: "",
label: "Category",
componentType: "select",
options: [
{
id: "men",
label: "Men",
},
{
id: "women",
label: "Women",
},
{
id: "kids",
label: "Kids",
},
],
},
{
id: "deliveryInfo",
type: "text",
placeholder: "Enter deliveryInfo",
label: "Delivery Info",
componentType: "input",
},
{
id: "onSale",
type: "",
placeholder: "",
label: "On Sale",
componentType: "select",
options: [
{
id: "yes",
label: "Yes",
},
{
id: "no",
label: "No",
},
],
},
{
id: "priceDrop",
type: "number",
placeholder: "Enter Price Drop",
label: "Price Drop",
componentType: "input",
},
];
export const AvailableSizes = [
{
id: "s",
label: "S",
},
{
id: "m",
label: "M",
},
{
id: "l",
label: "L",
},
];
export const firebaseConfig = {
apiKey: "API_KEY",
authDomain: "AUTH_DOMAIN",
projectId: "PROJECT_ID",
storageBucket: "STROAGE_BUCKET",
messagingSenderId: "MESSAGING_SENDER_ID",
appId: "APP_ID",
measurementId: "MEASUREMENT_ID",
};
export const firebaseStroageURL =
"YOUR_FIREBASE_STROAGE_URL";
export const addNewAddressFormControls = [
{
id: "fullName",
type: "input",
placeholder: "Enter your full name",
label: "Full Name",
componentType: "input",
},
{
id: "address",
type: "input",
placeholder: "Enter your full address",
label: "Address",
componentType: "input",
},
{
id: "city",
type: "input",
placeholder: "Enter your city",
label: "City",
componentType: "input",
},
{
id: "country",
type: "input",
placeholder: "Enter your country",
label: "Country",
componentType: "input",
},
{
id: "postalCode",
type: "input",
placeholder: "Enter your postal code",
label: "Postal Code",
componentType: "input",
},
];
================================================
FILE: tailwind.config.js
================================================
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./src/pages/**/*.{js,ts,jsx,tsx,mdx}',
'./src/components/**/*.{js,ts,jsx,tsx,mdx}',
'./src/app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
},
},
plugins: [],
}