├── src ├── components │ ├── Blog │ │ ├── Blog.css │ │ └── Blog.js │ ├── AdminPanel │ │ ├── Order │ │ │ ├── Order.css │ │ │ ├── AdminPlaceOrder.js │ │ │ └── Orders.js │ │ ├── Billing │ │ │ ├── Billing.js │ │ │ ├── Requests.js │ │ │ ├── Transactions.js │ │ │ └── PreviousTransactions.js │ │ ├── Analytics │ │ │ └── Analytics.js │ │ ├── Support │ │ │ ├── Support.js │ │ │ ├── Support.css │ │ │ ├── SupportSideBar.js │ │ │ └── SupportContent.js │ │ ├── AdminPanel.js │ │ ├── Navigation │ │ │ ├── AdminAppBar.js │ │ │ ├── AdminPanelNavbar.js │ │ │ └── AdminContentPanel.js │ │ ├── Book │ │ │ ├── Book.css │ │ │ ├── AdminFindBook.js │ │ │ ├── BookVerification │ │ │ │ ├── AdminBookDelete.js │ │ │ │ └── AdminBookApprove.js │ │ │ └── Book.js │ │ ├── AdminPanel.css │ │ └── UserProfile.js │ ├── auth │ │ ├── signup │ │ │ ├── signup.css │ │ │ └── verify.js │ │ ├── auth.css │ │ └── recovery │ │ │ └── recovery.css │ ├── MicroComponents │ │ ├── MicroComponents.css │ │ ├── BookshlfLoader.js │ │ ├── customCopyText.js │ │ └── Mail.js │ ├── search │ │ ├── searchresults.js │ │ ├── pagination.js │ │ ├── search.js │ │ ├── searchbook.js │ │ ├── search.css │ │ └── searchfilter.js │ ├── home │ │ ├── NotFoundPage.js │ │ ├── Categories.css │ │ ├── home.js │ │ ├── Categories.js │ │ ├── home.css │ │ └── Benefits.js │ ├── navbar │ │ ├── navbarlinks.js │ │ ├── navbarsearch.js │ │ └── navbarmenu.js │ ├── BookDetails │ │ ├── BookDetails.css │ │ ├── BookPurchaseAdmin.js │ │ └── Booksnaps.js │ ├── userpanel │ │ ├── usernav.js │ │ ├── userpanel.css │ │ ├── profile.js │ │ └── userpanel.js │ ├── Footer │ │ └── Footer.css │ ├── Checkout │ │ ├── CheckoutLoading.js │ │ ├── CheckoutOrderReview.js │ │ ├── CheckoutPayment.js │ │ ├── CheckoutAddress.js │ │ ├── CheckoutOrderPlace.js │ │ └── CheckoutStepper.js │ ├── Order │ │ └── tracking │ │ │ ├── tracking.js │ │ │ ├── tracking.css │ │ │ ├── trackprogress.js │ │ │ └── trackingstepper.js │ ├── Wallet │ │ └── Wallet.css │ ├── About │ │ ├── AboutSocial.js │ │ └── About.js │ ├── SellerPanel │ │ └── SellerPanel.css │ ├── Book │ │ └── AddBook.css │ └── AddressBook │ │ ├── AddressDetails.js │ │ └── AddressList.js ├── service │ ├── auth │ │ ├── verification.js │ │ ├── recovery.js │ │ ├── logout.js │ │ ├── login.js │ │ └── signup.js │ ├── AdminPanel │ │ └── Analytics │ │ │ ├── Analytics.js │ │ │ └── OrdersAnalytics.js │ ├── search │ │ └── booksearch.js │ └── Book │ │ └── AdminBookPurchase │ │ └── purchaseOrder.js ├── assets │ ├── Theme │ │ ├── fonts.js │ │ └── colors.js │ ├── components │ │ ├── input │ │ │ ├── textfield.js │ │ │ ├── passwordfield.js │ │ │ └── otpfield.js │ │ ├── buttons │ │ │ ├── button.js │ │ │ ├── bookbutton.js │ │ │ ├── loadingbutton.js │ │ │ ├── ordercancelbutton.js │ │ │ ├── cartbutton.js │ │ │ └── wishlistbutton.js │ │ ├── links │ │ │ ├── navlink.js │ │ │ ├── link.js │ │ │ └── links.css │ │ ├── container.js │ │ ├── pageloader.js │ │ └── base.css │ ├── counter.js │ └── utils │ │ ├── date.js │ │ └── commons.js ├── api │ ├── debounce.js │ ├── axios.js │ ├── requests │ │ ├── deleteAPI.js │ │ ├── postAPI.js │ │ └── getAPI.js │ └── endpoints.js ├── index.css ├── reportWebVitals.js ├── app │ ├── app.css │ └── app.js ├── context │ ├── adminContext.js │ └── userContext.js ├── index.js └── route │ └── router.js ├── .prettierignore ├── Demo.env.txt ├── public ├── images │ ├── ghost.png │ ├── india.png │ ├── logo.png │ ├── user.png │ ├── favicon.ico │ ├── logoView.png │ ├── smallLogo.png │ ├── userprofile.png │ ├── Benefits │ │ ├── book.png │ │ ├── easy.png │ │ ├── package.png │ │ ├── support.png │ │ ├── doorstep.png │ │ └── free-delivery.png │ ├── favicon-32x32.ico │ ├── smallLogoView.png │ ├── Categories │ │ ├── school.png │ │ ├── cbse-logo.png │ │ ├── novel-logo.jpg │ │ ├── neet-ug-logo.png │ │ ├── jeemains-logo.png │ │ └── JEE-Advance-Logo.png │ ├── Carousel │ │ ├── CarouselMobile │ │ │ ├── Carousel_bg1.png │ │ │ ├── Carousel_bg2.png │ │ │ ├── Carousel_bg3.png │ │ │ ├── Carousel_bg4.png │ │ │ ├── Carousel_bg5.png │ │ │ └── Carousel_bg6.png │ │ └── CarouselDesktop │ │ │ ├── Carousel_bg1.png │ │ │ ├── Carousel_bg2.png │ │ │ ├── Carousel_bg3.png │ │ │ ├── Carousel_bg4.png │ │ │ ├── Carousel_bg5.png │ │ │ └── Carousel_bg6.png │ ├── smallLogo.svg │ └── enviaLogo.svg ├── robots.txt ├── manifest.json ├── sitemap.xml └── index.html ├── .prettierrc ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── .gitignore ├── LICENSE └── package.json /src/components/Blog/Blog.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/service/auth/verification.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Order/Order.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Billing/Billing.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Billing/Requests.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/service/AdminPanel/Analytics/Analytics.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Billing/Transactions.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Billing/PreviousTransactions.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/.prettierignore -------------------------------------------------------------------------------- /src/assets/Theme/fonts.js: -------------------------------------------------------------------------------- 1 | // Main Font 2 | export const DMsans = "'DM Sans', sans-serif"; 3 | -------------------------------------------------------------------------------- /Demo.env.txt: -------------------------------------------------------------------------------- 1 | REACT_APP_BOOKSHLF=https://bookshlf.herokuapp.com/ 2 | REACT_APP_NODE_ENV=development -------------------------------------------------------------------------------- /public/images/ghost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/ghost.png -------------------------------------------------------------------------------- /public/images/india.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/india.png -------------------------------------------------------------------------------- /public/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/logo.png -------------------------------------------------------------------------------- /public/images/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/user.png -------------------------------------------------------------------------------- /public/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/favicon.ico -------------------------------------------------------------------------------- /public/images/logoView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/logoView.png -------------------------------------------------------------------------------- /public/images/smallLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/smallLogo.png -------------------------------------------------------------------------------- /public/images/userprofile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/userprofile.png -------------------------------------------------------------------------------- /public/images/Benefits/book.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Benefits/book.png -------------------------------------------------------------------------------- /public/images/Benefits/easy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Benefits/easy.png -------------------------------------------------------------------------------- /public/images/favicon-32x32.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/favicon-32x32.ico -------------------------------------------------------------------------------- /public/images/smallLogoView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/smallLogoView.png -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": false 6 | } 7 | -------------------------------------------------------------------------------- /public/images/Benefits/package.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Benefits/package.png -------------------------------------------------------------------------------- /public/images/Benefits/support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Benefits/support.png -------------------------------------------------------------------------------- /public/images/Benefits/doorstep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Benefits/doorstep.png -------------------------------------------------------------------------------- /public/images/Categories/school.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Categories/school.png -------------------------------------------------------------------------------- /public/images/Categories/cbse-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Categories/cbse-logo.png -------------------------------------------------------------------------------- /public/images/Categories/novel-logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Categories/novel-logo.jpg -------------------------------------------------------------------------------- /public/images/Benefits/free-delivery.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Benefits/free-delivery.png -------------------------------------------------------------------------------- /public/images/Categories/neet-ug-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Categories/neet-ug-logo.png -------------------------------------------------------------------------------- /public/images/Categories/jeemains-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Categories/jeemains-logo.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Allow: / 4 | 5 | Sitemap: https://rohit-kumar.me/sitemap.xml -------------------------------------------------------------------------------- /public/images/Categories/JEE-Advance-Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Categories/JEE-Advance-Logo.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselMobile/Carousel_bg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselMobile/Carousel_bg1.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselMobile/Carousel_bg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselMobile/Carousel_bg2.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselMobile/Carousel_bg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselMobile/Carousel_bg3.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselMobile/Carousel_bg4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselMobile/Carousel_bg4.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselMobile/Carousel_bg5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselMobile/Carousel_bg5.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselMobile/Carousel_bg6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselMobile/Carousel_bg6.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselDesktop/Carousel_bg1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselDesktop/Carousel_bg1.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselDesktop/Carousel_bg2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselDesktop/Carousel_bg2.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselDesktop/Carousel_bg3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselDesktop/Carousel_bg3.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselDesktop/Carousel_bg4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselDesktop/Carousel_bg4.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselDesktop/Carousel_bg5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselDesktop/Carousel_bg5.png -------------------------------------------------------------------------------- /public/images/Carousel/CarouselDesktop/Carousel_bg6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bookshlf-in/Website/HEAD/public/images/Carousel/CarouselDesktop/Carousel_bg6.png -------------------------------------------------------------------------------- /src/components/AdminPanel/Order/AdminPlaceOrder.js: -------------------------------------------------------------------------------- 1 | const AdminPlaceOrder = () => { 2 | return

Place Order Coming Soon

