├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── dependabot.yml │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── SECURITY.md ├── auth0icon.jpg ├── blogs ├── dev.md └── technicalBlog.md ├── client ├── .eslintrc.cjs ├── .gitignore ├── Dockerfile ├── index.html ├── package-lock.json ├── package.json ├── postcss.config.js ├── public │ ├── favicon.ico │ └── favicon_io │ │ ├── about.txt │ │ ├── android-chrome-192x192.png │ │ ├── android-chrome-512x512.png │ │ ├── apple-touch-icon.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ └── site.webmanifest ├── src │ ├── App.jsx │ ├── Components │ │ ├── BookList.jsx │ │ ├── Cart.jsx │ │ ├── Footer.jsx │ │ ├── Header.jsx │ │ ├── Loading.jsx │ │ ├── Logo.tsx │ │ ├── Search.jsx │ │ ├── TopButton.jsx │ │ └── index.js │ ├── Pages │ │ └── index.js │ ├── index.css │ ├── main.jsx │ └── utils │ │ ├── CartContext.jsx │ │ └── index.js ├── tailwind.config.js └── vite.config.js ├── design ├── booklist.md └── newlayout.md └── package-lock.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "npm" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | 8 | open-pull-requests-limit: 5 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Optional stylelint cache 58 | .stylelintcache 59 | 60 | # Microbundle cache 61 | .rpt2_cache/ 62 | .rts2_cache_cjs/ 63 | .rts2_cache_es/ 64 | .rts2_cache_umd/ 65 | 66 | # Optional REPL history 67 | .node_repl_history 68 | 69 | # Output of 'npm pack' 70 | *.tgz 71 | 72 | # Yarn Integrity file 73 | .yarn-integrity 74 | 75 | # dotenv environment variable files 76 | .env 77 | .env.development.local 78 | .env.test.local 79 | .env.production.local 80 | .env.local 81 | 82 | # parcel-bundler cache (https://parceljs.org/) 83 | .cache 84 | .parcel-cache 85 | 86 | # Next.js build output 87 | .next 88 | out 89 | 90 | # Nuxt.js build / generate output 91 | .nuxt 92 | dist 93 | 94 | # Gatsby files 95 | .cache/ 96 | # Comment in the public line in if your project uses Gatsby and not Next.js 97 | # https://nextjs.org/blog/next-9-1#public-directory-support 98 | # public 99 | 100 | # vuepress build output 101 | .vuepress/dist 102 | 103 | # vuepress v2.x temp and cache directory 104 | .temp 105 | .cache 106 | 107 | # Docusaurus cache and generated files 108 | .docusaurus 109 | 110 | # Serverless directories 111 | .serverless/ 112 | 113 | # FuseBox cache 114 | .fusebox/ 115 | 116 | # DynamoDB Local files 117 | .dynamodb/ 118 | 119 | # TernJS port file 120 | .tern-port 121 | 122 | # Stores VSCode versions used for testing VSCode extensions 123 | .vscode-test 124 | 125 | # yarn v2 126 | .yarn/cache 127 | .yarn/unplugged 128 | .yarn/build-state.yml 129 | .yarn/install-state.gz 130 | .pnp.* -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | ricochetthestoryteller2001@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to MyLibrary 📚 2 | 3 | Welcome to MyLibrary, a modern library management web application built with React.js, Vite, and Tailwind CSS. We're excited to have you as a potential contributor to our project. Whether you're a developer, designer, writer, or anyone enthusiastic about making MyLibrary better, there are numerous ways to get involved. 4 | 5 | ## 📝 Table of Contents 6 | - [🛠️ How to Contribute](#how-to-contribute) 7 | - [🐛 Reporting Issues](#reporting-issues) 8 | - [🎉 Hacktoberfest Participation](#hacktoberfest-participation) 9 | - [🧰 Coding Guidelines](#coding-guidelines) 10 | - [🔗 Creating Pull Requests](#creating-pull-requests) 11 | - [📖 Documentation](#documentation) 12 | 13 | 14 | ## 🛠️ How to Contribute 15 | 16 | Contributions to MyLibrary can encompass various forms, including but not limited to: 17 | 18 | - **Code Contributions:** Help us develop new features, enhance existing functionality, or fix bugs. 19 | - **Design Contributions:** Contribute to the UI and UX design of MyLibrary. 20 | - **Documentation Contributions:** Improve our project's documentation for users and contributors. 21 | - **Writing Contributions:** Create technical blogs, case studies, or guides related to MyLibrary. 22 | - **Testing Contributions:** Assist in identifying and resolving issues through testing. 23 | - **Feedback and Ideas:** Share your thoughts, ideas, and feedback in the Discussions section. 24 | 25 | ## 🐛 Reporting Issues 26 | 27 | If you encounter a bug, have a feature request, or any questions, please [create an issue](https://github.com/suryanshsingh2001/MyLibrary/issues). Be sure to provide detailed information to help us understand and address the issue effectively. 28 | 29 | ## 🎉 Hacktoberfest Participation 30 | 31 | MyLibrary actively participates in Hacktoberfest, an annual celebration of open-source contributions. Here's how you can join the Hacktoberfest fun with us: 32 | 33 | 1. Look for issues labeled as "Hacktoberfest" in our [GitHub issue tracker](https://github.com/suryanshsingh2001/MyLibrary/issues). These are specially curated issues for Hacktoberfest contributors. 34 | 35 | 2. Contribute to these issues by following the guidelines mentioned in each issue. You can work on bug fixes, features, or enhancements. 36 | 37 | 3. Submit your pull request (PR) with your contribution. Our team will review your PR and provide feedback. 38 | 39 | 4. Once your PR is merged, it will count towards your participation in Hacktoberfest. Plus, you'll be helping us improve MyLibrary! 40 | 41 | ## 🧰 Coding Guidelines 42 | 43 | When writing code for MyLibrary, please follow these guidelines: 44 | 45 | - Maintain the existing coding style and conventions used in the project. 46 | - Use clear and descriptive variable and function names. 47 | - Document your code changes, especially if they introduce new functionality. 48 | - Write tests for new features and ensure all tests pass before submitting a PR. 49 | 50 | ## 🔗 Creating Pull Requests 51 | 52 | To contribute code to MyLibrary, follow these steps: 53 | 54 | 1. Create a new branch for your contribution: 55 | ```bash 56 | git checkout -b feature/your-feature-name 57 | ``` 58 | 59 | 2. Write your code and make regular commits. 60 | 61 | 3. Push your branch to your GitHub fork: 62 | 63 | ```bash 64 | git push origin feature/your-feature-name 65 | ``` 66 | 4. Create a pull request (PR) from your branch to the main MyLibrary repository. Ensure your PR includes a clear description of the changes and references any related issues. 67 | 68 | 5. Our team will review your PR, provide feedback, and work with you to address any necessary changes. 69 | 70 | 6. Once your PR is approved, it will be merged into the main repository 71 | 72 | ## 📖 Documentation 73 | Clear and well-structured documentation is essential for MyLibrary. If you're interested in contributing to documentation: 74 | 75 | - Update and improve existing documentation. 76 | - Create new documentation for features or components. 77 | - Ensure documentation is accurate and follows best practices. 78 | 79 | --- 80 | Feel free to share your thoughts, ask questions, or engage in discussions with other contributors and users. Your feedback plays a vital role in shaping the future of MyLibrary, so don't hesitate to participate in the conversation! -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Suryansh Singh 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MyLibrary 📚 2 | [![version](https://img.shields.io/badge/version-2.0.0--beta-yellow)](https://github.com/suryanshsingh2001/MyLibrary) 3 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/suryanshsingh2001/MyLibrary/blob/main/LICENSE) 4 | [![GitHub Issues](https://img.shields.io/github/issues/suryanshsingh2001/MyLibrary.svg)](https://github.com/suryanshsingh2001/MyLibrary/issues) 5 | 6 | website 7 | 8 | 9 | MyLibrary is a modern and user-friendly library management web application built with React.js, Vite, Tailwind CSS, and powered by the Google API for fetching book data. It also incorporates Auth0 for secure authentication and session management, Font Awesome icons for styling, Axios for API calls, React Infinite Scroll for lazy loading, Toastify for notification messages, and `react-autocomplete` for search suggestions. 10 | 11 | 12 | 🚨 **Important Note**: 13 | 14 | We are currently in the process of transitioning our authentication provider to Firebase. Please refer to the `firebase` branch for the latest updates and instructions related to Firebase authentication. 15 | 16 | 🔗 [Live Link](https://mylibrary01.vercel.app/) 17 | 18 | https://github.com/user-attachments/assets/725b2b4a-5b79-4c4b-bc12-24aac7006516 19 | 20 | 🔗 [Video Link](https://drive.google.com/file/d/1kc842eXRTWBl9BZlxkU-aSq8w5mqV5Z2/view?usp=drive_link) 21 | 22 | ## Table of Contents 23 | - [MyLibrary 📚](#mylibrary-) 24 | - [Table of Contents](#table-of-contents) 25 | - [Tech Stack 🛠️](#tech-stack-️) 26 | - [Features ✅](#features-) 27 | - [Configuration - Setting Up API Keys 🛠️](#configuration---setting-up-api-keys-) 28 | - [Project Dockerization 📦](#project-dockerization-) 29 | - [Getting Started 🚀](#getting-started-) 30 | - [Contributing 🤝](#contributing-) 31 | - [Code of Conduct 📜](#code-of-conduct-) 32 | - [Hacktoberfest Contribution 🎃](#hacktoberfest-contribution-) 33 | - [Security 🔒](#security-) 34 | - [Feedback 💬](#feedback-) 35 | - [License 📝](#license-) 36 | 37 | ## Tech Stack 🛠️ 38 | 39 | - [Vite](https://vitejs.dev/) - Fast React.js build tool. 40 | - [React.js](https://reactjs.org/) - JavaScript library for building user interfaces. 41 | - [Tailwind CSS](https://tailwindcss.com/) - A utility-first CSS framework for fast and customizable styling. 42 | - [Google Books API](https://developers.google.com/books/docs/overview) - Used as the endpoint for book data. 43 | - [Auth0](https://auth0.com/) - Authentication and session management. 44 | - [Font Awesome](https://fontawesome.com/) - Icon library for styling. 45 | - [Axios](https://axios-http.com/) - Promise-based HTTP client for API calls. 46 | - [React Infinite Scroll](https://github.com/ankeetmaini/react-infinite-scroll-component) - Infinite scrolling component for efficient pagination. 47 | - [Toastify](https://fkhadra.github.io/react-toastify/introduction/) - React notification library for user feedback. 48 | - [react-autocomplete](https://github.com/reactjs/react-autocomplete) - React component for search suggestions. 49 | - [Vercel](https://vercel.com/) - Deployment platform for hosting web applications. 50 | 51 | --- 52 | 53 | ## Features ✅ 54 | - [x] An aesthetically pleasing and optimized loading animation. 55 | - [x] New user signup and login, using Proper authentication and sessions (Sign in with social media, Email and mobile number verification gets extra brownie points). 56 | - [x] Users can see the list of books, preferably using an actual endpoint (API) as a data source for books. 57 | - [x] Instead of loading all the results on the page, perform an optimized pagination (infinite scrolling with lazy loading). 58 | - [x] A well-built search bar, with suggestions (like Google Search, YouTube) that suggests and searches based on all the fields like Book name, Author name, Genre, Year of publishing, etc. 59 | - [x] An exclusive way of indicating the availability of the books, and the number of available copies, along with the previously mentioned fields. 60 | - [x] Users can filter and sort the list of books based on Title, Author, Subject, and Publish - date. 61 | - [x] Show the count of books upon every search results and upon every filtering. 62 | - [x] Implement a cart feature, upon adding books to the cart, the user will be able to check out and rent them. This should reflect in the availability and number of copies fields. 63 | 64 | --- 65 | ## Configuration - Setting Up API Keys 🛠️ 66 | 67 | To use certain features of the MyLibrary project, you'll need to configure the following API keys: 68 | 69 | 1. 📚 **Google Books API Key**: This key is required to fetch book information from Google Books API. 70 | 71 | 2. 🔐 **Auth0 Domain and Client ID**: These are required for authentication and user management. 72 | 73 | Follow these steps to set up the API keys: 74 | 75 | ### 1. Google Books API Key 76 | 77 | To obtain a Google Books API Key: 78 | 79 | 1. 🌐 Visit the [Google Cloud Console](https://console.cloud.google.com/). 80 | 2. 🏗️ Create a new project if you haven't already. 81 | 3. 🛠️ Navigate to the "APIs & Services" > "Credentials" section. 82 | 4. ➕ Click on "Create Credentials" and select "API Key." 83 | 5. 📋 Copy the generated API key. 84 | 85 | ### 2. Auth0 Domain and Client ID 86 | 87 | To obtain Auth0 credentials: 88 | 89 | 1. 🌐 Visit [Auth0](https://auth0.com/) and sign in or create an account. 90 | 2. 🏗️ Create a new application or use an existing one. 91 | 3. ⚙️ Navigate to the "Settings" of your Auth0 application. 92 | 4. 📋 Find and copy the "Domain" and "Client ID." 93 | 94 | ### 3. Create a .env File 95 | 96 | Once you have obtained the necessary API keys, create a `.env` file in the project root directory (if it doesn't already exist) and add the following environment variables with your API keys: 97 | 98 | ```env 99 | VITE_REACT_APP_GOOGLEBOOK_API_KEY=YOUR_GOOGLEBOOK_API_KEY 100 | VITE_REACT_APP_AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN 101 | VITE_REACT_APP_AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID 102 | ``` 103 | 104 | Replace YOUR_GOOGLEBOOK_API_KEY, YOUR_AUTH0_DOMAIN, and YOUR_AUTH0_CLIENT_ID with the respective values you obtained from Google and Auth0. 105 | 106 | Make sure to keep your .env file secure and do not share your API keys publicly. 107 | 108 | Now, you have successfully configured the required API keys for the MyLibrary project. You can start using these keys in your code to access Google Books API and authenticate with Auth0. 109 | 110 | --- 111 | 112 | ## Project Dockerization 📦 113 | 114 | To run RepoSavant in a Docker container, follow these steps: 115 | 116 | 1. Clone this repository. 117 | 2. Build the Docker image: 118 | ```bash[] 119 | docker build --pull --rm -f "Dockerfile" -t mylibrary:latest 120 | ``` 121 | 3. Run the Docker container: 122 | ```bash[] 123 | docker run --rm -d -p 8080:8080/tcp mylibrary:latest 124 | ``` 125 | --- 126 | ## Getting Started 🚀 127 | 128 | Follow these steps to set up, run, and deploy MyLibrary on Vercel: 129 | 130 | 1. Clone the repository: 131 | 132 | ```bash 133 | git clone https://github.com/suryanshsingh2001/MyLibrary.git 134 | cd client 135 | ``` 136 | 2. Install Dependencies when in `client` Directory 137 | 138 | ``` 139 | npm install 140 | ``` 141 | 3. Configure environment variables: Create a `.env` file and provide the necessary API keys and Auth0 credentials. 142 | 143 | ``` 144 | VITE_REACT_APP_GOOGLEBOOK_API_KEY=YOUR_GOOGLEBOOK_API_KEY 145 | 146 | VITE_REACT_APP_AUTH0_DOMAIN=YOUR_AUTH0_DOMAIN 147 | VITE_REACT_APP_AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID 148 | 149 | ``` 150 | 151 | 4. Start the development server: 152 | 153 | ``` 154 | npm run dev 155 | ``` 156 | 5. Open your browser and access `http://localhost:5173`. 157 | 158 | 6. Deploy on Vercel: 159 | - Sign up for an account on [Vercel](https://vercel.com/). 160 | - Follow Vercel's deployment instructions to connect your GitHub repository and deploy your app. 161 | 162 | 163 | ## Contributing 🤝 164 | We welcome contributions from the community! Whether you are a developer, designer, writer, or enthusiast, there are many ways to get involved. Check out our [**Contributing Guidelines**](https://github.com/suryanshsingh2001/MyLibrary/blob/main/CONTRIBUTING.md) to learn more about how you can contribute. 165 | 166 | 167 | 168 | 169 | 170 | ## Code of Conduct 📜 171 | Please review our [**Code of Conduct**](https://github.com/suryanshsingh2001/MyLibrary/blob/main/CODE_OF_CONDUCT.md) to understand the expectations for behavior within our community. 172 | 173 | ## Hacktoberfest Contribution 🎃 174 | MyLibrary actively participates in Hacktoberfest, an annual celebration of open-source contributions. Here's how you can join the Hacktoberfest fun with us: 175 | 176 | 1. Look for issues labeled as `Hacktoberfest` in our GitHub issue tracker. These are specially curated issues for Hacktoberfest contributors. 177 | 2. Contribute to these issues by following the guidelines mentioned in each issue. You can work on bug fixes, features, or enhancements. 178 | 179 | 3. Submit your pull request (PR) with your contribution. Our team will review your PR and provide feedback. 180 | 181 | 4. Once your PR is merged, it will count towards your participation in Hacktoberfest. Plus, you'll be helping us improve MyLibrary! 182 | 183 | ## Security 🔒 184 | The security of MyLibrary is important to us. If you discover any security vulnerabilities, please review our [**Security Policy**](https://github.com/suryanshsingh2001/MyLibrary/blob/main/SECURITY.md) for reporting guidelines. 185 | 186 | ## Feedback 💬 187 | We value your feedback and suggestions. Whether you have ideas for new features, bug reports, or general feedback, please visit our Feedback Section to share your thoughts. 188 | 189 | ## License 📝 190 | MyLibrary is open-source software licensed under the MIT License. 191 | 192 | --- 193 | 194 | >"Let's write the next chapter together!" 📝🌟 195 | Happy coding and happy reading! 📚🚀 196 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Please review the table below to understand which versions of MyLibrary are currently supported with security updates: 6 | 7 | | Version | Supported | 8 | | ------- | ------------------ | 9 | | 1.0.x | :white_check_mark: | 10 | | 0.9.x | :x: | 11 | | 0.8.x | :white_check_mark: | 12 | | < 0.8 | :x: | 13 | 14 | - :white_check_mark: Supported with security updates. 15 | - :x: Not supported with security updates. 16 | 17 | ## Reporting a Vulnerability 18 | 19 | If you discover a security vulnerability in MyLibrary, please help us by reporting it. We take security seriously and will do our best to address the issue promptly. 20 | 21 | To report a vulnerability, please follow these steps: 22 | 23 | 1. **Email:** Send an email to [ricocchetthestoryteller2001@gmail.com](mailto:ricocchetthestoryteller2001@gmail.com) with a detailed description of the vulnerability. Please include steps to reproduce the vulnerability if possible. 24 | 25 | 2. **Subject:** Use a clear and descriptive subject line for your email, such as "Security Vulnerability Report - MyLibrary." 26 | 27 | 3. **Response Time:** You can expect to receive an initial response to your report within 72 hours, acknowledging that we have received it. 28 | 29 | 4. **Investigation:** Our security team will investigate the reported vulnerability to assess its validity and potential impact. 30 | 31 | 5. **Resolution:** If the vulnerability is accepted, we will work on resolving it promptly. Once resolved, we will notify you and provide details about the fix. 32 | 33 | We appreciate your responsible disclosure of security vulnerabilities in MyLibrary. Your cooperation helps us maintain the security of our project and protect our users. 34 | 35 | Thank you for helping to keep MyLibrary secure. 36 | -------------------------------------------------------------------------------- /auth0icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/auth0icon.jpg -------------------------------------------------------------------------------- /blogs/dev.md: -------------------------------------------------------------------------------- 1 | [Dev.toBlogLink](https://dev.to/suryanshsingh2001/join-the-mylibrary-revolution-unleash-your-creativity-through-contribution-33bj) -------------------------------------------------------------------------------- /blogs/technicalBlog.md: -------------------------------------------------------------------------------- 1 | ## Technical Blog Link : [Blog](https://medium.com/@ayushvish6555/mylibrary-revolutionizing-library-management-with-modern-web-technology-a548f4a524ba) 2 | -------------------------------------------------------------------------------- /client/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { browser: true, es2020: true }, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:react/recommended', 7 | 'plugin:react/jsx-runtime', 8 | 'plugin:react-hooks/recommended', 9 | ], 10 | ignorePatterns: ['dist', '.eslintrc.cjs'], 11 | parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, 12 | settings: { react: { version: '18.2' } }, 13 | plugins: ['react-refresh'], 14 | rules: { 15 | 'react-refresh/only-export-components': [ 16 | 'warn', 17 | { allowConstantExport: true }, 18 | ], 19 | }, 20 | } 21 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:17-alpine 2 | 3 | WORKDIR /mylibrary 4 | 5 | COPY package.json . 6 | 7 | RUN npm install 8 | 9 | COPY . . 10 | 11 | EXPOSE 8080 12 | 13 | CMD ["npm", "run", "dev"] -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 17 | 18 | 22 | 26 | 27 | 28 | 29 | 30 | MyLibrary 31 | 61 | 62 | 63 | 64 |
65 |
66 |
67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "client", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 0", 10 | "preview": "vite preview" 11 | }, 12 | "dependencies": { 13 | "@auth0/auth0-react": "^2.2.1", 14 | "@emotion/styled": "^11.11.0", 15 | "@fortawesome/fontawesome-svg-core": "^6.4.2", 16 | "@fortawesome/free-brands-svg-icons": "^6.4.2", 17 | "@fortawesome/react-fontawesome": "^0.2.0", 18 | "@mui/icons-material": "^5.14.13", 19 | "axios": "^1.5.0", 20 | "firebase": "^10.4.0", 21 | "lodash.debounce": "^4.0.8", 22 | "react": "^18.2.0", 23 | "react-autosuggest": "^10.1.0", 24 | "react-dom": "^18.2.0", 25 | "react-infinite-scroll-component": "^6.1.0", 26 | "react-router-dom": "^6.16.0", 27 | "react-select": "^5.7.7", 28 | "react-toastify": "^9.1.3" 29 | }, 30 | "devDependencies": { 31 | "@types/react": "^18.2.15", 32 | "@types/react-dom": "^18.2.7", 33 | "@vitejs/plugin-react": "^4.0.3", 34 | "autoprefixer": "^10.4.16", 35 | "eslint": "^8.45.0", 36 | "eslint-plugin-react": "^7.32.2", 37 | "eslint-plugin-react-hooks": "^4.6.0", 38 | "eslint-plugin-react-refresh": "^0.4.3", 39 | "postcss": "^8.4.30", 40 | "tailwindcss": "^3.3.3", 41 | "vite": "^4.4.5" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /client/postcss.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon.ico -------------------------------------------------------------------------------- /client/public/favicon_io/about.txt: -------------------------------------------------------------------------------- 1 | This favicon was generated using the following font: 2 | 3 | - Font Title: Lalezar 4 | - Font Author: Copyright 2015 by Borna Izadpanah (www.borna.design). All rights reserved. 5 | - Font Source: http://fonts.gstatic.com/s/lalezar/v14/zrfl0HLVx-HwTP82UaDyIiL0RCg.ttf 6 | - Font License: SIL Open Font License, 1.1 (http://scripts.sil.org/OFL)) 7 | -------------------------------------------------------------------------------- /client/public/favicon_io/android-chrome-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon_io/android-chrome-192x192.png -------------------------------------------------------------------------------- /client/public/favicon_io/android-chrome-512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon_io/android-chrome-512x512.png -------------------------------------------------------------------------------- /client/public/favicon_io/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon_io/apple-touch-icon.png -------------------------------------------------------------------------------- /client/public/favicon_io/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon_io/favicon-16x16.png -------------------------------------------------------------------------------- /client/public/favicon_io/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon_io/favicon-32x32.png -------------------------------------------------------------------------------- /client/public/favicon_io/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/public/favicon_io/favicon.ico -------------------------------------------------------------------------------- /client/public/favicon_io/site.webmanifest: -------------------------------------------------------------------------------- 1 | {"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} -------------------------------------------------------------------------------- /client/src/App.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import { BrowserRouter as Router, Route, Routes } from "react-router-dom"; 3 | import debounce from "lodash.debounce"; 4 | import { CartProvider } from "./utils/CartContext"; 5 | import { BookList, Header, Search, Cart, Footer, TopButton } from "./Components"; 6 | import { ToastContainer } from "react-toastify"; 7 | 8 | const App = () => { 9 | const [searchQuery, setSearchQuery] = useState(""); 10 | const [selectedFilter, setSelectedFilter] = useState("title"); 11 | const [selectedSort, setSelectedSort] = useState("relevance"); 12 | 13 | const handleSearch = debounce((query) => { 14 | setSearchQuery(query); 15 | }, 300); 16 | 17 | const handleFilterChange = (selectedFilter) => { 18 | setSelectedFilter(selectedFilter); 19 | }; 20 | 21 | const handleSortChange = (selectedSort) => { 22 | setSelectedSort(selectedSort); 23 | }; 24 | 25 | return ( 26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 | 34 | 38 | 43 | 48 |
57 |
58 |
59 |
60 | ); 61 | }; 62 | 63 | export default App; 64 | -------------------------------------------------------------------------------- /client/src/Components/BookList.jsx: -------------------------------------------------------------------------------- 1 | import React, { useCallback, useEffect, useRef, useState } from 'react'; 2 | import axios from 'axios'; 3 | import { useCart } from '../utils/CartContext'; // Import useCart hook 4 | import { toast } from 'react-toastify'; 5 | import 'react-toastify/dist/ReactToastify.css'; 6 | import { useAuth0 } from '@auth0/auth0-react'; // Import useAuth0 for user authentication 7 | 8 | // Helper function to generate random integers 9 | function getRandomInt(min, max) { 10 | return Math.floor(Math.random() * (max - min + 1)) + min; 11 | } 12 | 13 | const BookList = ({ searchQuery, selectedSort }) => { 14 | const [books, setBooks] = useState([]); // Initialize books as an empty array 15 | const [loading, setLoading] = useState(true); 16 | const { addToCart, cartItems } = useCart(); // Access addToCart function and cartItems from CartContext 17 | const { isAuthenticated } = useAuth0(); // Access isAuthenticated from Auth0 18 | const [selectedResults, setSelectedResults] = useState(10); // Reduced Results to optimize API Key Usage 19 | const [page, setPage] = useState(0); 20 | const observer = useRef(); 21 | 22 | const fetchBooks = useCallback(() => { 23 | const apiKey = import.meta.env.VITE_REACT_APP_GOOGLE_API_KEY; 24 | const query = searchQuery ? `intitle:${searchQuery}` : 'programming'; // Filter by title if searchQuery is provided, else use a default query 25 | const startIndex = page * selectedResults; 26 | 27 | axios 28 | .get( 29 | `https://www.googleapis.com/books/v1/volumes?q=${query}&key=${apiKey}&startIndex=${startIndex}&maxResults=${selectedResults}&orderBy=${selectedSort}` 30 | ) 31 | .then((response) => { 32 | if (response.data.items) { 33 | const booksData = response.data.items.map((book) => { 34 | // Determine availability information (more available than unavailable) 35 | const isAvailable = Math.random() < 0.7; // 70% chance of being available 36 | const availableCopies = isAvailable ? getRandomInt(15, 35) : 0; 37 | 38 | return { 39 | id: book.id, 40 | title: book.volumeInfo.title, 41 | author: book.volumeInfo.authors 42 | ? book.volumeInfo.authors.join(', ') 43 | : 'Unknown', 44 | subject: book.volumeInfo.categories 45 | ? book.volumeInfo.categories.join(', ') 46 | : 'Unknown', 47 | published: book.volumeInfo.publishedDate || 'Unknown', 48 | isAvailable, // Store availability status 49 | availableCopies, // Store available copies 50 | image: book.volumeInfo.imageLinks?.thumbnail || '', // Image URL 51 | }; 52 | }); 53 | setBooks((prevBooks) => 54 | page === 0 ? booksData : [...prevBooks, ...booksData] 55 | ); 56 | } 57 | setLoading(false); 58 | }) 59 | .catch((error) => { 60 | console.error('Error fetching book data:', error); 61 | setLoading(false); 62 | }); 63 | }, [searchQuery, selectedResults, page, selectedSort]); 64 | 65 | useEffect(() => { 66 | setBooks([]); // Reset books if searchQuery changes 67 | setPage(0); // Reset page number 68 | }, [searchQuery, selectedResults]); 69 | 70 | useEffect(() => { 71 | fetchBooks(); 72 | }, [fetchBooks]); 73 | 74 | const handleAddToCart = (bookId) => { 75 | if (!isAuthenticated) { 76 | // Check if the user is not logged in 77 | toast.error('Please log in to use this feature.', { 78 | position: toast.POSITION.TOP_CENTER, 79 | autoClose: 3000, 80 | hideProgressBar: true, 81 | closeButton: false, 82 | }); 83 | return; 84 | } 85 | 86 | const updatedBooks = books.map((book) => { 87 | if (book.id === bookId && book.isAvailable) { 88 | addToCart(book); // Add the book to the cart 89 | const updatedCopies = book.availableCopies - 1; 90 | const updatedBook = { 91 | ...book, 92 | addedToCart: true, 93 | availableCopies: updatedCopies, 94 | }; 95 | toast.success(`"${updatedBook.title}" has been added to your cart.`, { 96 | position: toast.POSITION.TOP_CENTER, // Set the toast position 97 | autoClose: 3000, // Close the toast after 3 seconds (adjust as needed) 98 | hideProgressBar: true, // Hide the progress bar 99 | closeButton: false, // Do not show a close button 100 | }); 101 | return updatedBook; 102 | } 103 | return book; 104 | }); 105 | setBooks(updatedBooks); 106 | }; 107 | 108 | const handleResultsChange = (event) => { 109 | setSelectedResults(event.target.value); 110 | setPage(0); 111 | }; 112 | 113 | // const lastBookElementRef = useCallback( 114 | // (node) => { 115 | // if (loading) return; 116 | // if (observer.current) observer.current.disconnect(); 117 | // observer.current = new IntersectionObserver((entries) => { 118 | // if (entries[0].isIntersecting) { 119 | // setPage((prevPage) => prevPage + 1); // Increment page number 120 | // } 121 | // }); 122 | // if (node) observer.current.observe(node); // Observe new last book element 123 | // }, 124 | // [loading] 125 | // ); 126 | const loadMore = () =>{ 127 | setPage((prevPage) => prevPage + 1); // Increment page number 128 | } 129 | 130 | return ( 131 |
132 |

