├── public
├── robots.txt
├── favicon.ico
├── logo192.png
├── logo512.png
├── manifest.json
└── index.html
├── .babelrc
├── src
├── App.css
├── component
│ ├── books.js
│ ├── Navbar.js
│ ├── category.js
│ ├── form.js
│ ├── book.js
│ └── books.css
├── redux
│ ├── configStore.js
│ ├── categories
│ │ └── categories.js
│ └── books
│ │ └── books.js
├── index.js
├── index.css
├── App.js
└── API
│ └── bookapi.js
├── .gitignore
├── .hintrc
├── .stylelintrc.json
├── .eslintrc.json
├── README.md
├── package.json
└── .github
└── workflows
└── linters.yml
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Basir-Mohammadi/book-store-react/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Basir-Mohammadi/book-store-react/HEAD/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Basir-Mohammadi/book-store-react/HEAD/public/logo512.png
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | "@babel/preset-react"
4 | ],
5 | "plugins": ["@babel/plugin-syntax-jsx"]
6 | }
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | text-decoration: none;
5 | }
6 |
7 | #root {
8 | background: #e6e6e6;
9 | height: 100vh;
10 | }
11 |
--------------------------------------------------------------------------------
/src/component/books.js:
--------------------------------------------------------------------------------
1 | import Form from './form';
2 | import Book from './book';
3 |
4 | const Books = () => (
5 |
6 |
7 |
8 |
9 | );
10 |
11 | export default Books;
12 |
--------------------------------------------------------------------------------
/src/redux/configStore.js:
--------------------------------------------------------------------------------
1 | import { configureStore } from '@reduxjs/toolkit';
2 | import booksReducer from './books/books';
3 | import categoriesReducer from './categories/categories';
4 |
5 | const store = configureStore({
6 | reducer: {
7 | bookStore: booksReducer,
8 | categoriesReducer,
9 | },
10 | });
11 |
12 | export default store;
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/.hintrc:
--------------------------------------------------------------------------------
1 | {
2 | "connector": {
3 | "name": "local",
4 | "options": {
5 | "pattern": ["**", "!.git/**", "!node_modules/**"]
6 | }
7 | },
8 | "extends": ["development"],
9 | "formatters": ["stylish"],
10 | "hints": [
11 | "button-type",
12 | "disown-opener",
13 | "html-checker",
14 | "meta-charset-utf-8",
15 | "meta-viewport",
16 | "no-inline-styles:error"
17 | ]
18 | }
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom/client';
3 | import './index.css';
4 | import { Provider } from 'react-redux';
5 | import App from './App';
6 | import store from './redux/configStore';
7 |
8 | const root = ReactDOM.createRoot(document.getElementById('root'));
9 | root.render(
10 |
11 |
12 |
13 |
14 | ,
15 |
16 | );
17 |
--------------------------------------------------------------------------------
/src/component/Navbar.js:
--------------------------------------------------------------------------------
1 | import './books.css';
2 | import { Link } from 'react-router-dom';
3 |
4 | const Navbar = () => (
5 |
15 | );
16 |
17 | export default Navbar;
18 |
--------------------------------------------------------------------------------
/src/component/category.js:
--------------------------------------------------------------------------------
1 | import { useSelector, useDispatch } from 'react-redux/es/exports';
2 | import './books.css';
3 | import { CheckStatus } from '../redux/categories/categories';
4 |
5 | const Category = () => {
6 | const response = useSelector((state) => state.categoriesReducer);
7 | const dispatch = useDispatch();
8 | return (
9 |
10 |
11 |
{response}
12 |
13 | );
14 | };
15 |
16 | export default Category;
17 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | font-family:
4 | -apple-system,
5 | BlinkMacSystemFont,
6 | 'Segoe UI',
7 | 'Roboto',
8 | 'Oxygen',
9 | 'Ubuntu',
10 | 'Cantarell',
11 | 'Fira Sans',
12 | 'Droid Sans',
13 | 'Helvetica Neue',
14 | sans-serif;
15 | -webkit-font-smoothing: antialiased;
16 | -moz-osx-font-smoothing: grayscale;
17 | }
18 |
19 | code {
20 | font-family:
21 | source-code-pro,
22 | Menlo,
23 | Monaco,
24 | Consolas,
25 | 'Courier New',
26 | monospace;
27 | }
28 |
--------------------------------------------------------------------------------
/src/redux/categories/categories.js:
--------------------------------------------------------------------------------
1 | const CHECK_STATUS = 'book-store-react/categories/CHECK_STATUS';
2 |
3 | // Reducer
4 | const categoriesReducer = (state = [], action) => {
5 | switch (action.type) {
6 | case CHECK_STATUS:
7 | return action.text;
8 | default:
9 | return state;
10 | }
11 | };
12 |
13 | // Action Creators
14 | export const CheckStatus = () => {
15 | const status = {
16 | type: CHECK_STATUS,
17 | text: 'Under construction',
18 | };
19 | return status;
20 | };
21 |
22 | export default categoriesReducer;
23 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/.stylelintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["stylelint-config-standard"],
3 | "plugins": ["stylelint-scss", "stylelint-csstree-validator"],
4 | "rules": {
5 | "at-rule-no-unknown": [
6 | true,
7 | {
8 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
9 | }
10 | ],
11 | "scss/at-rule-no-unknown": [
12 | true,
13 | {
14 | "ignoreAtRules": ["tailwind", "apply", "variants", "responsive", "screen"]
15 | }
16 | ],
17 | "csstree/validator": true
18 | },
19 | "ignoreFiles": ["build/**", "dist/**", "**/reset*.css", "**/bootstrap*.css", "**/*.js", "**/*.jsx"]
20 | }
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "browser": true,
4 | "es6": true,
5 | "jest": true
6 | },
7 | "parser": "@babel/eslint-parser",
8 | "parserOptions": {
9 | "ecmaFeatures": {
10 | "jsx": true
11 | },
12 | "ecmaVersion": 2018,
13 | "sourceType": "module"
14 | },
15 | "extends": ["airbnb", "plugin:react/recommended"],
16 | "plugins": ["react"],
17 | "rules": {
18 | "react/jsx-filename-extension": ["warn", { "extensions": [".js", ".jsx"] }],
19 | "react/react-in-jsx-scope": "off",
20 | "import/no-unresolved": "off",
21 | "no-shadow": "off",
22 | "import/no-named-as-default": 0
23 | },
24 | "ignorePatterns": [
25 | "dist/",
26 | "build/"
27 | ]
28 | }
--------------------------------------------------------------------------------
/src/App.js:
--------------------------------------------------------------------------------
1 | import './App.css';
2 | import {
3 | BrowserRouter as Router, Switch, Route,
4 | } from 'react-router-dom';
5 | import Navbar from './component/Navbar';
6 | import Books from './component/books';
7 | import Category from './component/category';
8 | import Form from './component/form';
9 | import './component/books.css';
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | );
33 | }
34 |
35 | export default App;
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # book-store-react
2 |
3 | 
4 |
5 | > This is a website that allows users to add/remove books from a list. This project is build using JavaScript objects and arrays.
6 |
7 |
8 | ## Built With
9 |
10 | - HTML
11 | - CSS
12 | - Javascript
13 | - React
14 |
15 | ## Getting Started
16 |
17 | To get a local copy up and running follow these simple example steps.
18 |
19 | - Clone repository in your local machine
20 | - cd Portfolio
21 | - open `index.html` in your browser.
22 | - You can use live server.
23 |
24 | ## Live Demo
25 |
26 | [Books Live](https://book2store-react.herokuapp.com/)
27 |
28 | ## Author
29 |
30 | 👤 **Basir Mohammadi**
31 |
32 | - GitHub: [@basirking](https://github.com/Basir-Mohammadi)
33 | - LinkedIn: [Basir Mohammadi](https://www.linkedin.com/in/basirahmad1312/)
34 |
35 |
36 |
37 | ## 🤝 Contributing
38 |
39 | Contributions, issues, and feature requests are welcome!
40 |
41 | Feel free to check the [https://github.com/Basir-Mohammadi/Awesome_Books/issues](https://github.com/Basir-Mohammadi/book-store-react/issues)
42 |
43 | ## Show your support
44 |
45 | Give a ⭐️ to if you like this project!
46 |
47 |
48 | ## Acknowledgments
49 |
50 | - Hat tip to anyone whose code was used
51 | - Inspiration
52 | - etc
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/src/API/bookapi.js:
--------------------------------------------------------------------------------
1 | const API_URL = 'https://us-central1-bookstore-api-e63c8.cloudfunctions.net/bookstoreApi';
2 |
3 | // app id from the local storage
4 | const appId = '6QokoJSAh5dHBW2fXVma';
5 | export const getBooks = async () => {
6 | const response = await fetch(`${API_URL}/apps/${appId}/books`,
7 | {
8 | method: 'GET',
9 | headers: {
10 | 'Content-Type': 'application/json',
11 | },
12 | });
13 | const bookList = [];
14 | const books = await response.json().then((data) => data)
15 | .catch((err) => { console.log('Error', err); });
16 | Object.keys(books).forEach((book) => {
17 | books[book][0].id = book;
18 | bookList.push(books[book][0]);
19 | });
20 | return bookList;
21 | };
22 |
23 | export const postBook = async (bookdetails) => {
24 | const response = await fetch(`${API_URL}/apps/${appId}/books`,
25 | {
26 | method: 'POST',
27 | headers: { 'Content-Type': 'application/json' },
28 | body: JSON.stringify(bookdetails),
29 | });
30 | const book = await response.text().then((data) => data).catch((err) => { console.log('Error', err); });
31 | await getBooks();
32 | return book;
33 | };
34 |
35 | export const deleteBook = async (bookId) => {
36 | const response = await fetch(`${API_URL}/apps/${appId}/books/${bookId}`,
37 | {
38 | method: 'DELETE',
39 | headers: {
40 | 'Content-Type': 'application/json',
41 | },
42 | });
43 | await response.json();
44 | return bookId;
45 | };
46 |
--------------------------------------------------------------------------------
/src/redux/books/books.js:
--------------------------------------------------------------------------------
1 | import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
2 | import { getBooks, deleteBook, postBook } from '../../API/bookapi';
3 |
4 | const ADD_BOOK = 'book-store-react/books/ADD_BOOK';
5 | const FETCH_BOOKS = 'book-store-react/books/FETCH_BOOKS';
6 | const REMOVE_BOOK = 'book-store-react/books/REMOVE_BOOK';
7 |
8 | // fetch books from the api
9 | export const fetchBooks = createAsyncThunk(FETCH_BOOKS,
10 | async () => {
11 | const response = await getBooks();
12 | return response;
13 | });
14 | // add book to api
15 | export const addBook = createAsyncThunk(ADD_BOOK,
16 | async (bookdetails) => {
17 | const response = await postBook(bookdetails);
18 | return response;
19 | });
20 |
21 | // remove book from the api
22 | export const removeBook = createAsyncThunk(REMOVE_BOOK,
23 | async (bookId) => {
24 | const response = await deleteBook(bookId);
25 | return response;
26 | });
27 |
28 | const slice = createSlice({
29 | name: 'books',
30 | initialState: [],
31 | extraReducers: (builder) => {
32 | builder.addCase(
33 | fetchBooks.fulfilled,
34 | (books, action) => action.payload,
35 | );
36 | builder.addCase(addBook.fulfilled, (books, action) => {
37 | books.push(action.payload);
38 | });
39 | builder.addCase(removeBook.fulfilled,
40 | (books, action) => books.filter((book) => book.id !== action.payload));
41 | },
42 | });
43 | export const booksList = (state) => state.bookList;
44 | export default slice.reducer;
45 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "book-store-react",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@reduxjs/toolkit": "^1.8.3",
7 | "@testing-library/jest-dom": "^5.16.4",
8 | "@testing-library/react": "^13.3.0",
9 | "@testing-library/user-event": "^13.5.0",
10 | "react": "^18.2.0",
11 | "react-dom": "^18.2.0",
12 | "react-js-progressbar": "^1.1.1",
13 | "react-redux": "^8.0.2",
14 | "react-router-dom": "^5.3.3",
15 | "react-scripts": "5.0.1",
16 | "react-step-progress-bar": "^1.0.3",
17 | "uniqid": "^5.4.0",
18 | "web-vitals": "^2.1.4"
19 | },
20 | "scripts": {
21 | "start": "react-scripts start",
22 | "build": "react-scripts build",
23 | "test": "react-scripts test",
24 | "eject": "react-scripts eject"
25 | },
26 | "eslintConfig": {
27 | "extends": [
28 | "react-app",
29 | "react-app/jest"
30 | ]
31 | },
32 | "browserslist": {
33 | "production": [
34 | ">0.2%",
35 | "not dead",
36 | "not op_mini all"
37 | ],
38 | "development": [
39 | "last 1 chrome version",
40 | "last 1 firefox version",
41 | "last 1 safari version"
42 | ]
43 | },
44 | "devDependencies": {
45 | "@babel/core": "^7.18.6",
46 | "@babel/eslint-parser": "^7.18.2",
47 | "@babel/plugin-syntax-jsx": "^7.18.6",
48 | "@babel/preset-react": "^7.18.6",
49 | "eslint": "^7.32.0",
50 | "eslint-config-airbnb": "^18.2.1",
51 | "eslint-plugin-import": "^2.26.0",
52 | "eslint-plugin-jsx-a11y": "^6.6.0",
53 | "eslint-plugin-react": "^7.30.1",
54 | "eslint-plugin-react-hooks": "^4.6.0",
55 | "stylelint": "^13.13.1",
56 | "stylelint-config-standard": "^21.0.0",
57 | "stylelint-csstree-validator": "^1.9.0",
58 | "stylelint-scss": "^3.21.0"
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/component/form.js:
--------------------------------------------------------------------------------
1 | import { useDispatch } from 'react-redux/es/exports';
2 | import React, { useState, useEffect } from 'react';
3 | import uniqid from 'uniqid';
4 | import { addBook, fetchBooks } from '../redux/books/books';
5 | import './books.css';
6 |
7 | const Form = () => {
8 | const dispatch = useDispatch();
9 | const [state, setState] = useState({
10 | item_id: uniqid(),
11 | title: '',
12 | author: '',
13 | category: '',
14 | });
15 |
16 | const handleChanges = (e) => {
17 | setState({
18 | ...state, [e.target.name]: e.target.value,
19 | });
20 | };
21 |
22 | useEffect(() => {
23 | dispatch(fetchBooks());
24 | }, []);
25 |
26 | const handleSubmit = (e) => {
27 | e.preventDefault();
28 | dispatch(addBook(state));
29 | setState({
30 | item_id: uniqid(),
31 | title: '',
32 | author: '',
33 | category: '',
34 | });
35 | dispatch(fetchBooks());
36 | e.target.reset();
37 | };
38 |
39 | return (
40 |
54 | );
55 | };
56 |
57 | export default Form;
58 |
--------------------------------------------------------------------------------
/.github/workflows/linters.yml:
--------------------------------------------------------------------------------
1 | name: Linters
2 |
3 | on: pull_request
4 |
5 | env:
6 | FORCE_COLOR: 1
7 |
8 | jobs:
9 | eslint:
10 | name: ESLint
11 | runs-on: ubuntu-18.04
12 | steps:
13 | - uses: actions/checkout@v2
14 | - uses: actions/setup-node@v1
15 | with:
16 | node-version: "12.x"
17 | - name: Setup ESLint
18 | run: |
19 | npm install --save-dev eslint@7.x eslint-config-airbnb@18.x eslint-plugin-import@2.x eslint-plugin-jsx-a11y@6.x eslint-plugin-react@7.x eslint-plugin-react-hooks@4.x @babel/eslint-parser@7.x @babel/core@7.x @babel/plugin-syntax-jsx@7.x @babel/preset-env@7.x @babel/preset-react@7.x
20 | [ -f .eslintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.eslintrc.json
21 | [ -f .babelrc ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.babelrc
22 | - name: ESLint Report
23 | run: npx eslint .
24 | stylelint:
25 | name: Stylelint
26 | runs-on: ubuntu-18.04
27 | steps:
28 | - uses: actions/checkout@v2
29 | - uses: actions/setup-node@v1
30 | with:
31 | node-version: "12.x"
32 | - name: Setup Stylelint
33 | run: |
34 | npm install --save-dev stylelint@13.x stylelint-scss@3.x stylelint-config-standard@21.x stylelint-csstree-validator@1.x
35 | [ -f .stylelintrc.json ] || wget https://raw.githubusercontent.com/microverseinc/linters-config/master/react-redux/.stylelintrc.json
36 | - name: Stylelint Report
37 | run: npx stylelint "**/*.{css,scss}"
38 | nodechecker:
39 | name: node_modules checker
40 | runs-on: ubuntu-18.04
41 | steps:
42 | - uses: actions/checkout@v2
43 | - name: Check node_modules existence
44 | run: |
45 | if [ -d "node_modules/" ]; then echo -e "\e[1;31mThe node_modules/ folder was pushed to the repo. Please remove it from the GitHub repository and try again."; echo -e "\e[1;32mYou can set up a .gitignore file with this folder included on it to prevent this from happening in the future." && exit 1; fi
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
14 |
18 |
19 |
28 | React App
29 |
30 |
31 |
32 |
33 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/component/book.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect } from 'react';
2 | import { useSelector, useDispatch } from 'react-redux';
3 | import Progressbar from 'react-js-progressbar';
4 | import { removeBook, fetchBooks } from '../redux/books/books';
5 | import './books.css';
6 |
7 | const Book = () => {
8 | const books = useSelector((state) => state.bookStore);
9 | const dispatch = useDispatch();
10 | useEffect(() => {
11 | dispatch(fetchBooks());
12 | }, [books]);
13 | return (books.map((book) => (
14 |
15 |
16 |
Action
17 |
{book.category}
18 |
{book.title}
19 |
{book.author}
20 |
21 |
22 |
35 |
36 |
37 |
38 |
51 |
52 |
CURRENT CHAPTER
53 | CHAPTER 16
54 |
55 |
56 |
57 | )));
58 | };
59 |
60 | export default Book;
61 |
--------------------------------------------------------------------------------
/src/component/books.css:
--------------------------------------------------------------------------------
1 | .nav-content {
2 | list-style: none;
3 | margin-top: 2vh;
4 | display: flex;
5 | padding-left: 10%;
6 | height: 6vh;
7 | }
8 |
9 | .navbar {
10 | display: flex;
11 | justify-content: space-between;
12 | width: 100%;
13 | background-color: white;
14 | }
15 |
16 | .nav-content li {
17 | color: #0290ff;
18 | font-size: 20px;
19 | font-weight: 700;
20 | font-family: 'Montserrat-Bold', sans-serif;
21 | margin-right: 15px;
22 | margin-left: 10px;
23 | }
24 |
25 | .profile {
26 | padding: 11px;
27 | border: solid 1px #e8e8e8;
28 | border-radius: 60%;
29 | margin: 5px 5px;
30 | }
31 |
32 | .profile i {
33 | color: #0290ff;
34 | }
35 |
36 | .main-area ul li {
37 | border-right: 2px solid #1f7199;
38 | padding-right: 10px;
39 | margin-top: 12px;
40 | }
41 |
42 | .nav-content li:nth-child(2) {
43 | color: #121212;
44 | font-size: 18px;
45 | font-family: 'Montserrat-Regular', sans-serif;
46 | font-weight: 500;
47 | }
48 |
49 | .nav-content li:nth-child(3) {
50 | color: #121212;
51 | font-size: 16px;
52 | font-family: "Montserrat-Regular", sans-serif;
53 | font-weight: 300;
54 | margin-top: 4px;
55 | }
56 |
57 | .card {
58 | background: white;
59 | height: 20vh;
60 | margin: 24px;
61 | padding: 2rem 9.188rem 1.625rem 1.688rem;
62 | border-radius: 4px;
63 | font-family: "Montserrat-Regular", sans-serif;
64 | border: solid 1px #e8e8e8;
65 | display: flex;
66 | }
67 |
68 | .main-area {
69 | list-style: none;
70 | width: 50%;
71 | margin: 12px;
72 | }
73 |
74 | .main-area span {
75 | font-size: 12px;
76 | }
77 |
78 | .main-area h1 {
79 | font-size: 36px;
80 | }
81 |
82 | .main-area p {
83 | font-size: 18px;
84 | color: #1f7199;
85 | }
86 |
87 | .main-area ul {
88 | list-style: none;
89 | display: flex;
90 | gap: 10px;
91 | }
92 |
93 | .main-area ul li:nth-child(3) {
94 | border-right: none;
95 | }
96 |
97 | .main-area2 {
98 | width: 25%;
99 | border-right: 1px solid #e8e8e8;
100 | }
101 |
102 | .main-area2 h4 {
103 | font-size: 36px;
104 | }
105 |
106 | .main-area3 {
107 | float: right;
108 | width: 25%;
109 | }
110 |
111 | .main-area3 button {
112 | background-color: #0290ff;
113 | color: white;
114 | padding: 2%;
115 | border: none;
116 | border-radius: 5px;
117 | margin-top: 3px;
118 | }
119 |
120 | .progressbar {
121 | width: 40%;
122 | }
123 |
124 | .forms {
125 | /* margin: 0.313rem 6.25rem 0; */
126 | padding: 1rem 9.188rem 1.625rem 1.688rem;
127 | display: inline-block;
128 | width: 100%;
129 | }
130 |
131 | form input,
132 | select {
133 | margin: 1.188rem 1.125rem 0 0;
134 | padding: 0.813rem 5rem 0.813rem 1.063rem;
135 | border-radius: 4px;
136 | border: solid 1px #e8e8e8;
137 | background-color: #fff;
138 | }
139 |
140 | form input:hover,
141 | select:hover {
142 | outline: 0.5px solid #0290ff;
143 | border: none;
144 | }
145 |
146 | .btn {
147 | width: 11.5rem;
148 | height: 2.813rem;
149 | margin: 1.188rem 0 0 2.125rem;
150 | padding: 0.801rem 1.188rem 0.886rem 1.375rem;
151 | border-radius: 3px;
152 | background-color: #0290ff;
153 | color: #fff;
154 | border: none;
155 | outline: none;
156 | }
157 |
158 | .tranparent-btn {
159 | color: #0290ff;
160 | background-color: transparent;
161 | background-repeat: no-repeat;
162 | border: none;
163 | cursor: pointer;
164 | }
165 |
166 | .chapter-section {
167 | margin-left: 24px;
168 | line-height: 2;
169 | display: flex;
170 | flex-direction: column;
171 | justify-content: center;
172 | align-items: center;
173 | }
174 |
175 | .chapter {
176 | letter-spacing: -0.4px;
177 | color: #121212;
178 | padding-right: 4.2rem;
179 | }
180 |
181 | .sub-chapter {
182 | color: #e8e8e8;
183 | font-size: 1.2rem;
184 | font-weight: 300;
185 | padding-left: 2.2rem;
186 | }
187 |
188 | .title {
189 | font-size: 1.375rem;
190 | letter-spacing: -0.2px;
191 | height: 1.813rem;
192 | margin: 0.188rem 20.188rem 0 0;
193 | }
194 |
195 | .category {
196 | color: #121212;
197 | font-size: 0.875rem;
198 | height: 1.813rem;
199 | margin: 0.188rem 20.188rem 0 0;
200 | }
201 |
202 | .author {
203 | font-size: 0.875rem;
204 | color: #4386bf;
205 | height: 1.813rem;
206 | margin: 0.188rem 20.188rem 0 0;
207 | }
208 |
209 | .border-right {
210 | border-right: 1px solid #e4e4e4;
211 | padding: 0 1.25rem;
212 | }
213 |
214 | .completed {
215 | padding-left: 15px;
216 | }
217 |
--------------------------------------------------------------------------------