first commit
This commit is contained in:
commit
51153163a9
24
.gitignore
vendored
Normal file
24
.gitignore
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
node_modules
|
||||
dist
|
||||
dist-ssr
|
||||
*.local
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.idea
|
||||
.DS_Store
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
38
eslint.config.js
Normal file
38
eslint.config.js
Normal file
|
@ -0,0 +1,38 @@
|
|||
import js from '@eslint/js'
|
||||
import globals from 'globals'
|
||||
import react from 'eslint-plugin-react'
|
||||
import reactHooks from 'eslint-plugin-react-hooks'
|
||||
import reactRefresh from 'eslint-plugin-react-refresh'
|
||||
|
||||
export default [
|
||||
{ ignores: ['dist'] },
|
||||
{
|
||||
files: ['**/*.{js,jsx}'],
|
||||
languageOptions: {
|
||||
ecmaVersion: 2020,
|
||||
globals: globals.browser,
|
||||
parserOptions: {
|
||||
ecmaVersion: 'latest',
|
||||
ecmaFeatures: { jsx: true },
|
||||
sourceType: 'module',
|
||||
},
|
||||
},
|
||||
settings: { react: { version: '18.3' } },
|
||||
plugins: {
|
||||
react,
|
||||
'react-hooks': reactHooks,
|
||||
'react-refresh': reactRefresh,
|
||||
},
|
||||
rules: {
|
||||
...js.configs.recommended.rules,
|
||||
...react.configs.recommended.rules,
|
||||
...react.configs['jsx-runtime'].rules,
|
||||
...reactHooks.configs.recommended.rules,
|
||||
'react/jsx-no-target-blank': 'off',
|
||||
'react-refresh/only-export-components': [
|
||||
'warn',
|
||||
{ allowConstantExport: true },
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
13
index.html
Normal file
13
index.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Vite + React</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/src/main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
4675
package-lock.json
generated
Normal file
4675
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
package.json
Normal file
35
package.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "lab1.1",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"lint": "eslint .",
|
||||
"preview": "vite preview"
|
||||
},
|
||||
"dependencies": {
|
||||
"@reduxjs/toolkit": "^2.3.0",
|
||||
"axios": "^1.7.7",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-router-dom": "^6.26.2",
|
||||
"react-social-icons": "^6.18.0",
|
||||
"react-toastify": "^10.0.5",
|
||||
"validator": "^13.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.9.0",
|
||||
"@types/react": "^18.3.3",
|
||||
"@types/react-dom": "^18.3.0",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"eslint": "^9.9.0",
|
||||
"eslint-plugin-react": "^7.35.0",
|
||||
"eslint-plugin-react-hooks": "^5.1.0-rc.0",
|
||||
"eslint-plugin-react-refresh": "^0.4.9",
|
||||
"globals": "^15.9.0",
|
||||
"vite": "^5.4.1"
|
||||
}
|
||||
}
|
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
After Width: | Height: | Size: 1.5 KiB |
19
src/App.jsx
Normal file
19
src/App.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import BookList from "./books/BookList";
|
||||
import NavBar from './components/NavBar';
|
||||
import { RouterProvider } from "react-router-dom";
|
||||
import { router } from "./router";
|
||||
|
||||
|
||||
|
||||
function App() {
|
||||
|
||||
return (
|
||||
<>
|
||||
<RouterProvider router={router} />
|
||||
{/*<NavBar />
|
||||
<BookList />*/}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
1
src/assets/notFound.svg
Normal file
1
src/assets/notFound.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 23 KiB |
1
src/assets/other.svg
Normal file
1
src/assets/other.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 24 KiB |
1
src/assets/react.svg
Normal file
1
src/assets/react.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="35.93" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 228"><path fill="#00D8FF" d="M210.483 73.824a171.49 171.49 0 0 0-8.24-2.597c.465-1.9.893-3.777 1.273-5.621c6.238-30.281 2.16-54.676-11.769-62.708c-13.355-7.7-35.196.329-57.254 19.526a171.23 171.23 0 0 0-6.375 5.848a155.866 155.866 0 0 0-4.241-3.917C100.759 3.829 77.587-4.822 63.673 3.233C50.33 10.957 46.379 33.89 51.995 62.588a170.974 170.974 0 0 0 1.892 8.48c-3.28.932-6.445 1.924-9.474 2.98C17.309 83.498 0 98.307 0 113.668c0 15.865 18.582 31.778 46.812 41.427a145.52 145.52 0 0 0 6.921 2.165a167.467 167.467 0 0 0-2.01 9.138c-5.354 28.2-1.173 50.591 12.134 58.266c13.744 7.926 36.812-.22 59.273-19.855a145.567 145.567 0 0 0 5.342-4.923a168.064 168.064 0 0 0 6.92 6.314c21.758 18.722 43.246 26.282 56.54 18.586c13.731-7.949 18.194-32.003 12.4-61.268a145.016 145.016 0 0 0-1.535-6.842c1.62-.48 3.21-.974 4.76-1.488c29.348-9.723 48.443-25.443 48.443-41.52c0-15.417-17.868-30.326-45.517-39.844Zm-6.365 70.984c-1.4.463-2.836.91-4.3 1.345c-3.24-10.257-7.612-21.163-12.963-32.432c5.106-11 9.31-21.767 12.459-31.957c2.619.758 5.16 1.557 7.61 2.4c23.69 8.156 38.14 20.213 38.14 29.504c0 9.896-15.606 22.743-40.946 31.14Zm-10.514 20.834c2.562 12.94 2.927 24.64 1.23 33.787c-1.524 8.219-4.59 13.698-8.382 15.893c-8.067 4.67-25.32-1.4-43.927-17.412a156.726 156.726 0 0 1-6.437-5.87c7.214-7.889 14.423-17.06 21.459-27.246c12.376-1.098 24.068-2.894 34.671-5.345a134.17 134.17 0 0 1 1.386 6.193ZM87.276 214.515c-7.882 2.783-14.16 2.863-17.955.675c-8.075-4.657-11.432-22.636-6.853-46.752a156.923 156.923 0 0 1 1.869-8.499c10.486 2.32 22.093 3.988 34.498 4.994c7.084 9.967 14.501 19.128 21.976 27.15a134.668 134.668 0 0 1-4.877 4.492c-9.933 8.682-19.886 14.842-28.658 17.94ZM50.35 144.747c-12.483-4.267-22.792-9.812-29.858-15.863c-6.35-5.437-9.555-10.836-9.555-15.216c0-9.322 13.897-21.212 37.076-29.293c2.813-.98 5.757-1.905 8.812-2.773c3.204 10.42 7.406 21.315 12.477 32.332c-5.137 11.18-9.399 22.249-12.634 32.792a134.718 134.718 0 0 1-6.318-1.979Zm12.378-84.26c-4.811-24.587-1.616-43.134 6.425-47.789c8.564-4.958 27.502 2.111 47.463 19.835a144.318 144.318 0 0 1 3.841 3.545c-7.438 7.987-14.787 17.08-21.808 26.988c-12.04 1.116-23.565 2.908-34.161 5.309a160.342 160.342 0 0 1-1.76-7.887Zm110.427 27.268a347.8 347.8 0 0 0-7.785-12.803c8.168 1.033 15.994 2.404 23.343 4.08c-2.206 7.072-4.956 14.465-8.193 22.045a381.151 381.151 0 0 0-7.365-13.322Zm-45.032-43.861c5.044 5.465 10.096 11.566 15.065 18.186a322.04 322.04 0 0 0-30.257-.006c4.974-6.559 10.069-12.652 15.192-18.18ZM82.802 87.83a323.167 323.167 0 0 0-7.227 13.238c-3.184-7.553-5.909-14.98-8.134-22.152c7.304-1.634 15.093-2.97 23.209-3.984a321.524 321.524 0 0 0-7.848 12.897Zm8.081 65.352c-8.385-.936-16.291-2.203-23.593-3.793c2.26-7.3 5.045-14.885 8.298-22.6a321.187 321.187 0 0 0 7.257 13.246c2.594 4.48 5.28 8.868 8.038 13.147Zm37.542 31.03c-5.184-5.592-10.354-11.779-15.403-18.433c4.902.192 9.899.29 14.978.29c5.218 0 10.376-.117 15.453-.343c-4.985 6.774-10.018 12.97-15.028 18.486Zm52.198-57.817c3.422 7.8 6.306 15.345 8.596 22.52c-7.422 1.694-15.436 3.058-23.88 4.071a382.417 382.417 0 0 0 7.859-13.026a347.403 347.403 0 0 0 7.425-13.565Zm-16.898 8.101a358.557 358.557 0 0 1-12.281 19.815a329.4 329.4 0 0 1-23.444.823c-7.967 0-15.716-.248-23.178-.732a310.202 310.202 0 0 1-12.513-19.846h.001a307.41 307.41 0 0 1-10.923-20.627a310.278 310.278 0 0 1 10.89-20.637l-.001.001a307.318 307.318 0 0 1 12.413-19.761c7.613-.576 15.42-.876 23.31-.876H128c7.926 0 15.743.303 23.354.883a329.357 329.357 0 0 1 12.335 19.695a358.489 358.489 0 0 1 11.036 20.54a329.472 329.472 0 0 1-11 20.722Zm22.56-122.124c8.572 4.944 11.906 24.881 6.52 51.026c-.344 1.668-.73 3.367-1.15 5.09c-10.622-2.452-22.155-4.275-34.23-5.408c-7.034-10.017-14.323-19.124-21.64-27.008a160.789 160.789 0 0 1 5.888-5.4c18.9-16.447 36.564-22.941 44.612-18.3ZM128 90.808c12.625 0 22.86 10.235 22.86 22.86s-10.235 22.86-22.86 22.86s-22.86-10.235-22.86-22.86s10.235-22.86 22.86-22.86Z"></path></svg>
|
After Width: | Height: | Size: 4.0 KiB |
9
src/books/Author.jsx
Normal file
9
src/books/Author.jsx
Normal file
|
@ -0,0 +1,9 @@
|
|||
import React from "react";
|
||||
|
||||
|
||||
const Author = ({name}) => {
|
||||
|
||||
return <h4>{name}</h4>;
|
||||
};
|
||||
|
||||
export default Author;
|
19
src/books/Book.jsx
Normal file
19
src/books/Book.jsx
Normal file
|
@ -0,0 +1,19 @@
|
|||
import React from "react";
|
||||
import Image from "./Image";
|
||||
import Title from "./Title";
|
||||
import Author from "./Author";
|
||||
|
||||
|
||||
const Book = (props) => {
|
||||
const { title, subtitle, authors, imageLinks } = props;
|
||||
|
||||
return (
|
||||
<article>
|
||||
<Image thumbnail={imageLinks.thumbnail} title={title} />
|
||||
<Title title={title} subtitle={subtitle} />
|
||||
<Author name={authors} />
|
||||
</article>
|
||||
);
|
||||
};
|
||||
|
||||
export default Book;
|
50
src/books/BookList.jsx
Normal file
50
src/books/BookList.jsx
Normal file
|
@ -0,0 +1,50 @@
|
|||
import React, { useState } from "react";
|
||||
import Book from "./Book";
|
||||
import { data } from "./data.js";
|
||||
import MenuTitle from '../components/MenuTitle.jsx';
|
||||
import MenuCategories from '../components/MenuCategories.jsx';
|
||||
|
||||
const { items } = data;
|
||||
const menuTitle = "Books Menu";
|
||||
const tempAuthors = items.map((item) => item.volumeInfo.authors);
|
||||
|
||||
const tempSet = new Set(tempAuthors.flat());
|
||||
const allAuthors = ["All", ...tempSet];
|
||||
|
||||
const BookList = () => {
|
||||
const [authors, setAuthors] = useState(allAuthors);
|
||||
const [selectedAuthor, setSelectedAuthor] = useState("All");
|
||||
|
||||
const filterAuthor = (author) => {
|
||||
setSelectedAuthor(author);
|
||||
};
|
||||
|
||||
return (
|
||||
<section>
|
||||
<MenuTitle title={menuTitle} />
|
||||
<MenuCategories categories={authors} filterAuthor={filterAuthor} />
|
||||
|
||||
<div className="book-list">
|
||||
{items.map((item) => {
|
||||
const { volumeInfo } = item;
|
||||
const { authors: bookAuthors, title, subtitle, imageLinks } = volumeInfo;
|
||||
|
||||
if (selectedAuthor === "All" || (bookAuthors && bookAuthors.includes(selectedAuthor))) {
|
||||
return (
|
||||
<Book
|
||||
title={title}
|
||||
subtitle={subtitle}
|
||||
authors={bookAuthors}
|
||||
imageLinks={imageLinks}
|
||||
key={item.id}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null; // If no match, return nothing
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default BookList;
|
12
src/books/Image.jsx
Normal file
12
src/books/Image.jsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from "react";
|
||||
|
||||
const Image = ({ thumbnail, title }) => {
|
||||
return (
|
||||
<img
|
||||
src={thumbnail}
|
||||
alt={title}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default Image;
|
7
src/books/Title.jsx
Normal file
7
src/books/Title.jsx
Normal file
|
@ -0,0 +1,7 @@
|
|||
import React from "react";
|
||||
|
||||
const Title = ({title}) => {
|
||||
return <h3>{title}</h3>;
|
||||
};
|
||||
|
||||
export default Title;
|
889
src/books/data.js
Normal file
889
src/books/data.js
Normal file
|
@ -0,0 +1,889 @@
|
|||
export const data = {
|
||||
kind: "books#volumes",
|
||||
totalItems: 3823,
|
||||
items: [
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "S85NCwAAQBAJ",
|
||||
etag: "PpRTmD2S0mk",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/S85NCwAAQBAJ",
|
||||
volumeInfo: {
|
||||
title: "It",
|
||||
subtitle: "A Novel",
|
||||
authors: ["Stephen King"],
|
||||
publisher: "Simon and Schuster",
|
||||
publishedDate: "2016-01-05",
|
||||
description:
|
||||
"In 1985, six men and one woman are called back together to search for a creature of unspeakable evil that had stalked them as children.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9781501142970",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "1501142976",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: false,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 1184,
|
||||
printType: "BOOK",
|
||||
categories: ["Fiction"],
|
||||
averageRating: 4,
|
||||
ratingsCount: 16,
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "0.7.2.0.preview.0",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=S85NCwAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=S85NCwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=S85NCwAAQBAJ&printsec=frontcover&dq=stephen+king&hl=&cd=1&source=gbs_api",
|
||||
infoLink:
|
||||
"http://books.google.co.uk/books?id=S85NCwAAQBAJ&dq=stephen+king&hl=&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://books.google.com/books/about/It.html?hl=&id=S85NCwAAQBAJ",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "NOT_FOR_SALE",
|
||||
isEbook: false,
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED_FOR_ACCESSIBILITY",
|
||||
epub: {
|
||||
isAvailable: false,
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=S85NCwAAQBAJ&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"In 1985, six men and one woman are called back together to search for a creature of unspeakable evil that had stalked them as children.",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "2BcECkYB7uoC",
|
||||
etag: "KJgVwElWerc",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/2BcECkYB7uoC",
|
||||
volumeInfo: {
|
||||
title: "Stephen King from A to Z",
|
||||
subtitle: "An Encyclopedia of His Life and Work",
|
||||
authors: ["George Beahm", "Beahm"],
|
||||
publisher: "Andrews McMeel Publishing",
|
||||
publishedDate: "1998-09",
|
||||
description:
|
||||
"Contains hundreds of alphabetically arranged entries that provide information about various aspects of the life and work of popular novelist Stephen King.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "0836269144",
|
||||
},
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9780836269147",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: false,
|
||||
image: true,
|
||||
},
|
||||
pageCount: 278,
|
||||
printType: "BOOK",
|
||||
categories: ["Fiction"],
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "0.3.6.0.preview.1",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=2BcECkYB7uoC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=2BcECkYB7uoC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=2BcECkYB7uoC&printsec=frontcover&dq=stephen+king&hl=&cd=2&source=gbs_api",
|
||||
infoLink:
|
||||
"http://books.google.co.uk/books?id=2BcECkYB7uoC&dq=stephen+king&hl=&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://books.google.com/books/about/Stephen_King_from_A_to_Z.html?hl=&id=2BcECkYB7uoC",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "NOT_FOR_SALE",
|
||||
isEbook: false,
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: false,
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: true,
|
||||
acsTokenLink:
|
||||
"http://books.google.co.uk/books/download/Stephen_King_from_A_to_Z-sample-pdf.acsm?id=2BcECkYB7uoC&format=pdf&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api",
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=2BcECkYB7uoC&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"Contains hundreds of alphabetically arranged entries that provide information about various aspects of the life and work of popular novelist Stephen King.",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "Qbm5ejIoY5sC",
|
||||
etag: "3ITsljJRT68",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/Qbm5ejIoY5sC",
|
||||
volumeInfo: {
|
||||
title: "Stephen King Goes to the Movies",
|
||||
authors: ["Stephen King"],
|
||||
publisher: "Simon and Schuster",
|
||||
publishedDate: "2009-01-20",
|
||||
description:
|
||||
'A collection of five short stories that have been made into movies includes "The Mangler," in which a skeptical writer investigates a supposedly haunted hotel room that has apparently caused at least forty-two deaths.',
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9781416592365",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "1416592369",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: false,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 645,
|
||||
printType: "BOOK",
|
||||
categories: ["Fiction"],
|
||||
averageRating: 4,
|
||||
ratingsCount: 4,
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "0.1.1.0.preview.0",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=Qbm5ejIoY5sC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=Qbm5ejIoY5sC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=Qbm5ejIoY5sC&printsec=frontcover&dq=stephen+king&hl=&cd=3&source=gbs_api",
|
||||
infoLink:
|
||||
"http://books.google.co.uk/books?id=Qbm5ejIoY5sC&dq=stephen+king&hl=&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://books.google.com/books/about/Stephen_King_Goes_to_the_Movies.html?hl=&id=Qbm5ejIoY5sC",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "NOT_FOR_SALE",
|
||||
isEbook: false,
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED_FOR_ACCESSIBILITY",
|
||||
epub: {
|
||||
isAvailable: false,
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=Qbm5ejIoY5sC&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"Stephen King revisits five of his favorite short stories that have been turned into films. This collection features new commentary and introductions to all of these stories in a treasure-trove of movie trivia.",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "LC32OW8iVUQC",
|
||||
etag: "KJyl2WetsFg",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/LC32OW8iVUQC",
|
||||
volumeInfo: {
|
||||
title: "The Stand",
|
||||
authors: ["Stephen King"],
|
||||
publisher: "Hachette UK",
|
||||
publishedDate: "2008-12-11",
|
||||
description:
|
||||
"Stephen King's apocalyptic vision of a world blasted by virus and tangled in an elemental struggle between good and evil remains as riveting and eerily plausible as when it was first published. Soon to be a television series. 'THE STAND is a masterpiece' (Guardian). Set in a virus-decimated US, King's thrilling American fantasy epic, is a Classic. First come the days of the virus. Then come the dreams. Dark dreams that warn of the coming of the dark man. The apostate of death, his worn-down boot heels tramping the night roads. The warlord of the charnel house and Prince of Evil. His time is at hand. His empire grows in the west and the Apocalypse looms. When a man crashes his car into a petrol station, he brings with him the foul corpses of his wife and daughter. He dies and it doesn't take long for the virus which killed him to spread across America and the world.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9781848940833",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "1848940831",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: true,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 1553,
|
||||
printType: "BOOK",
|
||||
categories: ["Fiction"],
|
||||
averageRating: 5,
|
||||
ratingsCount: 4,
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: true,
|
||||
contentVersion: "0.24.20.0.preview.2",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=LC32OW8iVUQC&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=LC32OW8iVUQC&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=LC32OW8iVUQC&printsec=frontcover&dq=stephen+king&hl=&cd=4&source=gbs_api",
|
||||
infoLink:
|
||||
"https://play.google.com/store/books/details?id=LC32OW8iVUQC&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://play.google.com/store/books/details?id=LC32OW8iVUQC",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "FOR_SALE",
|
||||
isEbook: true,
|
||||
listPrice: {
|
||||
amount: 5.99,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amount: 5.99,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
buyLink:
|
||||
"https://play.google.com/store/books/details?id=LC32OW8iVUQC&rdid=book-LC32OW8iVUQC&rdot=1&source=gbs_api",
|
||||
offers: [
|
||||
{
|
||||
finskyOfferType: 1,
|
||||
listPrice: {
|
||||
amountInMicros: 5990000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amountInMicros: 5990000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
giftable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: true,
|
||||
acsTokenLink:
|
||||
"http://books.google.co.uk/books/download/The_Stand-sample-epub.acsm?id=LC32OW8iVUQC&format=epub&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api",
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=LC32OW8iVUQC&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"Soon to be a television series. 'THE STAND is a masterpiece' (Guardian). Set in a virus-decimated US, King's thrilling American fantasy epic, is a Classic. First come the days of the virus. Then come the dreams.",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "3wZaEAAAQBAJ",
|
||||
etag: "KddjrdYx04M",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/3wZaEAAAQBAJ",
|
||||
volumeInfo: {
|
||||
title: "Fairy Tale",
|
||||
authors: ["Stephen King"],
|
||||
publisher: "Hachette UK",
|
||||
publishedDate: "2022-09-06",
|
||||
description:
|
||||
"WELCOME TO THE DARK SIDE OF HAPPILY EVER AFTER Charlie Reade looks like a regular high school kid, great at baseball and football, a decent student. But when Charlie is seventeen, he meets a dog named Radar and her aging master, Howard Bowditch, a recluse in a big house at the top of a big hill, with a locked shed in the backyard. When Bowditch dies, he leaves Charlie a cassette tape telling a story no one would believe - inside the shed is a portal to another world. Legendary storyteller Stephen King goes into the deepest well of his imagination in this spellbinding novel about a seventeen-year-old boy who inherits the keys to a parallel world where good and evil are at war, and the stakes could not be higher - for their world or ours.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9781399705431",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "1399705431",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: true,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 706,
|
||||
printType: "BOOK",
|
||||
categories: ["Fiction"],
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: true,
|
||||
contentVersion: "2.6.6.0.preview.2",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=3wZaEAAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=3wZaEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=3wZaEAAAQBAJ&printsec=frontcover&dq=stephen+king&hl=&cd=5&source=gbs_api",
|
||||
infoLink:
|
||||
"https://play.google.com/store/books/details?id=3wZaEAAAQBAJ&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://play.google.com/store/books/details?id=3wZaEAAAQBAJ",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "FOR_SALE",
|
||||
isEbook: true,
|
||||
listPrice: {
|
||||
amount: 5.49,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amount: 5.49,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
buyLink:
|
||||
"https://play.google.com/store/books/details?id=3wZaEAAAQBAJ&rdid=book-3wZaEAAAQBAJ&rdot=1&source=gbs_api",
|
||||
offers: [
|
||||
{
|
||||
finskyOfferType: 1,
|
||||
listPrice: {
|
||||
amountInMicros: 5490000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amountInMicros: 5490000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
giftable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: true,
|
||||
acsTokenLink:
|
||||
"http://books.google.co.uk/books/download/Fairy_Tale-sample-epub.acsm?id=3wZaEAAAQBAJ&format=epub&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api",
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=3wZaEAAAQBAJ&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"Legendary storyteller Stephen King goes into the deepest well of his imagination in this spellbinding novel about a seventeen-year-old boy who inherits the keys to a parallel world where good and evil are at war, and the stakes could not be ...",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "wa6WDwAAQBAJ",
|
||||
etag: "81BtrOOIVOU",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/wa6WDwAAQBAJ",
|
||||
volumeInfo: {
|
||||
title: "Flight or Fright",
|
||||
subtitle: "17 Turbulent Tales",
|
||||
authors: ["Stephen King", "Bev Vincent"],
|
||||
publisher: "Scribner",
|
||||
publishedDate: "2019-06-04",
|
||||
description:
|
||||
"#1 New York Times bestselling author and master of horror Stephen King teams up with Bev Vincent of Cemetery Dance to present a terrifying collection of sixteen short stories (and one poem) that tap into one of King’s greatest fears—air travel—featuring brand-new stories by King and Joe Hill, “an expertly compiled collection of tales that entertain and scare†(Booklist). Stephen King hates to fly, and he and co-editor Bev Vincent would like to share their fear of flying with you. Welcome to Flight or Fright, an anthology about all the things that can go horribly wrong when you’re suspended six miles in the air, hurtling through space at more than 500 mph, and sealed up in a metal tube (like—gulp!—a coffin) with hundreds of strangers. Here are all the ways your trip into the friendly skies can turn into a nightmare, including some we’ll bet you’ve never thought of before... but now you will the next time you walk down the jetway and place your fate in the hands of a total stranger. Featuring brand-new “standouts†(Publishers Weekly) by Joe Hill and Stephen King, as well as fourteen classic tales and one poem from the likes of Richard Matheson, Ray Bradbury, Roald Dahl, Dan Simmons, Sir Arthur Conan Doyle, and many others, Flight or Fright is, as King says, “ideal airplane reading, especially on stormy descents…Even if you are safe on the ground, you might want to buckle up nice and tight.†Each story is introduced by Stephen King and all will have you thinking twice about how you want to reach your final destination.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9781982109004",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "1982109009",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: false,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 352,
|
||||
printType: "BOOK",
|
||||
categories: ["Fiction"],
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "0.0.1.0.preview.0",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=wa6WDwAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=wa6WDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=wa6WDwAAQBAJ&printsec=frontcover&dq=stephen+king&hl=&cd=6&source=gbs_api",
|
||||
infoLink:
|
||||
"http://books.google.co.uk/books?id=wa6WDwAAQBAJ&dq=stephen+king&hl=&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://books.google.com/books/about/Flight_or_Fright.html?hl=&id=wa6WDwAAQBAJ",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "NOT_FOR_SALE",
|
||||
isEbook: false,
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED_FOR_ACCESSIBILITY",
|
||||
epub: {
|
||||
isAvailable: false,
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=wa6WDwAAQBAJ&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"Here are all the ways your trip into the friendly skies can turn into a nightmare, including some we’ll bet you’ve never thought of before... but now you will the next time you walk down the jetway and place your fate in the hands of a ...",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "PPNaAAAAMAAJ",
|
||||
etag: "CUGOc79Zv6M",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/PPNaAAAAMAAJ",
|
||||
volumeInfo: {
|
||||
title: "Stephen King",
|
||||
authors: ["Douglas E. Winter"],
|
||||
publishedDate: "1982",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "OTHER",
|
||||
identifier: "UOM:39015020740000",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: false,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 136,
|
||||
printType: "BOOK",
|
||||
categories: ["Horror tales, American"],
|
||||
averageRating: 3,
|
||||
ratingsCount: 1,
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "0.6.2.0.preview.0",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=PPNaAAAAMAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=PPNaAAAAMAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=PPNaAAAAMAAJ&q=stephen+king&dq=stephen+king&hl=&cd=7&source=gbs_api",
|
||||
infoLink:
|
||||
"http://books.google.co.uk/books?id=PPNaAAAAMAAJ&dq=stephen+king&hl=&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://books.google.com/books/about/Stephen_King.html?hl=&id=PPNaAAAAMAAJ",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "NOT_FOR_SALE",
|
||||
isEbook: false,
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "NO_PAGES",
|
||||
embeddable: false,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: false,
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=PPNaAAAAMAAJ&hl=&source=gbs_api",
|
||||
accessViewStatus: "NONE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "XSWeBAAAQBAJ",
|
||||
etag: "GOfX6bTcLcU",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/XSWeBAAAQBAJ",
|
||||
volumeInfo: {
|
||||
title: "A Brief Guide to Stephen King",
|
||||
authors: ["Paul Simpson"],
|
||||
publisher: "Hachette UK",
|
||||
publishedDate: "2014-03-20",
|
||||
description:
|
||||
"2014 marks the 40th anniversary of the publication of Stephen King’s first novel Carrie in April 1974. Rescued from the rubbish by his wife Tabitha, the novel launched the Maine schoolteacher on a prolific and extraordinarily successful career. His name has become synonymous with horror and suspense through over fifty works, including The Dark Tower, a retelling of Byron’s Childe Harold to the Dark Tower Came. Simpson traces the writer’s life from his difficult childhood – his father went out to the shops and never came back – through his initial books under the pseudonym Richard Bachman to the success of Carrie, Salem’s Lot and The Shining in the 1970s, and beyond. He examines how King’s writing was affected by the accident that nearly killed him in 1999 and how his battles with alcohol and addiction to medication have been reflected in his stories. The guide will also take a look at the very many adaptation’s of King’s work in movies, on television and radio, and in comic books.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9781472110749",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "1472110749",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: true,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 304,
|
||||
printType: "BOOK",
|
||||
categories: ["Literary Criticism"],
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "1.2.3.0.preview.2",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=XSWeBAAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=XSWeBAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=XSWeBAAAQBAJ&printsec=frontcover&dq=stephen+king&hl=&cd=8&source=gbs_api",
|
||||
infoLink:
|
||||
"https://play.google.com/store/books/details?id=XSWeBAAAQBAJ&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://play.google.com/store/books/details?id=XSWeBAAAQBAJ",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "FOR_SALE",
|
||||
isEbook: true,
|
||||
listPrice: {
|
||||
amount: 2.49,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amount: 2.49,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
buyLink:
|
||||
"https://play.google.com/store/books/details?id=XSWeBAAAQBAJ&rdid=book-XSWeBAAAQBAJ&rdot=1&source=gbs_api",
|
||||
offers: [
|
||||
{
|
||||
finskyOfferType: 1,
|
||||
listPrice: {
|
||||
amountInMicros: 2490000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amountInMicros: 2490000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
giftable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: true,
|
||||
acsTokenLink:
|
||||
"http://books.google.co.uk/books/download/A_Brief_Guide_to_Stephen_King-sample-epub.acsm?id=XSWeBAAAQBAJ&format=epub&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api",
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=XSWeBAAAQBAJ&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"The guide will also take a look at the very many adaptation’s of King’s work in movies, on television and radio, and in comic books. All you wanted to know about Stephen King . . . but were too afraid to ask!",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "L2sFzeynyIUC",
|
||||
etag: "eaF3OLdvcaI",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/L2sFzeynyIUC",
|
||||
volumeInfo: {
|
||||
title: "Stephen King",
|
||||
subtitle: "King of Thrillers and Horror",
|
||||
authors: ["Suzan Wilson"],
|
||||
publisher: "Enslow Publishing",
|
||||
publishedDate: "2000",
|
||||
description:
|
||||
"Traces the life of a popular novelist, from his childhood as an avid reader to his current success as a creator of horror fiction.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "0766012336",
|
||||
},
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9780766012332",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: false,
|
||||
image: false,
|
||||
},
|
||||
pageCount: 132,
|
||||
printType: "BOOK",
|
||||
categories: ["Horror tales"],
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "0.3.3.0.preview.0",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=L2sFzeynyIUC&printsec=frontcover&img=1&zoom=5&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=L2sFzeynyIUC&printsec=frontcover&img=1&zoom=1&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=L2sFzeynyIUC&q=stephen+king&dq=stephen+king&hl=&cd=9&source=gbs_api",
|
||||
infoLink:
|
||||
"http://books.google.co.uk/books?id=L2sFzeynyIUC&dq=stephen+king&hl=&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://books.google.com/books/about/Stephen_King.html?hl=&id=L2sFzeynyIUC",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "NOT_FOR_SALE",
|
||||
isEbook: false,
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "NO_PAGES",
|
||||
embeddable: false,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: false,
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: false,
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=L2sFzeynyIUC&hl=&source=gbs_api",
|
||||
accessViewStatus: "NONE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"Traces the life of a popular novelist, from his childhood as an avid reader to his current success as a creator of horror fiction.",
|
||||
},
|
||||
},
|
||||
{
|
||||
kind: "books#volume",
|
||||
id: "giKIEAAAQBAJ",
|
||||
etag: "ENOizBHM8xM",
|
||||
selfLink: "https://www.googleapis.com/books/v1/volumes/giKIEAAAQBAJ",
|
||||
volumeInfo: {
|
||||
title: "Stephen King",
|
||||
subtitle: "A Complete Exploration of His Work, Life, and Influences",
|
||||
authors: ["Bev Vincent"],
|
||||
publisher: "becker&mayer! books ISBN",
|
||||
publishedDate: "2022-09-13",
|
||||
description:
|
||||
"Take an intimate tour through the life and works of Stephen King, made vivid with rare photos and ephemera from King’s personal collection. Even if you are a die-hard fan, you will find something new in this beautifully packaged Stephen King reference that you will return to again and again. Timed to celebrate Stephen King’s 75th birthday on September 21, 2022, Stephen King: A Complete Exploration of His Work, Life, and Influences reveals the inspiration behind the prolific author’s brilliant works of horror through a combination of photos and documents from King’s archives and an engaging account of the stories behind how his novels, novellas, short stories, and adaptations came to be. It might sound like a tall tale that Stephen King once met a bartender named Grady in an empty hotel in Colorado, or that the celebrated author helped his young daughter bury her cat in a nearby “pets sematary†after it was killed on a busy roadway. In this book, discover how King drew on these and more real personal experiences and mundane life events, then employed his extraordinary imagination to twist them into something horrific. From impoverished university student to struggling schoolteacher to one of the best-selling—and most recognizable—authors of all time, this engrossing book reveals the evolution and influences of Stephen King’s body of work over his nearly 50-year career, and how the themes of his writing reflect the changing times and events within his life. An expansion of Stephen King expert Bev Vincent’s The Stephen King Illustrated Companion, this fully revised, redesigned, and updated book includes: A review of King’s complete body of work, including Fairy Tale, published in September 2022. A wealth of rare memorabilia from King’s own collection, including personal and professional correspondences, handwritten manuscript pages, book covers, movie stills, and never-before-seen excerpts from one of his poems and an unpublished short story. Interludes on specific topics such as real-life settings that inspired King’s writing, the editor who discovered him, his life as a Boston Red Sox fan, and the many awards and honors he has received. Insightful quotes from King from interviews over the decades. Celebrate the beloved King of Horror with this informational and entertaining look inside King’s most iconic titles and the culture they have created.",
|
||||
industryIdentifiers: [
|
||||
{
|
||||
type: "ISBN_13",
|
||||
identifier: "9780760376829",
|
||||
},
|
||||
{
|
||||
type: "ISBN_10",
|
||||
identifier: "0760376824",
|
||||
},
|
||||
],
|
||||
readingModes: {
|
||||
text: true,
|
||||
image: true,
|
||||
},
|
||||
pageCount: 243,
|
||||
printType: "BOOK",
|
||||
categories: ["Biography & Autobiography"],
|
||||
averageRating: 5,
|
||||
ratingsCount: 1,
|
||||
maturityRating: "NOT_MATURE",
|
||||
allowAnonLogging: false,
|
||||
contentVersion: "1.3.2.0.preview.3",
|
||||
panelizationSummary: {
|
||||
containsEpubBubbles: false,
|
||||
containsImageBubbles: false,
|
||||
},
|
||||
imageLinks: {
|
||||
smallThumbnail:
|
||||
"http://books.google.com/books/content?id=giKIEAAAQBAJ&printsec=frontcover&img=1&zoom=5&edge=curl&source=gbs_api",
|
||||
thumbnail:
|
||||
"http://books.google.com/books/content?id=giKIEAAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api",
|
||||
},
|
||||
language: "en",
|
||||
previewLink:
|
||||
"http://books.google.co.uk/books?id=giKIEAAAQBAJ&printsec=frontcover&dq=stephen+king&hl=&cd=10&source=gbs_api",
|
||||
infoLink:
|
||||
"https://play.google.com/store/books/details?id=giKIEAAAQBAJ&source=gbs_api",
|
||||
canonicalVolumeLink:
|
||||
"https://play.google.com/store/books/details?id=giKIEAAAQBAJ",
|
||||
},
|
||||
saleInfo: {
|
||||
country: "GB",
|
||||
saleability: "FOR_SALE",
|
||||
isEbook: true,
|
||||
listPrice: {
|
||||
amount: 16.49,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amount: 16.49,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
buyLink:
|
||||
"https://play.google.com/store/books/details?id=giKIEAAAQBAJ&rdid=book-giKIEAAAQBAJ&rdot=1&source=gbs_api",
|
||||
offers: [
|
||||
{
|
||||
finskyOfferType: 1,
|
||||
listPrice: {
|
||||
amountInMicros: 16490000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
retailPrice: {
|
||||
amountInMicros: 16490000,
|
||||
currencyCode: "GBP",
|
||||
},
|
||||
giftable: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
accessInfo: {
|
||||
country: "GB",
|
||||
viewability: "PARTIAL",
|
||||
embeddable: true,
|
||||
publicDomain: false,
|
||||
textToSpeechPermission: "ALLOWED",
|
||||
epub: {
|
||||
isAvailable: true,
|
||||
acsTokenLink:
|
||||
"http://books.google.co.uk/books/download/Stephen_King-sample-epub.acsm?id=giKIEAAAQBAJ&format=epub&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api",
|
||||
},
|
||||
pdf: {
|
||||
isAvailable: true,
|
||||
acsTokenLink:
|
||||
"http://books.google.co.uk/books/download/Stephen_King-sample-pdf.acsm?id=giKIEAAAQBAJ&format=pdf&output=acs4_fulfillment_token&dl_type=sample&source=gbs_api",
|
||||
},
|
||||
webReaderLink:
|
||||
"http://play.google.com/books/reader?id=giKIEAAAQBAJ&hl=&source=gbs_api",
|
||||
accessViewStatus: "SAMPLE",
|
||||
quoteSharingAllowed: false,
|
||||
},
|
||||
searchInfo: {
|
||||
textSnippet:
|
||||
"In this book, discover how King drew on these and more real personal experiences and mundane life events, then employed his extraordinary imagination to twist them into something horrific.",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
99
src/components/Form.jsx
Normal file
99
src/components/Form.jsx
Normal file
|
@ -0,0 +1,99 @@
|
|||
import React, { useState } from "react";
|
||||
import validator from "validator";
|
||||
import { toast } from "react-toastify";
|
||||
|
||||
const Form = () => {
|
||||
const [firstName, setFirstName] = useState("");
|
||||
const [lastName, setLastName] = useState("");
|
||||
const [email, setEmail] = useState("");
|
||||
const [emailValid, setEmailValid] = useState(true);
|
||||
|
||||
const changeFirstName = (e) => {
|
||||
console.log(` before ..${firstName}`);
|
||||
setFirstName(e.target.value);
|
||||
console.log(` after ..${firstName}`);
|
||||
}
|
||||
|
||||
const changeLastName = (e) => {
|
||||
console.log(` before ..${lastName}`);
|
||||
setLastName(e.target.value);
|
||||
console.log(` after ..${lastName}`);
|
||||
}
|
||||
|
||||
const changeEmail = (e) => {
|
||||
setEmail(e.target.value);
|
||||
setEmailValid(validator.isEmail(e.target.value));
|
||||
console.log(validator.isEmail(e.target.value));
|
||||
}
|
||||
|
||||
|
||||
const handleSubmit = (e) => {
|
||||
e.preventDefault();
|
||||
console.log(e.currentTarget);
|
||||
const data = new FormData(e.currentTarget);
|
||||
const entries = Object.fromEntries(data);
|
||||
console.log(entries);
|
||||
setFirstName("");
|
||||
setLastName("");
|
||||
setEmail("");
|
||||
setEmailValid(true);
|
||||
toast.success("Form has been submitted successfully!");
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="formContainer">
|
||||
<h2>Subscribe for Newsletter</h2>
|
||||
<form onSubmit={handleSubmit} className="newsletterForm">
|
||||
<div className="formGroup">
|
||||
<label htmlFor="firstName">First Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="firstName"
|
||||
name="firstName"
|
||||
value={firstName}
|
||||
onChange={changeFirstName}
|
||||
required
|
||||
/>
|
||||
{firstName && (
|
||||
<small className="charCount">Number of Characters = {firstName.length}</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="formGroup">
|
||||
<label htmlFor="lastName">Last Name</label>
|
||||
<input
|
||||
type="text"
|
||||
id="lastName"
|
||||
name="lastName"
|
||||
value={lastName}
|
||||
onChange={changeLastName}
|
||||
required
|
||||
/>
|
||||
{lastName && (
|
||||
<small className="charCount">Number of Characters = {lastName.length}</small>
|
||||
)}
|
||||
</div>
|
||||
<div className="formGroup">
|
||||
<label htmlFor="email">Email</label>
|
||||
<input
|
||||
type="email"
|
||||
id="email"
|
||||
name="email"
|
||||
value={email}
|
||||
onChange={changeEmail}
|
||||
required
|
||||
/>
|
||||
{email ? (
|
||||
emailValid ? (
|
||||
<small className="charCount" style={{ color: 'red' }}>Email is Valid.</small>
|
||||
) : (
|
||||
<small className="charCount" style={{ color: 'red' }}>Email is Not Valid..</small>
|
||||
)
|
||||
) : null}
|
||||
</div>
|
||||
<button type="submit" className="subscribeButton">Subscribe</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Form;
|
22
src/components/MenuCategories.jsx
Normal file
22
src/components/MenuCategories.jsx
Normal file
|
@ -0,0 +1,22 @@
|
|||
import React from 'react';
|
||||
|
||||
const MenuCategories = ({ categories, filterAuthor }) => {
|
||||
return (
|
||||
<div>
|
||||
{categories.map((category) => {
|
||||
return (
|
||||
<button
|
||||
key={category}
|
||||
onClick={() => {
|
||||
filterAuthor(category);
|
||||
}}
|
||||
>
|
||||
{category}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MenuCategories;
|
11
src/components/MenuTitle.jsx
Normal file
11
src/components/MenuTitle.jsx
Normal file
|
@ -0,0 +1,11 @@
|
|||
import React from 'react';
|
||||
|
||||
const MenuTitle = ({ title }) => {
|
||||
return (
|
||||
<div>
|
||||
<h2>{title}</h2>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MenuTitle;
|
114
src/components/NavBar.css
Normal file
114
src/components/NavBar.css
Normal file
|
@ -0,0 +1,114 @@
|
|||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.navbar {
|
||||
background-color: #333;
|
||||
padding: 10px 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
|
||||
.navbar-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.hamburger {
|
||||
display: none;
|
||||
cursor: pointer;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.hamburger .line {
|
||||
width: 25px;
|
||||
height: 3px;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
|
||||
.nav-links {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
list-style: none;
|
||||
transition: max-height 0.5s ease;
|
||||
}
|
||||
|
||||
.nav-links li {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nav-links a {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
font-size: 18px;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
|
||||
.nav-links a:hover {
|
||||
color: #00bcd4;
|
||||
}
|
||||
|
||||
|
||||
.social-icons {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
.nav-links {
|
||||
position: absolute;
|
||||
top: 60px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
background-color: #333;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.nav-links.open {
|
||||
max-height: 200px;
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.social-icons {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.nav-links {
|
||||
justify-content: center;
|
||||
max-height: none;
|
||||
}
|
||||
|
||||
.hamburger {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.social-icons {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
37
src/components/NavBar.jsx
Normal file
37
src/components/NavBar.jsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import React, { useState } from 'react';
|
||||
import './NavBar.css';
|
||||
import { SocialIcons } from './SocialIcons';
|
||||
|
||||
const NavBar = () => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
|
||||
const toggleMenu = () => {
|
||||
setIsOpen(!isOpen);
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
<nav className="navbar">
|
||||
<div className="navbar-container">
|
||||
|
||||
<div className="hamburger" onClick={toggleMenu}>
|
||||
<span className="line"></span>
|
||||
<span className="line"></span>
|
||||
<span className="line"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<ul className={`nav-links ${isOpen ? 'open' : ''}`}>
|
||||
<li><a href="#home">Home</a></li>
|
||||
<li><a href="#books">Books</a></li>
|
||||
<li><a href="#newsletter">Newsletter</a></li>
|
||||
</ul>
|
||||
|
||||
<SocialIcons />
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default NavBar;
|
12
src/components/SocialIcons.jsx
Normal file
12
src/components/SocialIcons.jsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
import { SocialIcon } from 'react-social-icons';
|
||||
|
||||
export const SocialIcons = () => {
|
||||
return (
|
||||
<div className="social-icons">
|
||||
<SocialIcon url="https://twitter.com" />
|
||||
<SocialIcon url="https://facebook.com" />
|
||||
<SocialIcon url="https://instagram.com" />
|
||||
</div>
|
||||
);
|
||||
};
|
76
src/features/users/userSlice.js
Normal file
76
src/features/users/userSlice.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
|
||||
import axios from "axios";
|
||||
|
||||
const URL="https://randomuser.me/api/?results=12";
|
||||
|
||||
const initialState = {
|
||||
randomUsers : [],
|
||||
isLoading : true,
|
||||
}
|
||||
|
||||
export const fetchUsers = createAsyncThunk(
|
||||
"users/fetchUsers",
|
||||
async (name, thunkAPI) => {
|
||||
try {
|
||||
const response = await axios.get(URL);
|
||||
return response.data.results;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return thunkAPI.rejectWithValue(error.response);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
export const resetUsers = createAsyncThunk(
|
||||
"users/resetUsers",
|
||||
async (_, thunkAPI) => {
|
||||
try {
|
||||
const response = await axios.get(URL);
|
||||
return response.data.results;
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
return thunkAPI.rejectWithValue(error.response);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
const userSlice = createSlice({
|
||||
name: "users",
|
||||
initialState,
|
||||
reducers: {
|
||||
clearList: (state) => {
|
||||
state.randomUsers = [];
|
||||
},
|
||||
removeUser: (state, action) => {
|
||||
const uuid = action.payload;
|
||||
state.randomUsers = state.randomUsers.filter(
|
||||
(user) => user.login.uuid !== uuid
|
||||
);
|
||||
},
|
||||
},
|
||||
extraReducers: (builder) => {
|
||||
builder.addCase(fetchUsers.pending, (state) => {
|
||||
state.isLoading = true;
|
||||
});
|
||||
builder.addCase(fetchUsers.fulfilled, (state, action) => {
|
||||
console.log(state);
|
||||
console.log(action.payload);
|
||||
state.isLoading = false;
|
||||
state.randomUsers = action.payload;
|
||||
console.log(state.randomUsers.length);
|
||||
});
|
||||
builder.addCase(fetchUsers.rejected, (state) => {
|
||||
state.isLoading = false;
|
||||
});
|
||||
builder.addCase(resetUsers.fulfilled, (state, action) => {
|
||||
state.randomUsers = action.payload;
|
||||
});
|
||||
|
||||
},
|
||||
});
|
||||
|
||||
//console.log(userSlice);
|
||||
|
||||
export const { clearList, removeUser } = userSlice.actions;
|
||||
export default userSlice.reducer;
|
251
src/index.css
Normal file
251
src/index.css
Normal file
|
@ -0,0 +1,251 @@
|
|||
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
|
||||
section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
.book-list {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
|
||||
article {
|
||||
background-color: #e0f7fa;
|
||||
border-radius: 8px;
|
||||
padding: 15px;
|
||||
width: 200px;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
width: 150px;
|
||||
height: auto;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
|
||||
h3 {
|
||||
font-size: 1.1em;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1em;
|
||||
color: #666;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
|
||||
.errorContainer {
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
font-family: Arial, sans-serif;
|
||||
background-color: #f8f8f8;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.errorMessage {
|
||||
font-size: 24px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.errorImage {
|
||||
width: 150px;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.backHome {
|
||||
margin-top: 20px;
|
||||
text-decoration: none;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.formContainer {
|
||||
max-width: 400px;
|
||||
margin: 50px auto;
|
||||
padding: 20px;
|
||||
background-color: #fff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
h2 {
|
||||
text-align: center;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.newsletterForm {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.formGroup {
|
||||
position: relative;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
label {
|
||||
margin-bottom: 5px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
border-color: #007bff;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.charCount {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 10px;
|
||||
font-size: 12px;
|
||||
color: red;
|
||||
}
|
||||
|
||||
.subscribeButton {
|
||||
padding: 10px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.subscribeButton:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
|
||||
.user-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.user-item {
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
background-color: #f9f9f9;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.user-item:hover {
|
||||
transform: translateY(-5px);
|
||||
}
|
||||
|
||||
.user-details p {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.user-details strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
.user-photo {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.user-image {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
object-fit: cover;
|
||||
margin-bottom: 10px;
|
||||
border: 3px solid #ddd;
|
||||
}
|
||||
|
||||
.user-photo p {
|
||||
font-weight: bold;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin: 20px 0 40px 0;
|
||||
}
|
||||
|
||||
.centered-button {
|
||||
padding: 10px 20px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.remove-button {
|
||||
background-color: #ff4d4d;
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 8px 12px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.remove-button:hover {
|
||||
background-color: #ff1a1a;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 768px) {
|
||||
article {
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 480px) {
|
||||
article {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
18
src/main.jsx
Normal file
18
src/main.jsx
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App.jsx';
|
||||
import './index.css';
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import "react-toastify/dist/ReactToastify.css";
|
||||
import { store } from "./store.js";
|
||||
import { Provider } from "react-redux";
|
||||
|
||||
createRoot(document.getElementById('root')).render(
|
||||
<>
|
||||
<Provider store={store}>
|
||||
<ToastContainer position="top-center" />
|
||||
<App />
|
||||
</Provider>
|
||||
|
||||
</>,
|
||||
)
|
13
src/pages/BooksPage.jsx
Normal file
13
src/pages/BooksPage.jsx
Normal file
|
@ -0,0 +1,13 @@
|
|||
import React from "react";
|
||||
import BookList from "../books/BookList";
|
||||
|
||||
const BooksPage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<BookList />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default BooksPage;
|
34
src/pages/ErrorPage.jsx
Normal file
34
src/pages/ErrorPage.jsx
Normal file
|
@ -0,0 +1,34 @@
|
|||
import React from "react";
|
||||
import { Link, useRouteError } from "react-router-dom";
|
||||
import notFound from "../assets/notFound.svg";
|
||||
import other from "../assets/other.svg";
|
||||
|
||||
|
||||
const ErrorPage = () => {
|
||||
const error = useRouteError();
|
||||
console.log(error);
|
||||
|
||||
if (error.status === 404) {
|
||||
return (
|
||||
<div className="errorContainer">
|
||||
<img className="errorImage" src={notFound} alt="404" />
|
||||
<h4 className="errorMessage">Oops!! The resource requested is not available.</h4>
|
||||
<Link className="backHome" to="/">Back Home</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="errorContainer">
|
||||
<img className="errorImage" src={other} alt="other" />
|
||||
<h4 className="errorMessage">
|
||||
Oops! Something went wrong.<br />
|
||||
We encountered an unexpected issue while processing your request.<br />
|
||||
Please try refreshing the page, or come back later.
|
||||
</h4>
|
||||
<Link className="backHome" to="/">Back Home</Link>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorPage;
|
16
src/pages/HomeLayoutPage.jsx
Normal file
16
src/pages/HomeLayoutPage.jsx
Normal file
|
@ -0,0 +1,16 @@
|
|||
import React from "react";
|
||||
import { Outlet } from "react-router-dom";
|
||||
import NavBar from '../components/NavBar';
|
||||
|
||||
|
||||
const HomeLayoutPage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<NavBar />
|
||||
<Outlet />
|
||||
</>
|
||||
)
|
||||
};
|
||||
|
||||
export default HomeLayoutPage;
|
17
src/pages/LandingPage.jsx
Normal file
17
src/pages/LandingPage.jsx
Normal file
|
@ -0,0 +1,17 @@
|
|||
import React from "react";
|
||||
import BookList from "../books/BookList";
|
||||
import Users from "../users/Users";
|
||||
|
||||
|
||||
|
||||
const LandingPage = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/*<BookList />*/}
|
||||
<Users />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default LandingPage;
|
12
src/pages/NewsLetterPage.jsx
Normal file
12
src/pages/NewsLetterPage.jsx
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from "react";
|
||||
import Form from "../components/Form"
|
||||
|
||||
|
||||
const NewsLetterPage = () => {
|
||||
|
||||
return (
|
||||
<Form />
|
||||
);
|
||||
};
|
||||
|
||||
export default NewsLetterPage;
|
5
src/pages/index.js
Normal file
5
src/pages/index.js
Normal file
|
@ -0,0 +1,5 @@
|
|||
export { default as LandingPage } from "./LandingPage";
|
||||
export { default as BooksPage } from "./BooksPage";
|
||||
export { default as NewsLetterPage } from "./NewsLetterPage";
|
||||
export { default as HomeLayoutPage } from "./HomeLayoutPage";
|
||||
export { default as ErrorPage } from "./ErrorPage";
|
31
src/router.jsx
Normal file
31
src/router.jsx
Normal file
|
@ -0,0 +1,31 @@
|
|||
import { createBrowserRouter } from "react-router-dom";
|
||||
|
||||
import {
|
||||
LandingPage,
|
||||
BooksPage,
|
||||
NewsLetterPage,
|
||||
HomeLayoutPage,
|
||||
ErrorPage
|
||||
} from "./pages/index"
|
||||
|
||||
export const router = createBrowserRouter([
|
||||
{
|
||||
path: "/",
|
||||
element: <HomeLayoutPage />,
|
||||
errorElement: <ErrorPage />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <LandingPage />,
|
||||
},
|
||||
{
|
||||
path: "/books",
|
||||
element: <BooksPage />,
|
||||
},
|
||||
{
|
||||
path: "/newsletter",
|
||||
element: <NewsLetterPage />,
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
8
src/store.js
Normal file
8
src/store.js
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import usersReducer from "./features/users/userSlice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
users: usersReducer,
|
||||
},
|
||||
})
|
23
src/users/UserItem.jsx
Normal file
23
src/users/UserItem.jsx
Normal file
|
@ -0,0 +1,23 @@
|
|||
|
||||
import React from 'react';
|
||||
import UserPhoto from './UserPhoto';
|
||||
|
||||
|
||||
const UserItem = ({ user, remove }) => {
|
||||
const { email, location, name, picture } = user;
|
||||
|
||||
return (
|
||||
<div className="user-item">
|
||||
<UserPhoto picture={picture} name={name} />
|
||||
<div className="user-details">
|
||||
<p><strong>Email:</strong> {email}</p>
|
||||
<p><strong>Location:</strong> {location.city}, {location.country}</p>
|
||||
</div>
|
||||
<button className="remove-button" onClick={remove}>
|
||||
Remove
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserItem;
|
14
src/users/UserPhoto.jsx
Normal file
14
src/users/UserPhoto.jsx
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
import React from 'react';
|
||||
|
||||
|
||||
const UserPhoto = ({ picture, name }) => {
|
||||
return (
|
||||
<div className="user-photo">
|
||||
<img src={picture.large} alt={`${name.first} ${name.last}`} className="user-image" />
|
||||
<p>{`${name.first} ${name.last}`}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UserPhoto;
|
60
src/users/Users.jsx
Normal file
60
src/users/Users.jsx
Normal file
|
@ -0,0 +1,60 @@
|
|||
import React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import axios from "axios";
|
||||
import { toast } from "react-toastify";
|
||||
import UserItem from "./UserItem";
|
||||
import MenuTitle from "../components/MenuTitle";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { fetchUsers, resetUsers, clearList, removeUser } from "../features/users/userSlice";
|
||||
|
||||
|
||||
const URL="https://randomuser.me/api/?results=10";
|
||||
|
||||
const Users = () => {
|
||||
const { randomUsers, isLoading } = useSelector((store) => store.users);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchUsers());
|
||||
}, []);
|
||||
|
||||
const handleClearList = () => {
|
||||
dispatch(clearList());
|
||||
};
|
||||
|
||||
const handleReset = () => {
|
||||
dispatch(resetUsers());
|
||||
};
|
||||
|
||||
const handleRemove = (uuid) => {
|
||||
dispatch(removeUser(uuid));
|
||||
};
|
||||
|
||||
if(isLoading) {
|
||||
return <h4>Loading...</h4>;
|
||||
}
|
||||
|
||||
return (
|
||||
<section>
|
||||
<MenuTitle title="Board of Global Executives" />
|
||||
<div className="button-container">
|
||||
{randomUsers.length > 0 ? (
|
||||
<button className="centered-button" onClick={handleClearList}>
|
||||
Clear All
|
||||
</button>
|
||||
) : (
|
||||
<button className="centered-button" onClick={handleReset}>
|
||||
Reset Users
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<div className="user-container">
|
||||
{randomUsers.map((user) => {
|
||||
return <UserItem user={user} key={user.login.uuid} remove={() => handleRemove(user.login.uuid)} />
|
||||
})}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Users;
|
7
vite.config.js
Normal file
7
vite.config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { defineConfig } from 'vite'
|
||||
import react from '@vitejs/plugin-react'
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react()],
|
||||
})
|
Loading…
Reference in New Issue
Block a user