133 | Explore Our Collection 134 |

135 |

136 | Discover a wide variety of books in our collection. Whether you're 137 | searching for fiction, non-fiction, or a specific genre, we have 138 | something for every book lover. 139 |

140 | 141 |
142 | 145 | 155 |
156 | {loading ? ( 157 |

Loading...

158 | ) : ( 159 |
160 | {books.map((book, index) => { 161 | const isLastBook = index === books.length - 1; // Determine if the current book is the last one 162 | return ( 163 |
168 |
169 |

170 | {book.title} 171 |

172 | {book.isAvailable ? ( 173 |

174 | Available -{' '} 175 | 176 | {book.availableCopies}{' '} 177 | {book.availableCopies === 1 ? 'copy' : 'copies'} 178 | 179 |

180 | ) : ( 181 |

182 | Not Available 183 |

184 | )} 185 | {book.title} 190 |
191 |

Author: {book.author || 'Unknown'}

192 |

Genre: {book.subject || 'Unknown'}

193 |

194 | Published: {book.published || 'Unknown'} 195 |

196 |
197 |
198 |
199 | {book.addedToCart ? ( 200 | 206 | ) : ( 207 | 218 | )} 219 |
220 |
221 | ); 222 | })} 223 |
224 | 225 | )} 226 |
227 |
228 | 229 | 230 |
231 |
232 |
233 | ); 234 | }; 235 | 236 | export default BookList; 237 | -------------------------------------------------------------------------------- /client/src/Components/Cart.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { useCart } from "../utils/CartContext"; 3 | import { toast } from "react-toastify"; // Import the toast module 4 | import { Link, useNavigate } from "react-router-dom"; 5 | 6 | const Cart = () => { 7 | const { cartItems, removeFromCart, clearCart } = useCart(); 8 | const navigate = useNavigate(); 9 | 10 | const goBack = () => { 11 | navigate("/"); 12 | }; 13 | 14 | const goToRentConfirmation = () => { 15 | if (cartItems.length === 0) { 16 | // Check if the cart is empty 17 | toast.error("Your cart is empty. Please add items to rent.", { 18 | position: toast.POSITION.BOTTOM_RIGHT, 19 | autoClose: 3000, 20 | hideProgressBar: true, 21 | closeButton: false, 22 | }); 23 | } else { 24 | // Cart is not empty 25 | clearCart(); // Clear the cart 26 | toast.success( 27 | "Hurrah! 🎉 You've Successfully Rented the Selected Items. Enjoy Your Reading Adventure!", 28 | { 29 | position: toast.POSITION.TOP_CENTER, 30 | autoClose: 3000, 31 | hideProgressBar: true, 32 | closeButton: false, 33 | } 34 | ); 35 | } 36 | }; 37 | 38 | return ( 39 |
40 |
41 |