; 3 | }; 4 | 5 | export default AdminPlaceOrder; 6 | -------------------------------------------------------------------------------- /src/components/Blog/Blog.js: -------------------------------------------------------------------------------- 1 | import { React } from "react"; 2 | const Blog = () => { 3 | return ( 4 |
5 |

Blogs Coming Soon...

6 |
7 | ); 8 | }; 9 | 10 | export default Blog; 11 | -------------------------------------------------------------------------------- /src/components/auth/signup/signup.css: -------------------------------------------------------------------------------- 1 | .signUp-bg .Mui-disabled, 2 | .signUp-bg input.Mui-disabled { 3 | color: rgba(255, 255, 255, 0.6) !important; 4 | -webkit-text-fill-color: rgba(255, 255, 255, 0.6) !important; 5 | } 6 | -------------------------------------------------------------------------------- /src/assets/components/input/textfield.js: -------------------------------------------------------------------------------- 1 | import { TextField } from "@mui/material"; 2 | 3 | const InputTextField = (props) => { 4 | return ; 5 | }; 6 | 7 | export default InputTextField; 8 | -------------------------------------------------------------------------------- /src/api/debounce.js: -------------------------------------------------------------------------------- 1 | export const debounce = (func, timeout = 500) => { 2 | let timer; 3 | return (...args) => { 4 | clearTimeout(timer); 5 | timer = setTimeout(() => { 6 | func.apply(this, args); 7 | }, timeout); 8 | }; 9 | }; 10 | -------------------------------------------------------------------------------- /src/assets/components/buttons/button.js: -------------------------------------------------------------------------------- 1 | import { Button } from "@mui/material"; 2 | 3 | const SimpleButton = (props) => { 4 | return ( 5 | 8 | ); 9 | }; 10 | 11 | export default SimpleButton; 12 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "monthly" 7 | commit-message: 8 | prefix: "Dependency Update: " 9 | assignees: 10 | - "mrhb787" 11 | labels: 12 | - "dependency" 13 | target-branch: "dev" 14 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=DM+Sans&display=swap'); 2 | 3 | * { 4 | margin: 0; 5 | padding: 0; 6 | box-sizing: border-box; 7 | scroll-behavior: smooth; 8 | font-family: 'DM Sans', sans-serif; 9 | } 10 | 11 | body { 12 | overflow-y: auto; 13 | scrollbar-gutter: stable; 14 | } -------------------------------------------------------------------------------- /src/service/auth/recovery.js: -------------------------------------------------------------------------------- 1 | import { PostRequest } from "../../api/requests/postAPI"; 2 | import { passwordReset } from "../../api/endpoints"; 3 | 4 | export const handleResetPassword = async (requestBody) => { 5 | // console.log(requestBody); 6 | const response = await PostRequest(passwordReset, requestBody); 7 | return response; 8 | }; 9 | -------------------------------------------------------------------------------- /src/assets/Theme/colors.js: -------------------------------------------------------------------------------- 1 | // primary 2 | export const primary = "#F4A946"; 3 | 4 | // secondary 5 | export const secondary = "#1E1E1E"; 6 | 7 | // disabled 8 | export const disabled = "#99A2A5"; 9 | 10 | // error 11 | export const error = "#FF564F"; 12 | 13 | // customs 14 | 15 | // bookshlf-white 16 | export const bookshlfWhite = "#FDFDFD"; 17 | -------------------------------------------------------------------------------- /src/assets/components/links/navlink.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import "./links.css"; 3 | 4 | const NavLink = ({ path, name, active = false }) => { 5 | return ( 6 | 7 |
8 | {name} 9 |
10 | 11 | ); 12 | }; 13 | 14 | export default NavLink; 15 | -------------------------------------------------------------------------------- /src/components/auth/auth.css: -------------------------------------------------------------------------------- 1 | /* Login */ 2 | .auth-container { 3 | padding: 10px 15px; 4 | width: 100%; 5 | max-width: 600px; 6 | 7 | } 8 | 9 | .auth-title { 10 | text-align: center; 11 | } 12 | 13 | .login-links { 14 | padding: 0px 15px; 15 | } 16 | 17 | @media screen and (max-width: 600px) { 18 | .auth-title { 19 | font-size: 2em !important; 20 | } 21 | } -------------------------------------------------------------------------------- /src/components/MicroComponents/MicroComponents.css: -------------------------------------------------------------------------------- 1 | /* ========== Bookshlf Loader ========== */ 2 | .bookshlf-loader { 3 | animation: fadeinout 1s infinite; 4 | height: auto; 5 | width: 70px; 6 | margin: 10px; 7 | } 8 | 9 | @keyframes fadeinout { 10 | 0% { 11 | opacity: 0; 12 | transform: rotateY(0deg); 13 | } 14 | 15 | 100% { 16 | opacity: 1; 17 | transform: rotateY(360deg); 18 | } 19 | } -------------------------------------------------------------------------------- /src/api/axios.js: -------------------------------------------------------------------------------- 1 | import axios from "axios"; 2 | 3 | const instance = axios.create({ 4 | baseURL: process.env.REACT_APP_BOOKSHLF, 5 | withCredentials: true, 6 | }); 7 | 8 | const bookshlf_user = JSON.parse(localStorage.getItem("bookshlf_user")); 9 | 10 | if (bookshlf_user?.authHeader) { 11 | instance.defaults.headers.common["Authorization"] = bookshlf_user.authHeader; 12 | } 13 | 14 | export default instance; 15 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = (onPerfEntry) => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import("web-vitals").then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/assets/components/links/link.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | import { Typography } from "@mui/material"; 3 | const BaseLink = ({ path, isExternal = false, name }) => { 4 | return ( 5 | 9 | {name} 10 | 11 | ); 12 | }; 13 | 14 | export default BaseLink; 15 | -------------------------------------------------------------------------------- /src/assets/components/buttons/bookbutton.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | import { Button } from "@mui/material"; 3 | 4 | const BookButton = ({ book, ...props }) => { 5 | const navigate = useNavigate(); 6 | return ( 7 | 14 | ); 15 | }; 16 | 17 | export default BookButton; 18 | -------------------------------------------------------------------------------- /src/assets/counter.js: -------------------------------------------------------------------------------- 1 | import { Typography } from "@mui/material"; 2 | import { useEffect } from "react"; 3 | 4 | const Counter = ({ counter, setCounter, typographyProps }) => { 5 | // OTP Countdown 6 | useEffect(() => { 7 | const timer = 8 | counter > 0 && setInterval(() => setCounter(counter - 1), 1000); 9 | return () => clearInterval(timer); 10 | }, [counter]); 11 | 12 | return 00:{counter}; 13 | }; 14 | 15 | export default Counter; 16 | -------------------------------------------------------------------------------- /src/service/auth/logout.js: -------------------------------------------------------------------------------- 1 | import { GetRequest } from "../../api/requests/getAPI"; 2 | import { logout } from "../../api/endpoints"; 3 | import axios from "../../api/axios"; 4 | 5 | export const Logout = async () => { 6 | const response = await GetRequest(logout); 7 | if (response.success) { 8 | localStorage.removeItem("bookshlf_user"); 9 | localStorage.removeItem("bookshlf_user_AddBook"); 10 | delete axios.defaults.headers.common["Authorization"]; 11 | } 12 | return response; 13 | }; 14 | -------------------------------------------------------------------------------- /src/components/MicroComponents/BookshlfLoader.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import "./MicroComponents.css"; 3 | 4 | // Mui Components 5 | import { Stack } from "@mui/material"; 6 | 7 | const BookshlfLoader = (props) => { 8 | return ( 9 | 10 | bookshlf-custom-loader 16 | 17 | ); 18 | }; 19 | export default BookshlfLoader; 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # ide 4 | .vscode 5 | 6 | # dependencies 7 | /node_modules 8 | /.pnp 9 | .pnp.js 10 | 11 | # testing 12 | /coverage 13 | 14 | # production 15 | /build 16 | .firebaserc 17 | firebase.json 18 | /.firebase 19 | 20 | #api keys 21 | .env 22 | 23 | # misc 24 | .DS_Store 25 | .env.local 26 | .env.development.local 27 | .env.test.local 28 | .env.production.local 29 | 30 | #logs 31 | npm-debug.log* 32 | yarn-debug.log* 33 | yarn-error.log* 34 | -------------------------------------------------------------------------------- /src/app/app.css: -------------------------------------------------------------------------------- 1 | /* width */ 2 | ::-webkit-scrollbar { 3 | width: 5px; 4 | height: 5px; 5 | } 6 | 7 | /* Track */ 8 | ::-webkit-scrollbar-track { 9 | background: transparent; 10 | overflow: overlay; 11 | } 12 | 13 | /* Handle */ 14 | ::-webkit-scrollbar-thumb { 15 | background: rgb(255, 182, 73); 16 | border-radius: 5px; 17 | transition: height 0.2s ease-in-out; 18 | } 19 | 20 | /* Handle on hover */ 21 | ::-webkit-scrollbar-thumb:hover { 22 | background: rgb(243, 155, 23); 23 | } 24 | 25 | a { 26 | text-decoration: none; 27 | cursor: pointer; 28 | } -------------------------------------------------------------------------------- /src/assets/components/buttons/loadingbutton.js: -------------------------------------------------------------------------------- 1 | import { Button, CircularProgress } from "@mui/material"; 2 | const LoadingButton = ({ loading, size, children, ...props }) => { 3 | return ( 4 | 18 | ); 19 | }; 20 | 21 | export default LoadingButton; 22 | -------------------------------------------------------------------------------- /src/components/search/searchresults.js: -------------------------------------------------------------------------------- 1 | import { Grid } from "@mui/material"; 2 | import SearchBook from "./searchbook"; 3 | 4 | const SearchResult = ({ books }) => { 5 | return ( 6 | 12 | {books.map((book) => { 13 | return ( 14 | 15 | 16 | 17 | ); 18 | })} 19 | 20 | ); 21 | }; 22 | 23 | export default SearchResult; 24 | -------------------------------------------------------------------------------- /src/service/auth/login.js: -------------------------------------------------------------------------------- 1 | import { login } from "../../api/endpoints"; 2 | import { PostRequest } from "../../api/requests/postAPI"; 3 | import axios from "../../api/axios"; 4 | 5 | export const handleLogin = async (requestBody) => { 6 | const response = await PostRequest(login, requestBody); 7 | if (response.success) { 8 | axios.defaults.headers.common[ 9 | "Authorization" 10 | ] = `Bearer ${response.data.token}`; 11 | localStorage.setItem( 12 | "bookshlf_user", 13 | JSON.stringify({ 14 | authHeader: `Bearer ${response.data.token}`, 15 | }) 16 | ); 17 | } 18 | return response; 19 | }; 20 | -------------------------------------------------------------------------------- /src/api/requests/deleteAPI.js: -------------------------------------------------------------------------------- 1 | import axios from "../axios"; 2 | import { PrintInUATEnvironment } from "../../assets/utils/commons"; 3 | 4 | export const DeleteRequest = async (requestURL, data) => { 5 | const response = await axios 6 | .delete(requestURL, { data: data }) 7 | .then((res) => { 8 | return { data: res.data, success: true }; 9 | }) 10 | .catch((err) => { 11 | return { data: err.response.data, success: false }; 12 | }); 13 | const Request = { 14 | type: "DELETE", 15 | url: requestURL, 16 | params: data, 17 | response: response, 18 | }; 19 | PrintInUATEnvironment(Request); 20 | return response; 21 | }; 22 | -------------------------------------------------------------------------------- /src/api/requests/postAPI.js: -------------------------------------------------------------------------------- 1 | import axios from "../axios"; 2 | import { PrintInUATEnvironment } from "../../assets/utils/commons"; 3 | 4 | export const PostRequest = async (requestURL, requestBody) => { 5 | const response = await axios 6 | .post(requestURL, requestBody) 7 | .then((res) => { 8 | return { data: res.data, success: true }; 9 | }) 10 | .catch((err) => { 11 | return { data: err.response.data, success: false }; 12 | }); 13 | const Request = { 14 | type: "POST", 15 | url: requestURL, 16 | body: requestBody, 17 | response: response, 18 | }; 19 | PrintInUATEnvironment(Request); 20 | return response; 21 | }; 22 | -------------------------------------------------------------------------------- /src/api/requests/getAPI.js: -------------------------------------------------------------------------------- 1 | import axios from "../axios"; 2 | import { PrintInUATEnvironment } from "../../assets/utils/commons"; 3 | 4 | export const GetRequest = async (requestURL, requestParams) => { 5 | const response = await axios 6 | .get(requestURL, { params: requestParams }) 7 | .then((res) => { 8 | return { data: res.data, success: true }; 9 | }) 10 | .catch((err) => { 11 | return { data: err?.response?.data, success: false }; 12 | }); 13 | const Request = { 14 | type: "GET", 15 | url: requestURL, 16 | params: requestParams, 17 | response: response, 18 | }; 19 | PrintInUATEnvironment(Request); 20 | return response; 21 | }; 22 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Analytics/Analytics.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | // MUI Components 4 | import { Stack, Divider } from "@mui/material"; 5 | 6 | // components 7 | import OrdersAnalytics from "./Orders/OrdersAnalytics"; 8 | 9 | const Analytics = () => { 10 | return ( 11 | } 14 | sx={{ minHeight: "calc(100vh - 48px)" }} 15 | > 16 | {/* Navigation */} 17 | 18 | 19 | 20 | 21 | ); 22 | }; 23 | 24 | export default Analytics; 25 | -------------------------------------------------------------------------------- /src/assets/components/container.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | import { Helmet } from "react-helmet-async"; 3 | import { Stack } from "@mui/material"; 4 | import "./base.css"; 5 | 6 | import PageLoader from "./pageloader"; 7 | 8 | const Container = ({ 9 | title, 10 | children, 11 | isAutherized = true, 12 | loading = false, 13 | redirect = true, 14 | }) => { 15 | const navigate = useNavigate(); 16 | if (!isAutherized) { 17 | navigate("/auth/login"); 18 | } 19 | return ( 20 | <> 21 | 22 | {title} 23 | 24 | {loading ? : children} 25 | 26 | ); 27 | }; 28 | 29 | export default Container; 30 | -------------------------------------------------------------------------------- /src/service/auth/signup.js: -------------------------------------------------------------------------------- 1 | import { 2 | register, 3 | verifyEmailOtp, 4 | verifyEmail, 5 | recoveryEmailOtp, 6 | } from "../../api/endpoints"; 7 | import { PostRequest } from "../../api/requests/postAPI"; 8 | 9 | export const handelSignup = async (requestBody) => { 10 | const response = await PostRequest(register, requestBody); 11 | return response; 12 | }; 13 | 14 | export const handelSendOtp = async (type, requestBody) => { 15 | const url = type === "EMAIL_VERIFICATION" ? verifyEmailOtp : recoveryEmailOtp; 16 | const response = await PostRequest(url, requestBody); 17 | return response; 18 | }; 19 | 20 | export const handleVerify = async (requestBody) => { 21 | const response = await PostRequest(verifyEmail, requestBody); 22 | return response; 23 | }; 24 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | name: CI 3 | 4 | on: 5 | push: 6 | branches: [ "main" ] 7 | pull_request: 8 | branches: [ "main" ] 9 | 10 | jobs: 11 | build: 12 | 13 | runs-on: ubuntu-latest 14 | env: 15 | CI: false 16 | strategy: 17 | matrix: 18 | node-version: [14.x, 16.x, 18.x] 19 | 20 | steps: 21 | - uses: actions/checkout@v3 22 | - name: Use Node.js ${{ matrix.node-version }} 23 | uses: actions/setup-node@v3 24 | with: 25 | node-version: ${{ matrix.node-version }} 26 | cache: 'npm' 27 | - run: npm install 28 | - run: npm run build 29 | - run: npm test --passWithNoTests 30 | -------------------------------------------------------------------------------- /src/service/search/booksearch.js: -------------------------------------------------------------------------------- 1 | import { GetRequest } from "../../api/requests/getAPI"; 2 | import { searchTitle, searchBook } from "../../api/endpoints"; 3 | 4 | export const BookSearchTitle = async (bookTitle) => { 5 | const params = { 6 | q: bookTitle, 7 | }; 8 | const result = await GetRequest(searchTitle, params); 9 | return result; 10 | }; 11 | 12 | export const BookSearch = async (params) => { 13 | const result = await GetRequest(searchBook, params); 14 | return result; 15 | }; 16 | 17 | export const BooksPerPage = () => { 18 | const windowSize = window.innerWidth; 19 | switch (windowSize) { 20 | case 450: 21 | return 8; 22 | case 600: 23 | return 12; 24 | case 900: 25 | return 15; 26 | case 1200: 27 | return 20; 28 | default: 29 | return 20; 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/components/search/pagination.js: -------------------------------------------------------------------------------- 1 | import { useNavigate, useParams } from "react-router-dom"; 2 | import { Stack, Pagination } from "@mui/material"; 3 | 4 | const BottomPagination = ({ page = 1, totalPages }) => { 5 | const { query, filters } = useParams(); 6 | const navigate = useNavigate(); 7 | 8 | // changing Page 9 | const changePage = (e, pageNo) => { 10 | navigate(`/search/${query}/${filters}/${pageNo}`); 11 | }; 12 | 13 | return ( 14 | 15 | 25 | 26 | ); 27 | }; 28 | 29 | export default BottomPagination; 30 | -------------------------------------------------------------------------------- /src/assets/components/input/passwordfield.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { TextField, InputAdornment, IconButton } from "@mui/material"; 3 | import { Visibility, VisibilityOff } from "@mui/icons-material"; 4 | 5 | const InputPasswordField = (props) => { 6 | const [show, setShow] = useState(false); 7 | 8 | return ( 9 | 16 | setShow((prev) => !prev)}> 17 | {show ? : } 18 | 19 | 20 | ), 21 | }} 22 | /> 23 | ); 24 | }; 25 | 26 | export default InputPasswordField; 27 | -------------------------------------------------------------------------------- /src/context/adminContext.js: -------------------------------------------------------------------------------- 1 | import { React, createContext, useState, useEffect } from "react"; 2 | 3 | export const AdminContext = createContext(); 4 | 5 | export const CurrentAdminProvider = (props) => { 6 | const localAdmin = JSON.parse(localStorage.getItem("bookshlf_admin")); 7 | 8 | const [admin, setAdmin] = useState({ 9 | bookVerification: { 10 | data: [], 11 | totalPages: 0, 12 | isApproved: false, 13 | page: 1, 14 | noOfBooksInOnePage: 24, 15 | }, 16 | order: { 17 | panel: 0, 18 | orderDetails: { data: [], page: 1, totalPages: 0 }, 19 | }, 20 | }); 21 | 22 | useEffect(() => { 23 | if (localAdmin) { 24 | setAdmin(localAdmin); 25 | } 26 | }, []); 27 | 28 | return ( 29 | 30 | {props.children} 31 | 32 | ); 33 | }; 34 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import "./index.css"; 4 | import App from "./app/app"; 5 | import reportWebVitals from "./reportWebVitals"; 6 | import { HelmetProvider } from "react-helmet-async"; 7 | import { BrowserRouter } from "react-router-dom"; 8 | // Context 9 | import { CurrentUserProvider } from "./context/userContext"; 10 | import { CurrentAdminProvider } from "./context/adminContext"; 11 | 12 | const root = ReactDOM.createRoot(document.getElementById("root")); 13 | root.render( 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | ); 26 | reportWebVitals(); 27 | -------------------------------------------------------------------------------- /src/components/home/NotFoundPage.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | 4 | // mui 5 | import { Button } from "@mui/material"; 6 | import HomeIcon from "@mui/icons-material/Home"; 7 | 8 | const NotFoundPage = () => { 9 | const navigate = useNavigate(); 10 | return ( 11 |
12 |

13 | 4 14 | 15 | 16 | 17 | 4 18 |

19 |

Error: 404 page not found

20 |

Sorry, the page you're looking for cannot be accessed

21 |
22 | 30 |
31 | ); 32 | }; 33 | 34 | export default NotFoundPage; 35 | -------------------------------------------------------------------------------- /src/components/navbar/navbarlinks.js: -------------------------------------------------------------------------------- 1 | import { useLocation } from "react-router-dom"; 2 | import { Stack } from "@mui/material"; 3 | import NavLink from "../../assets/components/links/navlink"; 4 | 5 | const NavbarItems = () => { 6 | const location = useLocation(); 7 | const activePath = location.pathname; 8 | return ( 9 | 16 | 17 | 22 | 27 | 28 | ); 29 | }; 30 | 31 | export default NavbarItems; 32 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Support/Support.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | // MUI Components 4 | import { Stack, Divider } from "@mui/material"; 5 | 6 | // Custom CSS 7 | import "./Support.css"; 8 | 9 | // Custom Components 10 | import SupportSideBar from "./SupportSideBar"; 11 | import SupportContent from "./SupportContent"; 12 | 13 | const Support = () => { 14 | // data States 15 | const [panel, setPanel] = useState(0); 16 | const [page, setPage] = useState(1); 17 | 18 | return ( 19 | } 23 | spacing={1} 24 | > 25 | 26 | 32 | 33 | ); 34 | }; 35 | 36 | export default Support; 37 | -------------------------------------------------------------------------------- /src/assets/components/links/links.css: -------------------------------------------------------------------------------- 1 | /* NavLink Css */ 2 | .navlink { 3 | display: inline-block; 4 | color: #8f8f8f; 5 | text-transform: capitalize; 6 | font-size: 12px; 7 | cursor: pointer; 8 | } 9 | 10 | .navlink-active { 11 | color: #ffffff !important; 12 | } 13 | 14 | .navlink:after { 15 | display: block; 16 | padding: 2px; 17 | content: ''; 18 | border-bottom: solid 1px #ffffff; 19 | transform: scaleX(0); 20 | transition: transform 250ms ease-in-out; 21 | } 22 | 23 | .navlink:hover:after { 24 | transform: scaleX(1); 25 | } 26 | 27 | .navlink-active:after { 28 | transform: scaleX(1); 29 | } 30 | 31 | .base-link.MuiTypography-root { 32 | font-family: 'DM Sans', sans-serif; 33 | color: #8f8f8f; 34 | text-decoration: none; 35 | cursor: pointer; 36 | font-size: 14px; 37 | } 38 | 39 | @media screen and (max-width: 600px) { 40 | .base-link.MuiTypography-root { 41 | font-size: 12px; 42 | } 43 | } -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Bookshlf", 3 | "name": "Bookshlf | The Bookstore which cares", 4 | "description": "Buy and Sell second-hand books at your doorstep", 5 | "manifest_version": 1, 6 | "icons": [ 7 | { 8 | "src": "/images/favicon.ico", 9 | "sizes": "64x64 32x32 24x24 16x16", 10 | "type": "image/x-icon" 11 | }, 12 | { 13 | "src": "/images/smallLogo.png", 14 | "sizes": "181x149", 15 | "type": "image/png" 16 | }, 17 | { 18 | "src": "/images/smallLogoView.png", 19 | "sizes": "229x202", 20 | "type": "image/png" 21 | }, 22 | { 23 | "src": "/images/logo.png", 24 | "sizes": "804x149", 25 | "type": "image/png" 26 | }, 27 | { 28 | "src": "/images/logoView.png", 29 | "sizes": "900x232", 30 | "type": "image/png" 31 | } 32 | ], 33 | "start_url": ".", 34 | "display": "standalone", 35 | "theme_color": "#000000", 36 | "background_color": "#ffffff" 37 | } 38 | -------------------------------------------------------------------------------- /src/api/endpoints.js: -------------------------------------------------------------------------------- 1 | // AUTH 2 | export const login = "/signIn"; 3 | export const logout = "/signOut"; 4 | export const register = "/signUp"; 5 | export const verifyEmailOtp = "/sendVerifyEmailOtp"; 6 | export const recoveryEmailOtp = "/sendResetPasswordOtp"; 7 | export const verifyEmail = "/verifyEmail"; 8 | export const passwordReset = "/resetPassword"; 9 | 10 | // SEARCH 11 | export const searchTitle = "/searchTitle"; 12 | export const searchBook = "/search"; 13 | 14 | // WISHLIST 15 | export const addWishlist = "/addWishlistItem"; 16 | export const deleteWishlist = "/deleteWishlistItem"; 17 | 18 | // CART 19 | export const addCart = "/addCartItem"; 20 | export const deleteCart = "/deleteCartItem"; 21 | 22 | // ORDER 23 | export const orderDetails = "/getOrderDetails"; 24 | export const orderList = "/getOrderList"; 25 | export const orderCancel = "/cancelOrder"; 26 | 27 | // USER 28 | export const userProfile = "/getUserProfile"; 29 | 30 | // ADDRESS 31 | export const addressList = "/getAddressList"; 32 | -------------------------------------------------------------------------------- /public/images/smallLogo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/components/BookDetails/BookDetails.css: -------------------------------------------------------------------------------- 1 | .book-details-snap .book-snapshots { 2 | width: 100px !important; 3 | height: 100px !important; 4 | cursor: pointer; 5 | } 6 | 7 | .book-details-snap .book-large-snapshot { 8 | width: 400px !important; 9 | height: 450px !important; 10 | } 11 | .book-details-tag-stack div { 12 | margin: 8px 8px 0px 8px !important; 13 | } 14 | .book-large-snapshot { 15 | background-color: rgba(0, 0, 0, 0.1); 16 | border-radius: 5px; 17 | } 18 | .book-large-snapshot img { 19 | object-fit: contain; 20 | } 21 | @media screen and (max-width: 600px) { 22 | .book-details-snap .book-snapshots { 23 | width: 70px !important; 24 | height: 70px !important; 25 | } 26 | .book-details-snap .book-large-snapshot { 27 | width: 200px !important; 28 | height: 250px !important; 29 | } 30 | .book-details-tag-stack { 31 | flex-wrap: wrap !important; 32 | justify-content: flex-start !important; 33 | align-items: flex-start !important; 34 | } 35 | .book-details-tag-stack div { 36 | margin: 4px !important; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/components/userpanel/usernav.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | import { Paper, Stack, Typography } from "@mui/material"; 3 | 4 | import OrderIcon from "@mui/icons-material/LocalShipping"; 5 | import AddressIcon from "@mui/icons-material/HomeWork"; 6 | 7 | const UserNavItem = ({ logo, label }) => { 8 | const navigate = useNavigate(); 9 | const handleClick = () => { 10 | navigate(`/user/${label}`); 11 | }; 12 | return ( 13 | 14 | 19 | {logo} 20 | {label} 21 | 22 | 23 | ); 24 | }; 25 | 26 | const UserNav = () => { 27 | return ( 28 | 29 | } label="orders" /> 30 | } label="address" /> 31 | 32 | ); 33 | }; 34 | export default UserNav; 35 | -------------------------------------------------------------------------------- /src/components/AdminPanel/AdminPanel.js: -------------------------------------------------------------------------------- 1 | import { React, useContext } from "react"; 2 | import { UserContext } from "../../context/userContext"; 3 | import { Helmet } from "react-helmet-async"; 4 | 5 | // Custom CSS 6 | import "./AdminPanel.css"; 7 | 8 | // Components 9 | import { Box } from "@mui/material"; 10 | import { Alert, AlertTitle } from "@mui/material"; 11 | import Navigation from "./Navigation/AdminPanelNavbar"; 12 | 13 | const AdminPanel = () => { 14 | const [user] = useContext(UserContext); 15 | return ( 16 | <> 17 | 18 | Admin Panel | Bookshlf 19 | 20 | 21 | {user && user.roles?.includes("admin") ? ( 22 | 23 | ) : ( 24 | 25 | 26 | Access Denied 27 | 28 | You are Unauthorized to Access this Domain. Contact Admin for More 29 | Details 30 | 31 | )} 32 | 33 | 34 | ); 35 | }; 36 | export default AdminPanel; 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Bookshlf 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/assets/components/pageloader.js: -------------------------------------------------------------------------------- 1 | import { Stack, Box, CircularProgress } from "@mui/material"; 2 | const PageLoader = () => { 3 | return ( 4 | 5 | 6 | 10 | theme.palette.grey[theme.palette.mode === "light" ? 200 : 800], 11 | }} 12 | size={40} 13 | thickness={4} 14 | value={100} 15 | /> 16 | 21 | theme.palette.mode === "light" ? "#1a90ff" : "#308fe8", 22 | animationDuration: "550ms", 23 | position: "absolute", 24 | left: 0, 25 | "& .MuiCircularProgress-circle": { 26 | strokeLinecap: "round", 27 | }, 28 | }} 29 | size={40} 30 | thickness={4} 31 | /> 32 | 33 | 34 | ); 35 | }; 36 | 37 | export default PageLoader; 38 | -------------------------------------------------------------------------------- /src/components/Footer/Footer.css: -------------------------------------------------------------------------------- 1 | .footer-container { 2 | background: linear-gradient(90deg, rgb(17, 16, 16) 0%, rgb(63, 62, 62) 100%); 3 | } 4 | .footer-subscription { 5 | width: 100%; 6 | background-color: #fff; 7 | padding: 12px; 8 | color: black; 9 | } 10 | .footer-link-items { 11 | width: 170px; 12 | font-family: "Roboto", sans-serif; 13 | font-weight: 900; 14 | } 15 | .footer-link-items > h6 { 16 | margin-bottom: 5px; 17 | color: #fff; 18 | } 19 | .footer-link-items a { 20 | color: #b1b1b1; 21 | text-decoration: none; 22 | font-size: 12px; 23 | } 24 | .footer-link-items a:hover { 25 | color: #ff4208; 26 | font-weight: bolder !important; 27 | } 28 | .footer-link-items .cool-link::after { 29 | content: ""; 30 | display: block; 31 | width: 0; 32 | height: 2px; 33 | background: #b1b1b1; 34 | transition: width 0.3s; 35 | } 36 | 37 | .footer-link-items .cool-link:hover::after { 38 | width: 100%; 39 | background: #ff4208; 40 | } 41 | .footer-container3 { 42 | background-color: rgb(0, 0, 0); 43 | color: white; 44 | width: 100%; 45 | padding: 5px; 46 | font-family: "Roboto", sans-serif; 47 | font-size: 12px; 48 | } 49 | -------------------------------------------------------------------------------- /src/assets/utils/date.js: -------------------------------------------------------------------------------- 1 | const monthNames = [ 2 | "January", 3 | "February", 4 | "March", 5 | "April", 6 | "May", 7 | "June", 8 | "July", 9 | "August", 10 | "September", 11 | "October", 12 | "November", 13 | "December", 14 | ]; 15 | const dayNames = [ 16 | "Sunday", 17 | "Monday", 18 | "Tuesday", 19 | "Wednesday", 20 | "Thursday", 21 | "Friday", 22 | "Saturday", 23 | ]; 24 | 25 | export const currentDate = () => { 26 | const d = new Date(); 27 | const newdate = d.getDate(); 28 | const day = d.getDay(); 29 | const month = d.getMonth(); 30 | const year = d.getFullYear(); 31 | 32 | return { 33 | date: newdate, 34 | day: day, 35 | dayName: dayNames[day], 36 | month: month, 37 | monthName: monthNames[month], 38 | year: year, 39 | }; 40 | }; 41 | 42 | export const TimestampToDate = (date) => { 43 | const d = new Date(date); 44 | const newdate = d.getDate(); 45 | const day = d.getDay(); 46 | const month = d.getMonth(); 47 | const year = d.getFullYear(); 48 | return { 49 | date: newdate, 50 | dayName: dayNames[day], 51 | monthName: monthNames[month], 52 | year: year, 53 | }; 54 | }; 55 | -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://bookshlf.in 5 | 2022-01-25 6 | 7 | 8 | https://bookshlf.in/SearchResult/tag:ALL 9 | 2022-01-25 10 | 11 | 12 | https://bookshlf.in/Login 13 | 2022-01-25 14 | 15 | 16 | https://bookshlf.in/Signup 17 | 2022-01-25 18 | 19 | 20 | https://bookshlf.in/PasswordRecovery 21 | 2022-01-25 22 | 23 | 24 | https://bookshlf.in/About 25 | 2022-01-25 26 | 27 | 28 | https://bookshlf.in/Contact 29 | 2022-01-25 30 | 31 | 32 | https://bookshlf.in/TermsofUsePrivacyPolicy 33 | 2022-01-25 34 | 35 | -------------------------------------------------------------------------------- /src/components/userpanel/userpanel.css: -------------------------------------------------------------------------------- 1 | .user-profile { 2 | padding: 15px 24px; 3 | background-color: #1E1E1E; 4 | width: 100%; 5 | border-radius: 12px; 6 | color: #FFFFFF; 7 | } 8 | 9 | .user-profile .MuiDivider-root { 10 | border-color: #FFFFFF !important; 11 | } 12 | 13 | .user-name { 14 | font-size: 48px !important; 15 | font-weight: bolder !important; 16 | } 17 | 18 | .user-email { 19 | font-size: 18px !important; 20 | } 21 | 22 | .user-id.MuiChip-root { 23 | font-family: 'DM Sans', sans-serif !important; 24 | border-radius: 5px; 25 | max-width: 300px; 26 | } 27 | 28 | .user-roles { 29 | font-size: 24px !important; 30 | } 31 | 32 | .user-role { 33 | text-transform: capitalize !important; 34 | border-radius: 5px !important; 35 | } 36 | 37 | .usernav-item { 38 | width: 100px; 39 | height: 100px; 40 | cursor: pointer; 41 | color: #F4A946 !important; 42 | border-radius: 12px !important; 43 | text-transform: capitalize !important; 44 | } 45 | 46 | .usernav-item:hover { 47 | background-color: #1E1E1E; 48 | transition: 0.3s; 49 | color: #FFFFFF; 50 | } 51 | 52 | @media screen and (max-width : 400px) { 53 | .user-name { 54 | font-size: 32px !important; 55 | } 56 | 57 | .user-email { 58 | font-size: 14px !important; 59 | } 60 | } -------------------------------------------------------------------------------- /src/service/AdminPanel/Analytics/OrdersAnalytics.js: -------------------------------------------------------------------------------- 1 | import axios from "../../../api/axios"; 2 | 3 | export const makeRequest = (month, year, setLoad, setOrder, setFinance) => { 4 | setLoad(true); 5 | axios 6 | .get("/admin-getMonthOrderStats", { 7 | params: { 8 | month: month, 9 | year: year, 10 | }, 11 | }) 12 | .then((res) => { 13 | setOrder({ 14 | placed: res.data.totalOrders, 15 | confirmed: res.data.confirmed, 16 | packed: res.data.packed, 17 | shipped: res.data.shipped, 18 | delivered: res.data.delivered, 19 | rto: res.data.RTO, 20 | returned: res.data.returned, 21 | lost: res.data.lost, 22 | cancelled: res.data.cancelled, 23 | }); 24 | setFinance({ 25 | expectedRevenue: Math.round(res.data.expectedRevenue), 26 | actualRevenue: Math.round(res.data.totalRevenue), 27 | expectedProfit: Math.round(res.data.expectedProfit), 28 | deliveredProfit: Math.round(res.data.DeliveredProfit), 29 | rtoLoss: Math.round(res.data.RTOLoss), 30 | actualProfit: Math.round(res.data.totalProfit), 31 | }); 32 | console.log(res.data); 33 | setLoad(false); 34 | }) 35 | .catch((err) => { 36 | console.log(err.response.data); 37 | setLoad(false); 38 | }); 39 | }; 40 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Navigation/AdminAppBar.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | 3 | // Components 4 | import { AppBar, Toolbar } from "@mui/material"; 5 | import { Typography, IconButton } from "@mui/material"; 6 | 7 | // icons 8 | import MenuIcon from "@mui/icons-material/Menu"; 9 | import HomeIcon from "@mui/icons-material/Home"; 10 | 11 | // Custom Admin AppBar 12 | const AdminAppBar = ({ openSideBar, setOpenSideBar }) => { 13 | const navigate = useNavigate(); 14 | return ( 15 | 16 | 17 | setOpenSideBar(true)} 23 | > 24 | 25 | 26 | 32 | Admin Panel | Bookshlf 33 | 34 | navigate("/")} 40 | > 41 | 42 | 43 | 44 | 45 | ); 46 | }; 47 | 48 | export default AdminAppBar; 49 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Book/Book.css: -------------------------------------------------------------------------------- 1 | .AdminBookNav.MuiAppBar-root { 2 | background: transparent; 3 | box-shadow: none; 4 | } 5 | 6 | .AdminBookNav .MuiToolbar-root { 7 | background: linear-gradient(195deg, rgb(73, 163, 241), rgb(26, 115, 232)); 8 | padding: 0px 24px; 9 | } 10 | 11 | .AdminBookNav-btn { 12 | padding: 5px; 13 | margin-right: 0.5em; 14 | border-radius: 5px; 15 | cursor: pointer; 16 | } 17 | 18 | .AdminBookNav-btn:hover { 19 | background-color: rgba(255, 255, 255, 0.8); 20 | backdrop-filter: saturate(200%) blur(1.875rem); 21 | color: black; 22 | transition: 0.3s; 23 | } 24 | 25 | .AdminBookNav-btn-active { 26 | background-color: rgba(255, 255, 255, 0.8); 27 | backdrop-filter: saturate(200%) blur(1.875rem); 28 | color: black; 29 | } 30 | 31 | .AdminBookVerification .MuiTypography-root { 32 | font-size: 12px; 33 | } 34 | 35 | .admin-searchTagresult { 36 | max-height: 400px; 37 | max-width: 250px; 38 | overflow-y: auto; 39 | } 40 | 41 | .adminPanel-content .filepond--drop-label { 42 | min-height: 4em !important; 43 | background-color: #fff; 44 | border: 1px dotted rgba(0, 0, 0, 0.8); 45 | color: rgb(52, 52, 52) !important; 46 | border-radius: 5px; 47 | } 48 | 49 | .adminPanel-content .filepond--label-action { 50 | background-color: #bfbfbf; 51 | padding: 6px 10px; 52 | text-decoration: none !important; 53 | border-radius: 5px; 54 | } -------------------------------------------------------------------------------- /src/components/userpanel/profile.js: -------------------------------------------------------------------------------- 1 | import { Fragment } from "react"; 2 | 3 | // Components 4 | import { Stack, Divider, Typography } from "@mui/material"; 5 | import { Chip } from "@mui/material"; 6 | 7 | import { TimestampToDate } from "../../assets/utils/date"; 8 | 9 | const Account = ({ user }) => { 10 | const registeredOn = TimestampToDate(user?.createdAt); 11 | return ( 12 | 13 | {user.name} 14 | {user.email} 15 | 16 | 17 | Roles 18 | 19 | {user?.roles?.map((role) => ( 20 | 21 | 28 | 29 | ))} 30 | 31 | 32 | User Since :{" "} 33 | {registeredOn.date + 34 | ", " + 35 | registeredOn.monthName + 36 | " " + 37 | registeredOn.year + 38 | " (" + 39 | registeredOn.dayName + 40 | ")"} 41 | 42 | 43 | ); 44 | }; 45 | export default Account; 46 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Navigation/AdminPanelNavbar.js: -------------------------------------------------------------------------------- 1 | import { React, useState, useEffect } from "react"; 2 | import { useParams, useNavigate } from "react-router-dom"; 3 | 4 | // Components 5 | import { Drawer } from "@mui/material"; 6 | import { Stack } from "@mui/material"; 7 | 8 | // Custom components 9 | import AdminSideBar from "./AdminSideBar"; 10 | import AdminAppBar from "./AdminAppBar"; 11 | import AdminContentPanel from "./AdminContentPanel"; 12 | 13 | const AdminNavbar = () => { 14 | // Hooks Call 15 | const navigate = useNavigate(); 16 | const params = useParams(); 17 | 18 | // States 19 | const [Panel, setPanel] = useState(Number(params.panel)); 20 | const [openSideBar, setOpenSideBar] = useState(false); 21 | 22 | // update panel when text param changes 23 | useEffect(() => { 24 | setPanel(Number(params.panel)); 25 | }, [params]); 26 | 27 | return ( 28 | 29 | 30 | setOpenSideBar(false)} 34 | > 35 | 41 | 42 | 47 | 48 | ); 49 | }; 50 | export default AdminNavbar; 51 | -------------------------------------------------------------------------------- /src/components/Checkout/CheckoutLoading.js: -------------------------------------------------------------------------------- 1 | import { Stack, Grid, Skeleton } from "@mui/material"; 2 | 3 | const CheckoutLoading = () => { 4 | return ( 5 | 11 | 12 | 17 | 18 | 19 | 20 | 21 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 41 | 42 | 43 | 44 | 45 | ); 46 | }; 47 | 48 | export default CheckoutLoading; 49 | -------------------------------------------------------------------------------- /src/assets/components/buttons/ordercancelbutton.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { DeleteRequest } from "../../../api/requests/deleteAPI"; 4 | import { orderCancel } from "../../../api/endpoints"; 5 | 6 | import { Button, CircularProgress, Alert } from "@mui/material"; 7 | import CancelIcon from "@mui/icons-material/Cancel"; 8 | 9 | const OrderCancelButton = ({ orderId, className, props }) => { 10 | const navigate = useNavigate(); 11 | const [loading, setLoading] = useState(false); 12 | const [alert, setAlert] = useState(false); 13 | 14 | const handelCancelOrder = () => { 15 | setLoading(true); 16 | DeleteRequest(orderCancel, { orderId: orderId }) 17 | .then((response) => { 18 | setLoading(false); 19 | navigate(0); 20 | }) 21 | .catch((error) => { 22 | setLoading(false); 23 | setAlert(true); 24 | setTimeout(() => { 25 | setAlert(false); 26 | }, 5000); 27 | }); 28 | }; 29 | 30 | return ( 31 | <> 32 | 47 | {alert && Order Cancellation Failed!} 48 | 49 | ); 50 | }; 51 | 52 | export default OrderCancelButton; 53 | -------------------------------------------------------------------------------- /src/components/Order/tracking/tracking.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext } from "react"; 2 | import { UserContext } from "../../../context/userContext"; 3 | import { useParams } from "react-router-dom"; 4 | 5 | import { GetRequest } from "../../../api/requests/getAPI"; 6 | import { orderDetails } from "../../../api/endpoints"; 7 | 8 | import "./tracking.css"; 9 | 10 | import { Stack } from "@mui/material"; 11 | 12 | import Container from "../../../assets/components/container"; 13 | import Details from "./details"; 14 | import OrderProgress from "./trackprogress"; 15 | 16 | const Tracking = () => { 17 | const [user] = useContext(UserContext); 18 | const { orderId } = useParams(); 19 | 20 | const [loading, setLoading] = useState(true); 21 | const [order, setOrder] = useState({}); 22 | 23 | const getOrderDetails = () => { 24 | GetRequest(orderDetails, { orderId: orderId }).then((response) => { 25 | setOrder(response.data); 26 | setLoading(false); 27 | }); 28 | }; 29 | 30 | useEffect(() => { 31 | getOrderDetails(); 32 | }, [orderId]); 33 | 34 | return ( 35 | 36 | 46 | 47 |
48 | 49 | 50 | ); 51 | }; 52 | 53 | export default Tracking; 54 | -------------------------------------------------------------------------------- /src/components/auth/recovery/recovery.css: -------------------------------------------------------------------------------- 1 | .password-recovery-bg input:-webkit-autofill { 2 | -webkit-box-shadow: 0 0 0px 1000px rgb(35, 47, 62) inset; 3 | -webkit-text-fill-color: rgb(255, 255, 255); 4 | } 5 | .password-recovery-bg input:-webkit-autofill:focus { 6 | -webkit-text-fill-color: rgb(255, 255, 255); 7 | -webkit-box-shadow: 0 0 0px 1000px rgb(35, 47, 62) inset; 8 | } 9 | 10 | .otp-input-field { 11 | width: 100%; 12 | height: 32px; 13 | border-radius: 0.25rem; 14 | font-size: 16px; 15 | font-family: "PT sans"; 16 | text-align: center; 17 | background-color: #f3f6f9; 18 | color: #3f4254; 19 | outline: 0; 20 | border: 2px solid rgb(66, 66, 66); 21 | letter-spacing: 5px; 22 | } 23 | .otp-input-field:focus { 24 | box-shadow: 0 0 0 3px rgb(66 153 225 / 50%); 25 | transition: color 0.15s ease, background-color 0.15s ease, 26 | border-color 0.15s ease, box-shadow 0.15s ease; 27 | } 28 | .otp-input-field-mobile { 29 | display: none; 30 | width: 180px; 31 | height: 32px; 32 | border-radius: 0.25rem; 33 | font-size: 16px; 34 | font-family: "PT sans"; 35 | letter-spacing: 6px; 36 | text-align: center; 37 | background-color: #f3f6f9; 38 | color: #3f4254; 39 | outline: 0; 40 | border: 2px solid rgb(66, 66, 66); 41 | } 42 | .otp-input-field-mobile:focus { 43 | box-shadow: 0 0 0 3px rgb(66 153 225 / 50%); 44 | transition: color 0.15s ease, background-color 0.15s ease, 45 | border-color 0.15s ease, box-shadow 0.15s ease; 46 | } 47 | @media screen and (max-width: 400px) { 48 | #otp { 49 | display: none !important; 50 | } 51 | .otp-input-field-mobile { 52 | display: block; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/service/Book/AdminBookPurchase/purchaseOrder.js: -------------------------------------------------------------------------------- 1 | // API 2 | import axios from "../../../api/axios"; 3 | 4 | // Open Dialog 5 | export const handleOpen = (setOpen) => { 6 | setOpen(true); 7 | }; 8 | 9 | // Close Dialog 10 | export const handleClose = (setOpen) => { 11 | setOpen(false); 12 | }; 13 | 14 | // on Error 15 | export const handleError = (setError) => { 16 | setError(true); 17 | setTimeout(() => { 18 | setError(false); 19 | }, 3000); 20 | }; 21 | 22 | // Purchase Order 23 | export const adminBookPurchase = ( 24 | orderId, 25 | setOrderId, 26 | setOrderLoad, 27 | bookId, 28 | setSuccess, 29 | setOpen, 30 | setError 31 | ) => { 32 | console.log(orderId); 33 | setOrderId(orderId); 34 | setOrderLoad(true); 35 | axios 36 | .get("/admin-getOrderDetails", { 37 | params: { orderId: orderId }, 38 | }) 39 | .then((response) => { 40 | axios 41 | .post("/admin-purchaseBook", { 42 | bookId: bookId, 43 | customerId: response.data.customerId, 44 | customerAddressId: response.data.customerAddress._id, 45 | purchaseQty: 1, 46 | }) 47 | .then((res) => { 48 | console.log("Order Placed!"); 49 | setOrderLoad(false); 50 | setSuccess(true); 51 | setTimeout(() => { 52 | setOpen(false); 53 | }, 3000); 54 | }) 55 | .catch((err) => { 56 | console.log(err.response.data); 57 | setOrderLoad(false); 58 | handleError(setError); 59 | }); 60 | return response; 61 | }) 62 | .catch((err) => { 63 | console.log(err); 64 | setOrderLoad(false); 65 | handleError(setError); 66 | }); 67 | }; 68 | -------------------------------------------------------------------------------- /src/components/Wallet/Wallet.css: -------------------------------------------------------------------------------- 1 | .wallet-stack-item { 2 | font-family: "PT sans"; 3 | display: flex; 4 | justify-content: center; 5 | align-items: center; 6 | } 7 | .amount-icon { 8 | padding: 6px; 9 | background-color: rgba(0, 0, 0, 0.06); 10 | border-radius: 10px; 11 | font-family: "PT sans"; 12 | margin: 10px 0px; 13 | } 14 | .wallet-stack-item .debit-amount, 15 | .wallet-stack-item .credit-amount { 16 | padding: 6px; 17 | font-size: 14px; 18 | font-family: "PT sans"; 19 | } 20 | .wallet-stack-item .debit-amount { 21 | color: rgb(231, 39, 39); 22 | } 23 | .wallet-stack-item .credit-amount { 24 | color: forestgreen; 25 | } 26 | 27 | .Wallet-Accordian .MuiAccordionSummary-content { 28 | margin: 0px !important; 29 | } 30 | 31 | .Wallet-Accordian .MuiAccordionDetails-root { 32 | padding: 8px !important; 33 | } 34 | 35 | .Wallet-Accordian .MuiList-root { 36 | padding: 0px !important; 37 | } 38 | 39 | .Wallet-Accordian .MuiListItem-gutters { 40 | padding: 4px 6px !important; 41 | } 42 | 43 | .Wallet-Accordian .MuiListItemAvatar-root { 44 | min-width: 30px !important; 45 | } 46 | .Wallet-Accordian .MuiListItemText-root { 47 | margin: 0px !important; 48 | padding: 0px 6px; 49 | } 50 | 51 | .Wallet-Accordian .MuiTypography-root { 52 | font-size: 0.75rem !important; 53 | font-family: "PT sans" !important; 54 | } 55 | 56 | .Wallet-Accordian .MuiListItemText-secondary { 57 | font-family: "PT sans" !important; 58 | font-size: 0.65rem !important; 59 | } 60 | 61 | .Wallet-Accordian .MuiAlert-message { 62 | font-family: "PT sans"; 63 | } 64 | 65 | .Wallet-Accordian .MuiChip-label { 66 | font-family: "PT sans" !important; 67 | font-size: 10px !important; 68 | letter-spacing: 0.5px !important; 69 | } 70 | -------------------------------------------------------------------------------- /src/components/AdminPanel/AdminPanel.css: -------------------------------------------------------------------------------- 1 | .adminPanel-container { 2 | min-height: 100vh; 3 | } 4 | 5 | .MuiPaper-root.adminPanel-sidebar { 6 | height: 100%; 7 | width: 250px; 8 | background: linear-gradient(195deg, rgb(66, 66, 74), rgb(25, 25, 25)); 9 | border-radius: 0; 10 | color: white; 11 | transform: translateX(0px); 12 | transition: width 225ms cubic-bezier(0.4, 0, 0.6, 1) 0ms, background-color 225ms cubic-bezier(0.4, 0, 0.6, 1) 0ms; 13 | box-shadow: rgb(0 0 0 / 5%) 0rem 1.25rem 1.6875rem; 14 | } 15 | 16 | .adminPanel-sidebar-logo { 17 | padding: 15px; 18 | height: 60px; 19 | } 20 | 21 | .MuiDivider-root.adminPanel-sidebar-divider { 22 | flex-shrink: 0; 23 | border-top: 0px solid rgba(0, 0, 0, 0.08); 24 | border-right: 0px solid rgba(0, 0, 0, 0.08); 25 | border-left: 0px solid rgba(0, 0, 0, 0.08); 26 | height: 0.0625rem; 27 | margin: 1rem 0px; 28 | border-bottom: none; 29 | opacity: 0.25; 30 | background-color: transparent; 31 | background-image: linear-gradient(to right, rgba(255, 255, 255, 0), rgb(255, 255, 255), rgba(255, 255, 255, 0)) !important; 32 | } 33 | 34 | .adminPanel-container .MuiAppBar-root { 35 | background: linear-gradient(195deg, rgb(66, 66, 74), rgb(25, 25, 25)); 36 | } 37 | 38 | .adminPanel-sidebar-Nav { 39 | padding: 15px; 40 | width: 100%; 41 | } 42 | 43 | .adminPanel-navButton { 44 | padding: 0.8rem 1rem; 45 | border-radius: 0.375rem; 46 | transition: box-shadow 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms, background-color 200ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; 47 | cursor: pointer; 48 | } 49 | 50 | .adminPanel-navButton-active { 51 | background: linear-gradient(195deg, rgb(73, 163, 241), rgb(26, 115, 232)); 52 | } 53 | 54 | .adminPanel-navButton:hover { 55 | background-color: rgba(255, 255, 255, 0.2); 56 | } -------------------------------------------------------------------------------- /src/components/MicroComponents/customCopyText.js: -------------------------------------------------------------------------------- 1 | import { React, useState } from "react"; 2 | 3 | import { Stack, Tooltip, Typography } from "@mui/material"; 4 | 5 | // MUI Icons 6 | import CopyIcon from "@mui/icons-material/ContentCopy"; 7 | import CopiedIcon from "@mui/icons-material/Check"; 8 | 9 | const CopyableText = ({ text, fontSize }) => { 10 | const [copied, setcopied] = useState(false); 11 | 12 | const CopyText = () => { 13 | navigator.clipboard.writeText(text); 14 | setcopied(true); 15 | setTimeout(() => { 16 | setcopied(false); 17 | }, 3000); 18 | }; 19 | 20 | return ( 21 | 33 | 38 | {text} 39 | 40 | 49 | 50 | {!copied ? ( 51 | 52 | ) : ( 53 | 54 | )} 55 | 56 | 57 | 58 | ); 59 | }; 60 | 61 | export default CopyableText; 62 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Book/AdminFindBook.js: -------------------------------------------------------------------------------- 1 | import { React, useState, useContext } from "react"; 2 | import { AdminContext } from "../../../context/adminContext"; 3 | 4 | // MUI Components 5 | import { Stack, Button, TextField } from "@mui/material"; 6 | 7 | // Custom Components 8 | import BookDetails from "./BookVerification/BookDetails"; 9 | 10 | const AdminFindBook = () => { 11 | // admin Context 12 | const [admin, setAdmin] = useContext(AdminContext); 13 | 14 | // States 15 | const [bookId, setBookId] = useState(admin?.AdminFindBook?.bookId); 16 | const [getBook, setGetBook] = useState(false); 17 | 18 | const handleGetBook = () => { 19 | setGetBook(true); 20 | setAdmin({ 21 | ...admin, 22 | AdminFindBook: { ...admin.AdminFindBook, bookId: bookId }, 23 | }); 24 | localStorage.setItem( 25 | "bookshlf_admin", 26 | JSON.stringify({ 27 | ...admin, 28 | AdminFindBook: { ...admin.AdminFindBook, bookId: bookId }, 29 | }) 30 | ); 31 | }; 32 | return ( 33 | 43 | 44 | setBookId(e.target.value)} 50 | sx={{ minWidth: 300 }} 51 | /> 52 | 55 | 56 | {getBook ? : null} 57 | 58 | ); 59 | }; 60 | export default AdminFindBook; 61 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Support/Support.css: -------------------------------------------------------------------------------- 1 | .admin-support { 2 | min-height: calc(100vh - 48px); 3 | padding: 0; 4 | } 5 | 6 | .admin-support-sidebar { 7 | min-width: 250px; 8 | max-width: 300px; 9 | } 10 | 11 | .MuiButton-root.admin-ComposeMailBtn { 12 | margin: 10px; 13 | border-radius: 16px; 14 | color: #001d35; 15 | height: 56px; 16 | padding: 0 24px 0 0; 17 | min-width: 150px; 18 | font-size: .875rem; 19 | background-color: #c2e7ff; 20 | box-shadow: 0 1px 2px 0 #0000, 0 1px 3px 1px #0000; 21 | } 22 | 23 | .MuiButton-root.admin-ComposeMailBtn:hover { 24 | transition: box-shadow .08s linear, min-width .15s cubic-bezier(0.4, 0, 0.2, 1); 25 | box-shadow: 0 1px 3px 0 rgb(60 64 67 / 30%), 0 4px 8px 3px rgb(60 64 67 / 15%); 26 | background-color: #c2e7ff; 27 | } 28 | 29 | .admin-sidebar-btn { 30 | box-shadow: inset 0 0 0 1px transparent; 31 | border-radius: 0 16px 16px 0; 32 | height: 32px; 33 | padding: 0 12px 0 26px; 34 | cursor: pointer; 35 | } 36 | 37 | .admin-sidebar-btn-active { 38 | background-color: #d3e3fd; 39 | } 40 | 41 | .admin-sidebar-btn:hover { 42 | background-color: rgba(0, 0, 0, 0.1); 43 | } 44 | 45 | .admin-sidebar-btn-active:hover { 46 | background-color: #d3e3fd; 47 | } 48 | 49 | .admin-supportContent { 50 | padding: 10px 0px; 51 | flex-grow: 1; 52 | } 53 | 54 | .admin-support-msg { 55 | padding: 10px; 56 | box-shadow: inset 0 -1px 0 0 rgb(100 121 143 / 12%); 57 | cursor: pointer; 58 | width: 100%; 59 | } 60 | 61 | .admin-support-msg:hover { 62 | box-shadow: inset 1px 0 0 #dadce0, inset -1px 0 0 #dadce0, 0 1px 2px 0 rgb(60 64 67 / 30%), 0 1px 3px 1px rgb(60 64 67 / 15%); 63 | z-index: 2; 64 | } 65 | 66 | .admin-support-msg-read { 67 | background-color: rgba(0, 0, 0, 0.08); 68 | } -------------------------------------------------------------------------------- /src/assets/utils/commons.js: -------------------------------------------------------------------------------- 1 | export const isLocationAuth = (pathname) => { 2 | if (pathname.startsWith("/auth")) return true; 3 | return false; 4 | }; 5 | 6 | export const isUATEnvironment = () => { 7 | if (process.env.REACT_APP_NODE_ENV === "uat") return true; 8 | return false; 9 | }; 10 | 11 | export const PrintInUATEnvironment = (data) => { 12 | if (isUATEnvironment()) console.log(data); 13 | }; 14 | 15 | export const userRoleCheck = (user, role) => { 16 | if (user?.roles?.includes(role)) return true; 17 | return false; 18 | }; 19 | 20 | export const trimText = (text, maxLength) => { 21 | return text.length >= maxLength ? text.substr(0, maxLength) + "..." : text; 22 | }; 23 | 24 | export const StringtoObject = (string, splitter = "&", delimiter = "=") => { 25 | if (string === undefined || string === "default") return {}; 26 | const params = string.split(splitter); 27 | let result = {}; 28 | params.map((param) => { 29 | const key = param.split(delimiter)[0]; 30 | const value = param.split(delimiter)[1]; 31 | result = { 32 | ...result, 33 | [key]: value, 34 | }; 35 | return param; 36 | }); 37 | return result; 38 | }; 39 | 40 | export const StringtoArray = (string, splitter = "&") => { 41 | if (string === undefined || string === "default") return ["default"]; 42 | return string.split(splitter); 43 | }; 44 | 45 | export const isEnterKey = (e) => { 46 | return e.key === "Enter"; 47 | }; 48 | 49 | export const AddressFormat = (address = {}) => { 50 | return ( 51 | address.address + 52 | ", " + 53 | address.city + 54 | " " + 55 | address.state + 56 | " (" + 57 | address.zipCode + 58 | ")" 59 | ); 60 | }; 61 | 62 | export const Sort = (data = [], key) => { 63 | data.sort((a, b) => { 64 | return a[key] < b[key] ? 1 : a[key] > b[key] ? -1 : 0; 65 | }); 66 | }; 67 | -------------------------------------------------------------------------------- /src/components/search/search.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { useParams } from "react-router-dom"; 3 | import "./search.css"; 4 | 5 | // Components 6 | import { Stack } from "@mui/material"; 7 | 8 | // Custom Components 9 | import Container from "../../assets/components/container"; 10 | import SearchFilter from "./searchfilter"; 11 | import SearchResult from "./searchresults"; 12 | import Pagination from "./pagination"; 13 | import BookshlfLoader from "../MicroComponents/BookshlfLoader"; 14 | 15 | // Services 16 | import { StringtoObject } from "../../assets/utils/commons"; 17 | import { BookSearch, BooksPerPage } from "../../service/search/booksearch"; 18 | 19 | const Search = () => { 20 | // Calling Hooks 21 | const { query, filters, page = 1 } = useParams(); 22 | 23 | // Functionality States 24 | const [loading, setLoading] = useState(false); 25 | 26 | // Data states 27 | const [books, setbooks] = useState([]); 28 | const [totalPages, settotalPages] = useState(1); 29 | 30 | useEffect(() => { 31 | const makeRequest = async () => { 32 | setLoading(true); 33 | const response = await BookSearch({ 34 | ...StringtoObject(filters), 35 | q: query, 36 | noOfBooksInOnePage: BooksPerPage(), 37 | page: Number(page), 38 | }); 39 | if (response.success) { 40 | setbooks(response.data.data); 41 | settotalPages(response.data.totalPages); 42 | } 43 | setLoading(false); 44 | }; 45 | makeRequest(); 46 | }, [query, page, filters]); 47 | 48 | return ( 49 | 50 | 51 | 52 | {loading && } 53 | {!loading && } 54 | {!loading && } 55 | 56 | 57 | ); 58 | }; 59 | 60 | export default Search; 61 | -------------------------------------------------------------------------------- /src/components/Order/tracking/tracking.css: -------------------------------------------------------------------------------- 1 | .track-box { 2 | background: #FDFDFD; 3 | box-shadow: 10px 10px 28px -2px rgba(0, 0, 0, 0.1); 4 | border-radius: 12px; 5 | width: 100%; 6 | } 7 | 8 | .tracking-dayname { 9 | font-weight: bold !important; 10 | font-size: 2em !important; 11 | color: #1E1E1E !important; 12 | } 13 | 14 | .tracking-monthyear { 15 | font-weight: bold !important; 16 | color: #1E1E1E !important; 17 | font-size: 1.2em !important; 18 | } 19 | 20 | .tracking-date { 21 | font-weight: bold !important; 22 | color: #F4A946 !important; 23 | font-size: 4em !important; 24 | } 25 | 26 | .order-current-status { 27 | text-transform: capitalize; 28 | font-weight: bold !important; 29 | color: #2d82f9 !important; 30 | font-size: 2em !important; 31 | } 32 | 33 | .order-cancel-btn { 34 | background-color: rgb(255, 86, 79) !important; 35 | color: #FDFDFD !important; 36 | font-family: "DM Sans", sans-serif !important; 37 | text-transform: capitalize !important; 38 | border-radius: 12px !important; 39 | padding: 10px 15px !important; 40 | } 41 | 42 | .track-order-image { 43 | height: 300px; 44 | width: 300px; 45 | object-fit: cover; 46 | border-radius: 12px; 47 | } 48 | 49 | .track-detail-title { 50 | font-size: 14px !important; 51 | font-weight: bold !important; 52 | } 53 | 54 | .track-detail-text { 55 | font-size: 12px !important; 56 | color: #0071f3 !important; 57 | } 58 | 59 | .track-box .Mui-active { 60 | color: #1692f1 !important; 61 | } 62 | 63 | .track-box .Mui-completed { 64 | color: rgb(4, 154, 4) !important; 65 | } 66 | 67 | .step-content { 68 | font-size: 12px !important; 69 | padding: 10px 15px; 70 | border: 1px solid rgba(0, 0, 0, 0.2) !important; 71 | border-radius: 12px; 72 | } 73 | 74 | @media screen and (max-width:600px) { 75 | .track-order-image { 76 | height: 200px; 77 | width: 200px; 78 | object-fit: cover; 79 | border-radius: 12px; 80 | } 81 | } -------------------------------------------------------------------------------- /src/components/MicroComponents/Mail.js: -------------------------------------------------------------------------------- 1 | import { React, useState } from "react"; 2 | import axios from "../../api/axios"; 3 | 4 | // MUI Components 5 | import { Button, CircularProgress } from "@mui/material"; 6 | 7 | const Btn = (props) => { 8 | const [load, setLoad] = useState(false); 9 | const [sent, setSent] = useState(false); 10 | 11 | const SendMail = () => { 12 | setLoad(true); 13 | // console.log(props.template); 14 | axios 15 | .post("/admin-sendEmail", { 16 | type: "SEND_MULTIPLE", 17 | emailData: { 18 | to: props.to, 19 | from: "shipment@bookshlf.in", 20 | cc: props.cc, 21 | bcc: "bookshlf.in@gmail.com", 22 | subject: props.subject, 23 | text: props.subject, 24 | html: props.template, 25 | }, 26 | }) 27 | .then((res) => { 28 | setLoad(false); 29 | setSent(true); 30 | }) 31 | .catch((err) => { 32 | setLoad(false); 33 | // console.log(err.response.data); 34 | }); 35 | }; 36 | return ( 37 | 47 | ); 48 | }; 49 | const Form = (props) => { 50 | return
Form
; 51 | }; 52 | const Mail = (props) => { 53 | return ( 54 |
55 | {props.type === "button" ? ( 56 | 66 | ) : ( 67 |
68 | )} 69 |
70 | ); 71 | }; 72 | export default Mail; 73 | -------------------------------------------------------------------------------- /src/components/home/Categories.css: -------------------------------------------------------------------------------- 1 | .categories { 2 | padding-top: 10px; 3 | background-color: white; 4 | color: rgb(51, 51, 51); 5 | } 6 | .item { 7 | display: flex; 8 | flex-direction: column; 9 | justify-content: center; 10 | align-items: center; 11 | padding: 10px; 12 | height: 230px; 13 | width: 100%; 14 | max-width: 350px; 15 | cursor: pointer; 16 | background-color: rgb(10, 37, 64); 17 | border-radius: 15px; 18 | box-shadow: 2px 2px 3px 2px rgba(0, 0, 0, 0.2); 19 | position: relative; 20 | border: 0.5px solid rgba(255, 255, 255, 0); 21 | color: rgb(255, 151, 65); 22 | } 23 | .item:hover { 24 | background-color: rgb(255, 151, 65); 25 | transition: 0.3s; 26 | color: rgb(51, 51, 51); 27 | border: 0.5px solid rgba(255, 255, 255, 0.3); 28 | } 29 | .item-h6 { 30 | font-size: 1em; 31 | margin-top: 100px; 32 | font-family: "Montserrat", sans-serif; 33 | letter-spacing: 2px; 34 | text-align: center; 35 | } 36 | 37 | @media screen and (max-width: 768px) { 38 | .categories h4 { 39 | font-size: 24px; 40 | font-weight: bolder !important; 41 | } 42 | .categories h6 { 43 | font-size: 12px !important; 44 | font-weight: bolder !important; 45 | } 46 | .categories .MuiAvatar-root { 47 | height: 50px; 48 | width: 50px; 49 | } 50 | .categories .MuiTypography-caption { 51 | font-size: 9px; 52 | padding: 6px 0px; 53 | width: 50px; 54 | } 55 | .item { 56 | height: 125px; 57 | width: 125px; 58 | } 59 | .item-h6 { 60 | font-size: 12px !important; 61 | margin-top: 40px; 62 | } 63 | } 64 | @media screen and (max-width: 350px) { 65 | .categories h6 { 66 | font-size: 9px !important; 67 | } 68 | .categories .MuiAvatar-root { 69 | height: 35px; 70 | width: 35px; 71 | top: 5px; 72 | } 73 | .categories .MuiTypography-caption { 74 | font-size: 9px; 75 | padding: 6px 0px; 76 | width: 50px; 77 | } 78 | .item { 79 | height: 125px; 80 | width: 125px; 81 | } 82 | .item-h6 { 83 | font-size: 12px !important; 84 | margin-top: 40px; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/components/Order/tracking/trackprogress.js: -------------------------------------------------------------------------------- 1 | import { Stack, Typography, Skeleton, Divider } from "@mui/material"; 2 | 3 | import { TimestampToDate } from "../../../assets/utils/date"; 4 | import OrderCancelButton from "../../../assets/components/buttons/ordercancelbutton"; 5 | import TrackingStepper from "./trackingstepper"; 6 | 7 | const TrackProgress = ({ order = {}, loading }) => { 8 | const { date, dayName, monthName, year } = TimestampToDate( 9 | order.expectedDeliveryDate 10 | ); 11 | 12 | const orderCurrentStatus = order.status 13 | ? order.status[order.status.length - 1] 14 | : "UnKnown"; 15 | 16 | return ( 17 | 18 | {loading && ( 19 | 25 | )} 26 | {!loading && ( 27 | 28 | 33 | Estimated Delivery Date 34 | {orderCurrentStatus === "Order placed" && ( 35 | 39 | )} 40 | 41 | 42 | {dayName} 43 | 44 | {monthName + ", " + year} 45 | 46 | {date} 47 | 48 | 49 | {orderCurrentStatus} 50 | 51 | 52 | 53 | 54 | )} 55 | 56 | ); 57 | }; 58 | 59 | export default TrackProgress; 60 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Support/SupportSideBar.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | // MUI Components 4 | import { Stack, Typography } from "@mui/material"; 5 | 6 | // Custom Components 7 | import ComposeMail from "./ComposeMail"; 8 | 9 | // MUI Icons 10 | import InboxIcon from "@mui/icons-material/Inbox"; 11 | import GeneralIcon from "@mui/icons-material/Info"; 12 | import FeedbackIcon from "@mui/icons-material/Feedback"; 13 | import OrderhelpIcon from "@mui/icons-material/LocalShipping"; 14 | 15 | const SidebarBtn = ({ panel, setPanel, value, Icon, txt }) => { 16 | return ( 17 | setPanel(value)} 27 | > 28 | {Icon} 29 | 30 | {txt} 31 | 32 | 33 | ); 34 | }; 35 | 36 | const SupportSideBar = ({ panel, setPanel }) => { 37 | return ( 38 | 39 | 40 | } 45 | txt="Inbox" 46 | /> 47 | } 52 | txt="General Query" 53 | /> 54 | } 59 | txt="Order Help" 60 | /> 61 | } 66 | txt="Feedback" 67 | /> 68 | 69 | ); 70 | }; 71 | 72 | export default SupportSideBar; 73 | -------------------------------------------------------------------------------- /src/components/About/AboutSocial.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | // Mui Components 4 | import { Stack, IconButton } from "@mui/material"; 5 | 6 | // Mui Icons 7 | import WebsiteIcon from "@mui/icons-material/Language"; 8 | import GitHubIcon from "@mui/icons-material/GitHub"; 9 | import FacebookIcon from "@mui/icons-material/Facebook"; 10 | import YouTubeIcon from "@mui/icons-material/YouTube"; 11 | import InstagramIcon from "@mui/icons-material/Instagram"; 12 | import LinkedInIcon from "@mui/icons-material/LinkedIn"; 13 | 14 | // Links 15 | const GITHUB_URL = "https://github.com/Bookshlf-in"; 16 | const WEBSITE_URL = "https://bookshlf.in"; 17 | const YOUTUBE_URL = "https://www.youtube.com/channel/UCvZJWq7cQ4-cGJFsCWIppGQ"; 18 | const FACEBOOK_URL = "https://www.facebook.com/Bookshlf-109479771200918"; 19 | const LINKEDIN_URL = "https://www.linkedin.com/in/bookshlf-by-aman-861073223/"; 20 | const INSTAGRAM_URL = "https://instagram.com/_bookshlf"; 21 | 22 | const AboutSocial = () => { 23 | // Opening Links 24 | const OpenLink = (link) => { 25 | window.open(link, "_blank").focus(); 26 | }; 27 | 28 | // Custom Icon Button Component 29 | const SocialLink = (props) => { 30 | return ( 31 | OpenLink(props.url)} 34 | sx={{ color: "white" }} 35 | size="small" 36 | > 37 | {props.Icon} 38 | 39 | ); 40 | }; 41 | 42 | return ( 43 | 47 | 48 | } /> 49 | } /> 50 | } /> 51 | 52 | 53 | } /> 54 | } /> 55 | } /> 56 | 57 | 58 | ); 59 | }; 60 | export default AboutSocial; 61 | -------------------------------------------------------------------------------- /src/components/About/About.js: -------------------------------------------------------------------------------- 1 | import { React } from "react"; 2 | import { Helmet } from "react-helmet-async"; 3 | import "./About.css"; 4 | 5 | // Components 6 | import { Box, Stack, Typography, Avatar } from "@mui/material"; 7 | 8 | // About Components 9 | import AboutSocial from "./AboutSocial"; 10 | import AboutTeam from "./AboutTeam"; 11 | 12 | const Year = new Date().getFullYear(); 13 | const About = () => { 14 | return ( 15 | <> 16 | 17 | About | Bookshlf 18 | 22 | 23 | 24 | 29 | 35 | 45 | BOOKSHLF 46 | 47 | 48 | 55 | TEAM 56 | 57 | 58 | 63 | {Year} 64 | 65 | 66 | 67 | 68 | ); 69 | }; 70 | export default About; 71 | -------------------------------------------------------------------------------- /src/components/SellerPanel/SellerPanel.css: -------------------------------------------------------------------------------- 1 | .sellerPanel-container .MuiTabs-flexContainer { 2 | height: 100% !important; 3 | } 4 | .seller-register-banner { 5 | width: 100%; 6 | min-height: calc(100vh - 48px); 7 | background-color: rgba(27, 16, 95, 255); 8 | color: aliceblue; 9 | padding: 16px 24px; 10 | } 11 | .seller-register-banner-img { 12 | height: auto; 13 | width: 500px; 14 | } 15 | .seller-register-banner h2 { 16 | font-family: "Staatliches", sans-serif; 17 | letter-spacing: 0.05em; 18 | } 19 | .seller-register-banner span { 20 | font-family: "Montserrat", sans-serif; 21 | text-transform: capitalize; 22 | color: rgb(255, 255, 255, 0.8); 23 | } 24 | .seller-register-form { 25 | padding: 16px 24px; 26 | position: relative; 27 | width: 100%; 28 | min-height: calc(100vh - 48px); 29 | background-color: rgba(27, 16, 95, 255); 30 | } 31 | .seller-register-form .MuiOutlinedInput-root, 32 | .seller-register-form .MuiFormHelperText-root, 33 | .seller-register-form .MuiInputLabel-root { 34 | color: rgb(219, 219, 219) !important; 35 | } 36 | .seller-register-form .MuiOutlinedInput-notchedOutline { 37 | border-color: inherit; 38 | } 39 | .seller-register-form-back { 40 | position: absolute !important; 41 | top: 0; 42 | left: 0; 43 | } 44 | .iframe-container { 45 | position: relative; 46 | overflow: hidden; 47 | width: 100%; 48 | padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */ 49 | } 50 | .responsive-iframe { 51 | position: absolute; 52 | top: 0; 53 | left: 0; 54 | bottom: 0; 55 | right: 0; 56 | width: 100%; 57 | height: 100%; 58 | } 59 | @media screen and (max-width: 850px) { 60 | .seller-register-banner-img { 61 | height: auto; 62 | width: 300px; 63 | } 64 | } 65 | @media screen and (max-width: 600px) { 66 | .seller-register-banner-img { 67 | height: auto; 68 | width: 300px; 69 | } 70 | .seller-register-banner h2 { 71 | font-size: 2em; 72 | } 73 | } 74 | @media screen and (max-width: 400px) { 75 | .seller-register-banner-img { 76 | height: auto; 77 | width: 150px; 78 | } 79 | .seller-register-banner h2 { 80 | font-size: 16px; 81 | } 82 | .seller-register-banner span { 83 | font-size: 9px; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Book/BookVerification/AdminBookDelete.js: -------------------------------------------------------------------------------- 1 | import { React, useState, useContext } from "react"; 2 | import { AdminContext } from "../../../../context/adminContext"; 3 | 4 | // API 5 | import axios from "../../../../api/axios"; 6 | 7 | // MUI Components 8 | import { IconButton, CircularProgress } from "@mui/material"; 9 | 10 | // icons 11 | import DeleteIcon from "@mui/icons-material/Delete"; 12 | 13 | const AdminBookDelete = ({ bookId }) => { 14 | // Admin Context 15 | const [admin, setAdmin] = useContext(AdminContext); 16 | 17 | // Loading States 18 | const [deleteLoad, setDeleteLoad] = useState(false); 19 | 20 | // Deleting Books 21 | const handelDeleteBook = () => { 22 | setDeleteLoad(true); 23 | axios 24 | .delete("/admin-deleteBook", { 25 | data: { 26 | bookId: bookId, 27 | message: "Book is not appropriate and have many unavoidable errors", 28 | }, 29 | }) 30 | .then((response) => { 31 | console.log(response.data); 32 | setDeleteLoad(false); 33 | setAdmin({ 34 | ...admin, 35 | bookVerification: { 36 | ...admin.bookVerification, 37 | data: admin.bookVerification.data.filter( 38 | (book) => book._id !== bookId 39 | ), 40 | }, 41 | }); 42 | localStorage.setItem( 43 | "bookshlf_admin", 44 | JSON.stringify({ 45 | ...admin, 46 | bookVerification: { 47 | ...admin.bookVerification, 48 | data: admin.bookVerification.data.filter( 49 | (book) => book._id !== bookId 50 | ), 51 | }, 52 | }) 53 | ); 54 | }) 55 | .catch((error) => { 56 | setDeleteLoad(false); 57 | console.log(error.response.data); 58 | }); 59 | }; 60 | 61 | return ( 62 | 68 | {deleteLoad ? ( 69 | 70 | ) : ( 71 | 72 | )} 73 | 74 | ); 75 | }; 76 | 77 | export default AdminBookDelete; 78 | -------------------------------------------------------------------------------- /src/components/search/searchbook.js: -------------------------------------------------------------------------------- 1 | import { Link } from "react-router-dom"; 2 | 3 | // Mui Components 4 | import { Box, Stack, Typography, Tooltip } from "@mui/material"; 5 | 6 | // assets 7 | import BookButton from "../../assets/components/buttons/bookbutton"; 8 | import WishlistButton from "../../assets/components/buttons/wishlistbutton"; 9 | import CartButton from "../../assets/components/buttons/cartbutton"; 10 | 11 | // services 12 | import { trimText } from "../../assets/utils/commons"; 13 | 14 | const BookImage = ({ photo, title }) => { 15 | return ( 16 |
17 | 18 | {title} 24 | 25 |
26 | ); 27 | }; 28 | 29 | const BookTitle = ({ title }) => { 30 | return ( 31 | 32 | {trimText(title, 60)} 33 | 34 | ); 35 | }; 36 | 37 | const BookPriceTag = ({ price }) => { 38 | return ( 39 | 40 | Rs. {price}/- 41 | 42 | ); 43 | }; 44 | 45 | const SearchBook = ({ book }) => { 46 | return ( 47 | 48 | 49 | 50 | 55 | 56 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | Buy 68 | 69 | 70 | 71 | 72 | 73 | ); 74 | }; 75 | 76 | export default SearchBook; 77 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Navigation/AdminContentPanel.js: -------------------------------------------------------------------------------- 1 | import { useContext } from "react"; 2 | import { UserContext } from "../../../context/userContext"; 3 | 4 | // Components 5 | import { Stack, Alert } from "@mui/material"; 6 | 7 | // Other Components 8 | import Books from "../Book/Book"; 9 | import Seller from "../Sellers"; 10 | import Orders from "../Order/Orders"; 11 | import Support from "../Support/Support"; 12 | import Users from "../Users"; 13 | import Wallet from "../Billing/Wallet"; 14 | import Analytics from "../Analytics/Analytics"; 15 | 16 | const PermissionAlert = ({ user, permission, content }) => { 17 | return user.adminPermissions?.includes(permission) ? ( 18 | content 19 | ) : ( 20 | 21 | You Don't have permission to access the given content. Contact super admin 22 | for permission. 23 | 24 | ); 25 | }; 26 | 27 | const AdminContentPanel = ({ Panel, setPanel, navigate }) => { 28 | const [user] = useContext(UserContext); 29 | if (Panel === 7) navigate("/"); 30 | return ( 31 | 32 | 33 | {Panel === 0 ? ( 34 | } /> 35 | ) : Panel === 1 ? ( 36 | } 40 | /> 41 | ) : Panel === 2 ? ( 42 | } 46 | /> 47 | ) : Panel === 3 ? ( 48 | } 52 | /> 53 | ) : Panel === 4 ? ( 54 | } /> 55 | ) : Panel === 5 ? ( 56 | } 60 | /> 61 | ) : Panel === 6 ? ( 62 | } 66 | /> 67 | ) : null} 68 | 69 | 70 | ); 71 | }; 72 | 73 | export default AdminContentPanel; 74 | -------------------------------------------------------------------------------- /src/route/router.js: -------------------------------------------------------------------------------- 1 | import { useRoutes } from "react-router-dom"; 2 | 3 | // Components 4 | import Login from "../components/auth/login"; 5 | import Recovery from "../components/auth/recovery/recovery"; 6 | import Signup from "../components/auth/signup/signup"; 7 | import Verify from "../components/auth/signup/verify"; 8 | import Home from "../components/home/home"; 9 | import Search from "../components/search/search"; 10 | import OrderTracking from "../components/Order/tracking/tracking"; 11 | import UserPanel from "../components/userpanel/userpanel"; 12 | import Profile from "../components/userpanel/profile"; 13 | 14 | const Router = () => { 15 | const routes = useRoutes([ 16 | { 17 | path: "/auth/login", 18 | element: , 19 | children: [ 20 | { 21 | path: ":email", 22 | element: , 23 | }, 24 | ], 25 | }, 26 | { 27 | path: "/auth/signup", 28 | element: , 29 | children: [ 30 | { 31 | path: ":email", 32 | element: , 33 | }, 34 | ], 35 | }, 36 | { 37 | path: "/auth/verify", 38 | element: , 39 | children: [ 40 | { 41 | path: ":email", 42 | element: , 43 | }, 44 | ], 45 | }, 46 | { 47 | path: "/auth/recovery", 48 | element: , 49 | children: [ 50 | { 51 | path: ":email", 52 | element: , 53 | }, 54 | ], 55 | }, 56 | { 57 | path: "/", 58 | element: , 59 | }, 60 | { 61 | path: "/search", 62 | element: , 63 | children: [ 64 | { 65 | path: ":query", 66 | element: , 67 | }, 68 | { 69 | path: ":query/:filters", 70 | element: , 71 | }, 72 | { 73 | path: ":query/:filters/:page", 74 | element: , 75 | }, 76 | ], 77 | }, 78 | { 79 | path: "/track/:orderId", 80 | element: , 81 | }, 82 | { 83 | path: "/user", 84 | element: , 85 | children: [ 86 | { 87 | path: ":panel", 88 | element: , 89 | }, 90 | ], 91 | }, 92 | ]); 93 | return routes; 94 | }; 95 | 96 | export default Router; 97 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Book/Book.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | // custom Styling 4 | import "./Book.css"; 5 | 6 | // MUI Components 7 | import { AppBar, Toolbar } from "@mui/material"; 8 | import { Stack, Typography } from "@mui/material"; 9 | 10 | // custom Components 11 | import SellerBooks from "./SellerBooks"; 12 | import BookVerification from "./BookVerification/BookVerification"; 13 | import AdminFindBook from "./AdminFindBook"; 14 | import BookshlfImageUploadUtility from "./ImageUploadUtility"; 15 | 16 | const BookNavButton = ({ panel, setPanel, btnTxt, value }) => { 17 | const handleClick = () => { 18 | setPanel(value); 19 | }; 20 | return ( 21 | 29 | 30 | {btnTxt} 31 | 32 | 33 | ); 34 | }; 35 | 36 | const BookNavBar = ({ panel, setPanel }) => { 37 | return ( 38 | 39 | 40 | 46 | 52 | 58 | 64 | 65 | 66 | ); 67 | }; 68 | 69 | const AdminBook = () => { 70 | const [panel, setPanel] = useState(0); 71 | return ( 72 | 73 | 74 | {panel === 0 ? ( 75 | 76 | ) : panel === 1 ? ( 77 | 78 | ) : panel === 2 ? ( 79 | 80 | ) : panel === 3 ? ( 81 | 82 | ) : ( 83 | <> 84 | )} 85 | 86 | ); 87 | }; 88 | 89 | export default AdminBook; 90 | -------------------------------------------------------------------------------- /src/components/userpanel/userpanel.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useContext, useCallback, Fragment } from "react"; 2 | import { useParams, useNavigate } from "react-router-dom"; 3 | import { UserContext } from "../../context/userContext"; 4 | import "./userpanel.css"; 5 | 6 | // API 7 | import { GetRequest } from "../../api/requests/getAPI"; 8 | import { userProfile, addressList, orderList } from "../../api/endpoints"; 9 | 10 | // Components 11 | import { Stack } from "@mui/material"; 12 | import Container from "../../assets/components/container"; 13 | import Profile from "./profile"; 14 | import UserNav from "./usernav"; 15 | import Address from "../AddressBook/Address"; 16 | 17 | // Services 18 | import { Sort } from "../../assets/utils/commons"; 19 | 20 | const Panels = { 21 | profile: "profile", 22 | orders: "orders", 23 | address: "address", 24 | }; 25 | 26 | const UserPanel = () => { 27 | const navigate = useNavigate(); 28 | const { panel } = useParams(); 29 | const [user] = useContext(UserContext); 30 | const [account, setAccount] = useState({}); 31 | const [orders, setOrders] = useState([]); 32 | const [address, setAddress] = useState([]); 33 | 34 | // Loading state 35 | const [loading, setLoading] = useState(true); 36 | 37 | useEffect(() => { 38 | if (!panel) navigate(`/user/${Panels.profile}`); 39 | }, [panel, navigate]); 40 | 41 | const FetchData = async () => { 42 | const profile = await GetRequest(userProfile); 43 | const addressBook = await GetRequest(addressList); 44 | const ordersList = await GetRequest(orderList); 45 | setOrders(ordersList.data); 46 | setAddress(Sort(addressBook.data, "updatedAt")); 47 | setAccount(profile.data); 48 | setLoading(false); 49 | }; 50 | 51 | useEffect(() => { 52 | FetchData(); 53 | }, []); 54 | 55 | const PanelSelector = () => { 56 | return ( 57 | 58 | {Panels.profile === panel ? ( 59 | 60 | 61 | 62 | 63 | ) : Panels.address === panel ? ( 64 |
65 | ) : ( 66 |

Orders to be made

67 | )} 68 | 69 | ); 70 | }; 71 | return ( 72 | 73 | 74 | 75 | ); 76 | }; 77 | 78 | export default UserPanel; 79 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 18 | 22 | 23 | 24 | 28 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | Bookshlf 39 | 40 | 44 | 52 | 53 | 54 | 55 |
56 | 57 | 58 | -------------------------------------------------------------------------------- /src/components/Checkout/CheckoutOrderReview.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from "react"; 2 | import { Stack, Typography, Divider, Chip } from "@mui/material"; 3 | import RupeeIcon from "@mui/icons-material/CurrencyRupee"; 4 | 5 | const CurrentAddress = ({ address, addressId }) => { 6 | const [currentAddress, setCurrentAddress] = useState( 7 | address.filter((adr) => adr._id === addressId) 8 | ); 9 | 10 | useEffect(() => { 11 | setCurrentAddress(address.filter((adr) => adr._id === addressId)); 12 | }, [address, addressId]); 13 | return ( 14 | 23 | 24 | 25 | 26 | {currentAddress[0]?.address} 27 | {currentAddress[0]?.city} 28 | {currentAddress[0]?.state} 29 | {currentAddress[0]?.zipCode} 30 | {currentAddress[0]?.phoneNo} 31 | 32 | 33 | ); 34 | }; 35 | 36 | const CheckoutOrderReview = ({ address, addressId, checkout }) => { 37 | return ( 38 | 39 | Shipping Address 40 | 41 | Payment Details 42 | 50 | Total Items : 51 | 52 | Order Total : 53 | } 55 | label={checkout.orderTotal} 56 | size="small" 57 | color="info" 58 | sx={{ width: 100 }} 59 | /> 60 | 61 | 62 | ); 63 | }; 64 | 65 | export default CheckoutOrderReview; 66 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "2.0.0", 4 | "license": "MIT", 5 | "description": "Bookshlf frontend", 6 | "keywords": [ 7 | "react", 8 | "html", 9 | "css", 10 | "javascript", 11 | "mui" 12 | ], 13 | "author": "Mrhb787", 14 | "private": true, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/Bookshlf-in/Website.git" 18 | }, 19 | "main": "app.js", 20 | "dependencies": { 21 | "@emotion/react": "^11.10.8", 22 | "@emotion/styled": "^11.10.8", 23 | "@mui/icons-material": "^5.11.6", 24 | "@mui/lab": "^5.0.0-alpha.131", 25 | "@mui/material": "^5.13.2", 26 | "@mui/x-data-grid": "^6.5.0", 27 | "apexcharts": "^3.36.3", 28 | "axios": "^1.3.5", 29 | "filepond": "^4.30.4", 30 | "react": "^18.2.0", 31 | "react-apexcharts": "^1.4.0", 32 | "react-dom": "^18.2.0", 33 | "react-filepond": "^7.1.1", 34 | "react-helmet-async": "^1.3.0", 35 | "react-router-dom": "^6.11.2", 36 | "web-vitals": "^3.3.1" 37 | }, 38 | "scripts": { 39 | "start": "react-scripts start", 40 | "build": "react-scripts build", 41 | "test": "react-scripts test --passWithNoTests", 42 | "eject": "react-scripts eject", 43 | "prettier": "prettier --write ." 44 | }, 45 | "eslintConfig": { 46 | "extends": [ 47 | "react-app", 48 | "react-app/jest" 49 | ] 50 | }, 51 | "browserslist": { 52 | "production": [ 53 | ">0.2%", 54 | "not dead", 55 | "not op_mini all" 56 | ], 57 | "development": [ 58 | "last 1 chrome version", 59 | "last 1 firefox version", 60 | "last 1 safari version" 61 | ] 62 | }, 63 | "devDependencies": { 64 | "@blacklab/react-image-magnify": "^4.1.1", 65 | "@react-hook/resize-observer": "^1.2.6", 66 | "@svgr/plugin-svgo": "^8.0.1", 67 | "@svgr/webpack": "^8.0.1", 68 | "browser-image-compression": "^2.0.2", 69 | "css-select": "^5.1.0", 70 | "detect-it": "^4.0.1", 71 | "email-validator": "^2.0.4", 72 | "filepond-plugin-file-validate-type": "^1.2.6", 73 | "filepond-plugin-image-exif-orientation": "^1.0.11", 74 | "filepond-plugin-image-preview": "^4.6.10", 75 | "nth-check": "^2.1.1", 76 | "prettier": "2.8.8", 77 | "react-error-overlay": "^6.0.11", 78 | "react-otp-input": "^3.0.2", 79 | "react-popper": "^2.3.0", 80 | "react-scripts": "^5.0.1" 81 | }, 82 | "overrides": { 83 | "@svgr/webpack": "$@svgr/webpack", 84 | "@svgr/plugin-svgo": "$@svgr/plugin-svgo" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/assets/components/input/otpfield.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { Stack, Typography, Button } from "@mui/material"; 3 | import { Alert, CircularProgress } from "@mui/material"; 4 | import OtpInput from "react-otp-input"; 5 | import Counter from "../../counter"; 6 | import { handelSendOtp } from "../../../service/auth/signup"; 7 | 8 | const OtpField = ({ 9 | otp, 10 | setOtp, 11 | otpLength = 6, 12 | email, 13 | time = 60, 14 | type = "EMAIL_VERIFICATION", 15 | }) => { 16 | const [counter, setCounter] = useState(time); 17 | const [loading, setLoading] = useState(false); 18 | const [alert, setAlert] = useState({ 19 | show: false, 20 | type: "success", 21 | msg: "OTP Sent", 22 | }); 23 | 24 | const hideAlert = () => { 25 | setTimeout(() => { 26 | setAlert({ show: false, type: "success", msg: "OTP Sent" }); 27 | }, 60000); 28 | }; 29 | 30 | const sendOtp = async () => { 31 | setLoading(true); 32 | const response = await handelSendOtp(type, { email: email }); 33 | if (response.success) { 34 | setAlert({ show: true, type: "success", msg: "OTP Sent" }); 35 | setCounter(60); 36 | hideAlert(); 37 | } else { 38 | handleOtpSendError( 39 | response.data.errors 40 | ? response.data.errors[0].error 41 | : response.data.error 42 | ); 43 | } 44 | setLoading(false); 45 | }; 46 | 47 | const handleOtpSendError = (error) => { 48 | setAlert({ show: true, type: "error", msg: error }); 49 | }; 50 | 51 | return ( 52 | 53 | Enter OTP 54 | ( 59 | 60 | )} 61 | /> 62 | {counter > 0 ? ( 63 | 64 | ) : ( 65 | 74 | )} 75 | {alert.show && ( 76 | 77 | {alert.msg} 78 | 79 | )} 80 | 81 | ); 82 | }; 83 | 84 | export default OtpField; 85 | -------------------------------------------------------------------------------- /src/components/AdminPanel/Support/SupportContent.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | 3 | // API 4 | import axios from "../../../api/axios"; 5 | 6 | // MUI Components 7 | import { Stack, Pagination, Alert } from "@mui/material"; 8 | import { CircularProgress } from "@mui/material"; 9 | import Message from "./Message"; 10 | 11 | const SupportContent = ({ panel, setPanel, page, setPage }) => { 12 | // loading 13 | const [Loading, setLoading] = useState(false); 14 | 15 | // data states 16 | const [totalPages, setTotalPages] = useState(0); 17 | const [noOfMessagesInOnePage, setnoOfMessagesInOnePage] = useState(50); 18 | const [messagesList, setMessagesList] = useState([]); 19 | 20 | // fetch users messages 21 | const fetchMessages = () => { 22 | setLoading(true); 23 | const getURL = "/admin-getMessageList"; 24 | let getParams = { 25 | page: page, 26 | noOfMessagesInOnePage: noOfMessagesInOnePage, 27 | }; 28 | if (panel > 0) { 29 | getParams = { 30 | ...getParams, 31 | queryType: 32 | panel === 1 ? "GENERAL" : panel === 2 ? "ORDER_HELP" : "FEEDBACK", 33 | }; 34 | } 35 | 36 | axios 37 | .get(getURL, { 38 | params: getParams, 39 | }) 40 | .then((res) => { 41 | // console.log(res.data); 42 | setMessagesList(res.data.data); 43 | setTotalPages(res.data.totalPages); 44 | setLoading(false); 45 | }) 46 | .catch((err) => { 47 | setLoading(false); 48 | console.log(err.response.data); 49 | }); 50 | }; 51 | 52 | useEffect(() => { 53 | fetchMessages(); 54 | }, [panel, page]); 55 | 56 | return ( 57 | 58 | setPage(pageNo)} 62 | color="primary" 63 | size="small" 64 | shape="rounded" 65 | /> 66 | 70 | {Loading && } 71 | {!Loading && messagesList && messagesList.length ? ( 72 | messagesList.map((message) => ( 73 | 74 | 75 | 76 | )) 77 | ) : !Loading ? ( 78 | No Messages Found 79 | ) : null} 80 | 81 | 82 | ); 83 | }; 84 | 85 | export default SupportContent; 86 | -------------------------------------------------------------------------------- /src/components/Order/tracking/trackingstepper.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | 3 | import { Box, Typography } from "@mui/material"; 4 | import { Step, Stepper, StepLabel, StepContent } from "@mui/material"; 5 | 6 | const steps = [ 7 | { 8 | id: "Order placed", 9 | label: "Order Placed", 10 | description: 11 | "Order has been placed and is currently pending the customer & seller confirmation", 12 | }, 13 | { 14 | id: "Cancelled", 15 | label: "Order Cancelled", 16 | description: "Order has been cancelled", 17 | }, 18 | { 19 | id: "Order Confirmed", 20 | label: "Order Confirmed", 21 | description: 22 | "Order is confirmed by customer and is pending from seller for packaging", 23 | }, 24 | { 25 | id: "Packed", 26 | label: "Order Packed", 27 | description: "Order has been packed and is ready for shipment", 28 | }, 29 | { 30 | id: "Shipped", 31 | label: "Order Shipped", 32 | description: "Shipement details manifested and order is being shipped", 33 | }, 34 | { 35 | id: "enroute", 36 | label: "Order En Route", 37 | description: "Order has been shipped and is currently on the way", 38 | }, 39 | { 40 | id: "Delivered", 41 | label: "Order Delivered", 42 | description: "Order has been successfully delivered", 43 | }, 44 | { 45 | id: "RTO", 46 | label: "RTO", 47 | description: 48 | "Order has been Rejected and is currently being returned to seller", 49 | }, 50 | { 51 | id: "Returned", 52 | label: "Returned", 53 | description: "Order has been Returned to seller", 54 | }, 55 | ]; 56 | 57 | const getActiveSteps = (status = []) => { 58 | return status.map((currentStatus) => { 59 | return steps.find((step) => step.id === currentStatus); 60 | }); 61 | }; 62 | 63 | const getActiveStep = (activeSteps = []) => { 64 | return activeSteps.length - 1; 65 | }; 66 | 67 | const TrackingStepper = ({ status = ["Order placed"] }) => { 68 | const activeSteps = getActiveSteps(status); 69 | const [activeStep] = useState(getActiveStep(activeSteps)); 70 | 71 | return ( 72 | 73 | 74 | {activeSteps.map((step, index) => ( 75 | 76 | {step.label} 77 | 78 | 79 | {step.description} 80 | 81 | 82 | 83 | ))} 84 | 85 | 86 | ); 87 | }; 88 | export default TrackingStepper; 89 | -------------------------------------------------------------------------------- /src/components/Book/AddBook.css: -------------------------------------------------------------------------------- 1 | .add-book-form-lf fieldset, 2 | .add-book-form-rt fieldset { 3 | border-radius: 5px; 4 | padding: 12px 15px; 5 | } 6 | 7 | .add-book-form-rt { 8 | margin-top: 10px; 9 | } 10 | 11 | .add-book-form-lf fieldset legend { 12 | font-family: "Roboto", sans-serif; 13 | font-weight: bold; 14 | padding: 0px 5px; 15 | } 16 | 17 | .add-book-form-lf .MuiAlert-root { 18 | font-family: "pt sans"; 19 | font-size: 0.65rem; 20 | padding: 0px 6px; 21 | justify-content: center; 22 | align-items: center; 23 | } 24 | 25 | .add-book-form-lf .searchTitleresult { 26 | position: absolute; 27 | left: 36px; 28 | top: 42px; 29 | background-color: rgba(255, 255, 255, 0.95); 30 | z-index: 200; 31 | max-height: 200px; 32 | width: 100%; 33 | max-width: 600px; 34 | overflow-y: auto; 35 | overflow-x: hidden; 36 | box-shadow: 6px 3px 3px rgba(0, 0, 0, 0.2); 37 | border-radius: 5px; 38 | } 39 | 40 | .add-book-form-lf .searchTagresult { 41 | position: absolute; 42 | left: 36px; 43 | top: 42px; 44 | background-color: rgba(255, 255, 255, 0.95); 45 | z-index: 200; 46 | max-height: 200px; 47 | width: 165px; 48 | overflow-y: auto; 49 | overflow-x: hidden; 50 | box-shadow: 6px 3px 3px rgba(0, 0, 0, 0.2); 51 | border-radius: 5px; 52 | } 53 | 54 | .searchTitleresult #result-title { 55 | padding: 6px; 56 | font-size: 12px; 57 | } 58 | 59 | .searchTagresult #result-tag { 60 | padding: 6px; 61 | } 62 | 63 | .add-book-bg .MuiAlert-message { 64 | font-family: "PT sans" !important; 65 | } 66 | 67 | /* ========= Filepond custom css =========== */ 68 | .filepond--wrapper { 69 | width: 100% !important; 70 | } 71 | 72 | .filepond--drop-label { 73 | min-height: 4em !important; 74 | background-color: cornflowerblue; 75 | color: whitesmoke; 76 | border-radius: 5px; 77 | } 78 | 79 | .filepond--drop-label { 80 | color: whitesmoke !important; 81 | } 82 | 83 | .filepond--label-action { 84 | background-color: #333; 85 | padding: 6px 10px; 86 | text-decoration: none !important; 87 | border-radius: 5px; 88 | } 89 | 90 | .filepond--list.filepond--list { 91 | top: 10px !important; 92 | } 93 | 94 | @media (min-width: 30em) { 95 | .filepond--item { 96 | width: calc(50% - 0.5em); 97 | } 98 | } 99 | 100 | @media (min-width: 50em) { 101 | .filepond--item { 102 | width: calc(25% - 0.5em); 103 | } 104 | } 105 | 106 | /* ========= ============ =========== */ 107 | 108 | @media screen and (max-width: 400px) { 109 | 110 | .add-book-form-lf, 111 | .add-book-form-rt { 112 | padding: 0px; 113 | } 114 | } -------------------------------------------------------------------------------- /src/components/BookDetails/BookPurchaseAdmin.js: -------------------------------------------------------------------------------- 1 | // hooks 2 | import { useState } from "react"; 3 | 4 | // MUI Components 5 | import { Button, Dialog, Stack, Typography } from "@mui/material"; 6 | import { TextField, Alert, CircularProgress } from "@mui/material"; 7 | 8 | // micro components 9 | import CopyableText from "../MicroComponents/customCopyText"; 10 | 11 | // Methods 12 | import { 13 | handleOpen, 14 | handleClose, 15 | adminBookPurchase, 16 | } from "../../service/Book/AdminBookPurchase/purchaseOrder"; 17 | 18 | const BookPurchaseAdmin = ({ bookId }) => { 19 | // states 20 | const [open, setOpen] = useState(false); 21 | const [orderId, setOrderId] = useState(""); 22 | const [orderLoad, setOrderLoad] = useState(false); 23 | const [error, setError] = useState(false); 24 | const [success, setSuccess] = useState(false); 25 | 26 | // utitility function to call admin purchase 27 | const purchaseBook = (orderId) => { 28 | adminBookPurchase( 29 | orderId, 30 | setOrderId, 31 | setOrderLoad, 32 | bookId, 33 | setSuccess, 34 | setOpen, 35 | setError 36 | ); 37 | }; 38 | 39 | return ( 40 |
41 | 48 | handleClose(setOpen)}> 49 | 50 | 51 | Book ID 52 | 53 | 54 | purchaseBook(e.target.value.trim())} 60 | /> 61 | 72 | {error && ( 73 | 74 | Error Occured. Check Order Id and Try Again! 75 | 76 | )} 77 | {success && Order Placed!} 78 | 79 | 80 |
81 | ); 82 | }; 83 | 84 | export default BookPurchaseAdmin; 85 | -------------------------------------------------------------------------------- /src/components/home/home.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Helmet } from "react-helmet-async"; 3 | import "./home.css"; 4 | 5 | // Home Components 6 | import Carousel from "../../assets/components/carousel"; 7 | import Categories from "./Categories"; 8 | import Benefits from "./Benefits"; 9 | import Reviews from "../Reviews/CustomerReviews"; 10 | import Footer from "../Footer/Footer"; 11 | 12 | const Home = () => { 13 | return ( 14 | <> 15 | 16 | 17 | Bookshlf | Buy and Sell Used Books, Second Hand Books Online 18 | 19 | {/* */} 20 | 60 | 61 | 62 | 63 | 64 | 65 |