Shopping Cart

42 | {cartItems.length === 0 ? ( 43 |
44 |

45 | Oops! Your Cart is Empty{" "} 46 | 47 | 😊 48 | 49 |

50 |

51 | It's a bit lonely in here! Why not start adding some amazing books 52 | to your cart? Happy shopping! 53 |

54 | 55 | 61 |
62 | ) : ( 63 |
64 |
65 | {cartItems.map((item) => ( 66 |
70 |

{item.title}

71 |
72 |

Author: {item.author}

73 |

Genre: {item.genre}

74 |

Publish Date: {item.published}

75 |
76 |
Quantity: {item.quantity}
77 |
78 | 84 |
85 |
86 | ))} 87 |
88 | 89 |
90 | 99 | 107 |
108 |
109 | )} 110 |
111 |
112 | ); 113 | }; 114 | 115 | export default Cart; 116 | -------------------------------------------------------------------------------- /client/src/Components/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; 4 | import { faGithub } from "@fortawesome/free-brands-svg-icons"; 5 | import "../index.css"; 6 | 7 | const Footer = () => { 8 | return ( 9 | 39 | ); 40 | }; 41 | 42 | export default Footer; 43 | -------------------------------------------------------------------------------- /client/src/Components/Header.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { Link } from "react-router-dom"; 3 | import { useAuth0 } from "@auth0/auth0-react"; 4 | import { useCart } from "../utils/CartContext"; 5 | import { useNavigate } from "react-router-dom"; 6 | import { toast } from "react-toastify"; 7 | import "react-toastify/dist/ReactToastify.css"; 8 | import Logo from "./Logo"; 9 | 10 | const Header = () => { 11 | const { loginWithRedirect, isAuthenticated, logout, user } = useAuth0(); 12 | const { cartItems } = useCart(); 13 | const navigate = useNavigate(); 14 | const isTrue = true; // Variable to temporarily store true value 15 | 16 | // Function to navigate to the cart page if logged in, show prompt if not 17 | const handleCartClick = () => { 18 | if (isTrue) { //Change to isAuthenticated to enable authentication 19 | navigate("/cart"); 20 | } else { 21 | toast.error("Please log in to access the cart.", { 22 | position: toast.POSITION.TOP_CENTER, 23 | autoClose: 3000, 24 | hideProgressBar: true, 25 | closeButton: false, 26 | }); 27 | } 28 | }; 29 | 30 | return ( 31 |
32 |
33 | {/* Brand Logo as a Link with Bounce Animation */} 34 | 39 | 40 | 41 |
42 | {/* Display user name if authenticated */} 43 | {isAuthenticated && ( 44 | 45 | Hello, {user.name} 46 | 47 | )} 48 | 49 | {/* Navigation */} 50 | 95 | 96 |
97 |
98 |
99 | ); 100 | }; 101 | 102 | export default Header; 103 | -------------------------------------------------------------------------------- /client/src/Components/Loading.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Loading = () => { 4 | return ( 5 |
6 |
7 | Loading... 8 |
9 |
10 | ); 11 | }; 12 | 13 | export default Loading; 14 | -------------------------------------------------------------------------------- /client/src/Components/Logo.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | const Logo = () => { 4 | return ( 5 |
6 |

7 | My Library 8 |

9 |
10 |
11 |
12 |
13 |
14 |
15 | ); 16 | }; 17 | 18 | export default Logo; 19 | -------------------------------------------------------------------------------- /client/src/Components/Search.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from "react"; 2 | import AsyncSelect from "react-select/async"; 3 | import { toast } from "react-toastify"; 4 | import axios from "axios"; 5 | 6 | const Search = ({ onSearch, onFilterChange, onSortChange }) => { 7 | const [selectedFilter, setSelectedFilter] = useState("title"); 8 | const [selectedSort, setSelectedSort] = useState("relevance"); 9 | 10 | const filters = ["title", "author", "subject", "published"]; 11 | const sortOptions = ["relevance", "newest"]; 12 | 13 | // used to check if one toast is already displaying and prevent multiple toasts 14 | const toastId = React.useRef(null); 15 | 16 | const notifyerror = (msg) => { 17 | if (!toast.isActive(toastId.current)) { 18 | toastId.current = toast.error(msg); 19 | } 20 | }; 21 | 22 | const handleFilterChange = (event) => { 23 | setSelectedFilter(event.target.value); 24 | onFilterChange(event.target.value); 25 | }; 26 | 27 | const handleSortChange = (event) => { 28 | setSelectedSort(event.target.value); 29 | onSortChange(event.target.value); 30 | }; 31 | 32 | function handleSelect(input) { 33 | onSearch(input.label); 34 | } 35 | 36 | function handleChange(input) { 37 | if (!input) return []; 38 | onSearch(input); 39 | return axios 40 | .get( 41 | `https://www.googleapis.com/books/v1/volumes?q=${encodeURIComponent( 42 | input 43 | )}` 44 | ) 45 | .then((res) => { 46 | const data = res.data; 47 | const opts = data.items.map((d) => { 48 | return { 49 | value: d.id, 50 | label: `${d.volumeInfo.title}${ 51 | d.volumeInfo.publisher ? `, ${d.volumeInfo.publisher}` : "" 52 | }`, 53 | }; 54 | }); 55 | return opts; 56 | }) 57 | .catch((err) => { 58 | notifyerror(err.message); 59 | return []; 60 | }); 61 | } 62 | 63 | return ( 64 |
65 |
66 | 73 |
74 | {/* Added ml-4 here */} 75 |
76 | 79 | 91 |
92 |
93 | 96 | 108 |
109 |
110 |
111 |
112 |
113 | ); 114 | }; 115 | 116 | export default Search; 117 | -------------------------------------------------------------------------------- /client/src/Components/TopButton.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react'; 2 | import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward'; 3 | 4 | export const TopButton = () => { 5 | const [isVisible, setIsVisible] = useState(false); 6 | const [isHovered, setIsHovered] = useState(false); 7 | 8 | // Show button when the page is scrolled down 9 | const toggleVisibility = () => { 10 | if (window.scrollY > 50) { 11 | setIsVisible(true); 12 | } else { 13 | setIsVisible(false); 14 | } 15 | }; 16 | 17 | // Scroll to the top smoothly 18 | const scrollToTop = () => { 19 | window.scrollTo({ 20 | top: 0, 21 | behavior: 'smooth', 22 | }); 23 | }; 24 | 25 | useEffect(() => { 26 | window.addEventListener('scroll', toggleVisibility); 27 | return () => window.removeEventListener('scroll', toggleVisibility); 28 | }, []); 29 | 30 | return ( 31 |
42 |
{ 59 | setIsHovered(true); 60 | }} 61 | onMouseLeave={() => { 62 | setIsHovered(false); 63 | }} 64 | > 65 | 66 |
67 |
68 | ); 69 | }; 70 | -------------------------------------------------------------------------------- /client/src/Components/index.js: -------------------------------------------------------------------------------- 1 | import Header from "./Header"; 2 | import Search from "./Search"; 3 | 4 | import BookList from "./BookList"; 5 | import Cart from "./Cart"; 6 | import Loading from "./Loading"; 7 | import Footer from "./Footer"; 8 | import { TopButton } from "./TopButton"; 9 | 10 | export { 11 | Header, 12 | Search, 13 | BookList, 14 | Cart, 15 | Loading, 16 | Footer, 17 | TopButton 18 | } -------------------------------------------------------------------------------- /client/src/Pages/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/src/Pages/index.js -------------------------------------------------------------------------------- /client/src/index.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | .logoFont { 6 | font-family: "Kodchasan", sans-serif; 7 | } 8 | .logoIcon{ 9 | @apply w-3 h-7 sm:w-4 sm:h-10 bg-white group-hover:bg-black 10 | } 11 | 12 | /* width */ 13 | ::-webkit-scrollbar { 14 | width: 10px; 15 | border-radius: 5px; 16 | } 17 | 18 | /* Track */ 19 | ::-webkit-scrollbar-track { 20 | background: rgb(226, 209, 195); 21 | box-shadow: inset 0 0 5px rgb(226, 209, 195); 22 | border-radius: 5px; 23 | } 24 | 25 | /* Handle */ 26 | ::-webkit-scrollbar-thumb { 27 | background: rgb(82, 63, 27); 28 | border-radius: 5px; 29 | } 30 | 31 | .page-turn { 32 | transition: transform 0.3s ease-in-out; 33 | } 34 | 35 | .page-turn:hover { 36 | transform: perspective(1000px) rotateY(10deg); 37 | } 38 | 39 | .zoom-in { 40 | transition: transform 0.3s ease-in-out; 41 | } 42 | 43 | .zoom-in:hover { 44 | transform: scale(1.1); 45 | } 46 | -------------------------------------------------------------------------------- /client/src/main.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App.jsx"; 4 | import "./index.css"; 5 | import { Auth0Provider } from "@auth0/auth0-react"; 6 | 7 | const auth0Config = { 8 | domain: import.meta.env.VITE_REACT_APP_AUTH0_DOMAIN, 9 | clientId: import.meta.env.VITE_REACT_APP_AUTH0_CLIENT_ID, 10 | redirectUri: window.location.origin, 11 | }; 12 | ReactDOM.createRoot(document.getElementById("root")).render( 13 | 14 | 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /client/src/utils/CartContext.jsx: -------------------------------------------------------------------------------- 1 | import React, { createContext, useState, useContext, useEffect } from "react"; 2 | 3 | // Create a context 4 | const CartContext = createContext(); 5 | 6 | // Create a provider component that will wrap your entire application 7 | const CartProvider = ({ children }) => { 8 | const [cartItems, setCartItems] = useState([]); 9 | 10 | // Function to load cart data from localStorage on component mount 11 | useEffect(() => { 12 | const savedCart = localStorage.getItem("cart"); 13 | if (savedCart) { 14 | setCartItems(JSON.parse(savedCart)); 15 | } 16 | }, []); 17 | 18 | // Function to save cart data to localStorage whenever cartItems change 19 | useEffect(() => { 20 | localStorage.setItem("cart", JSON.stringify(cartItems)); 21 | }, [cartItems]); 22 | 23 | const addToCart = (item) => { 24 | // Include additional details in the item 25 | const newItem = { 26 | id: item.id, 27 | title: item.title, 28 | author: item.author, 29 | genre: item.subject, // Include genre 30 | published: item.published, 31 | quantity: 1, 32 | }; 33 | 34 | setCartItems([...cartItems, newItem]); 35 | }; 36 | 37 | const removeFromCart = (itemId) => { 38 | const updatedCart = cartItems.filter((item) => item.id !== itemId); 39 | setCartItems(updatedCart); 40 | }; 41 | 42 | const clearCart = () => { 43 | setCartItems([]); 44 | }; 45 | 46 | return ( 47 | 50 | {children} 51 | 52 | ); 53 | }; 54 | 55 | // Create a custom hook to access the cart context 56 | const useCart = () => { 57 | return useContext(CartContext); 58 | }; 59 | 60 | export { CartProvider, useCart }; 61 | -------------------------------------------------------------------------------- /client/src/utils/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suryanshsingh2001/MyLibrary/bc9d882f9a979a3c7489c624342f5200491d806c/client/src/utils/index.js -------------------------------------------------------------------------------- /client/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | export default { 3 | content: [ 4 | "./index.html", 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | fontSize: { 9 | xs: ['12px', '16px'], 10 | sm: ['14px', '20px'], 11 | base: ['16px', '19.5px'], 12 | lg: ['18px', '21.94px'], 13 | xl: ['20px', '24.38px'], 14 | '2xl': ['24px', '29.26px'], 15 | '3xl': ['28px', '50px'], 16 | '4xl': ['48px', '58px'], 17 | '8xl': ['96px', '106px'] 18 | }, 19 | 20 | extend: { 21 | fontFamily: { 22 | palanquin: ['Palanquin', 'sans-serif'], 23 | montserrat: ['Montserrat', 'sans-serif'], 24 | }, 25 | colors: { 26 | 'primary': "#ECEEFF", 27 | "coral-red": "#D400FF", 28 | "slate-gray": "#6D6D6D", 29 | "pale-blue": "#F5F6FF", 30 | "white-400": "rgba(255, 255, 255, 0.80)" 31 | }, 32 | boxShadow: { 33 | '3xl': '0 10px 40px rgba(0, 0, 0, 0.1)' 34 | }, 35 | backgroundImage: { 36 | 'hero': "url('assets/images/collection-background.svg')", 37 | 'card': "url('assets/images/thumbnail-background.svg')", 38 | }, 39 | screens: { 40 | "wide": "1440px" 41 | } 42 | }, 43 | }, 44 | plugins: [], 45 | } -------------------------------------------------------------------------------- /client/vite.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite' 2 | import react from '@vitejs/plugin-react' 3 | 4 | // https://vitejs.dev/config/ 5 | export default defineConfig({ 6 | plugins: [react()], 7 | server: { 8 | watch: { 9 | usePolling: true, 10 | }, 11 | host: true, // needed for the Docker Container port mapping to work 12 | strictPort: true, 13 | // port: 8080 // you can replace this port with any port 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /design/booklist.md: -------------------------------------------------------------------------------- 1 | Add your designs here\ -------------------------------------------------------------------------------- /design/newlayout.md: -------------------------------------------------------------------------------- 1 | # Improved Layout Design for Book Lists 2 | 3 | ## Introduction 4 | This pull request showcases a comprehensive UI/UX redesign for the book lists layout in the MyLibrary 📚 web application. The MyLibrary app is a modern library management tool developed using React.js, featuring 🔐 Auth0 for authentication and utilizing 📖 Google Books API for book data. The user interface has been styled with 🎨 Tailwind CSS to provide an exceptional user experience. 5 | 6 | ## Design Overview 7 | The primary goal of this redesign is to elevate both the user interface (UI) and user experience (UX) of the book lists within the MyLibrary project. We have focused on proposing an improved layout design that enhances accessibility, usability, and visual appeal. 8 | 9 | ## Design Assets 10 | - **Desktop Size**: 1356px by [Height] 11 | - **Book Title**: Roboto, 22px for the title, 24px for lineheight, color #1f2937 12 | - **Availability**: Segeo UI, 16px for content, 24px for hlineheight, no color change 13 | - **Published Date, Author, Genre**: Inter, 16px for content, 20px for lineheight, using brand color medium 14 | - **Author's Name, Genre Type, Published Date**: Inter Regular, 14px for content, 20px for lineheight 15 | - **Button Text**: Space Grotesk Bold, 18px 16 | - **Filtered and Sorted by**: Brand color, 18px for content, 20px for lineheight 17 | - **Filter By, Sort By**: Segeo UI, 20px for content, 24px for lineheight 18 | 19 | - **Link to Figma design**: [https://www.figma.com/file/2Ioo7XKcrMX4Qs8gVnFmlh/MyLibrary?type=design&node-id=4%3A892&mode=design&t=LWf4xbRAXAOMHrG3-1] 20 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "MyLibrary", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | --------------------------------------------------------------------------------