Сейчас будем пытаться сделать все максимально гибко

This commit is contained in:
2025-09-24 11:54:07 +04:00
parent 51e33fd62d
commit 546f09fda3
8 changed files with 522 additions and 78 deletions

View File

@@ -8,6 +8,9 @@
"name": "online-library",
"version": "0.1.0",
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/material": "^7.3.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",
@@ -2232,6 +2235,152 @@
"postcss-selector-parser": "^6.0.10"
}
},
"node_modules/@emotion/babel-plugin": {
"version": "11.13.5",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
"integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/serialize": "^1.3.3",
"babel-plugin-macros": "^3.1.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^4.0.0",
"find-root": "^1.1.0",
"source-map": "^0.5.7",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
},
"node_modules/@emotion/babel-plugin/node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/@emotion/cache": {
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
"integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
"dependencies": {
"@emotion/memoize": "^0.9.0",
"@emotion/sheet": "^1.4.0",
"@emotion/utils": "^1.4.2",
"@emotion/weak-memoize": "^0.4.0",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="
},
"node_modules/@emotion/is-prop-valid": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.4.0.tgz",
"integrity": "sha512-QgD4fyscGcbbKwJmqNvUMSE02OsHUa+lAWKdEUIJKgqe5IwRSKd7+KhibEWdaKwgjLj0DRSHA9biAIqGBk05lw==",
"dependencies": {
"@emotion/memoize": "^0.9.0"
}
},
"node_modules/@emotion/memoize": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="
},
"node_modules/@emotion/react": {
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/cache": "^11.14.0",
"@emotion/serialize": "^1.3.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
"@emotion/utils": "^1.4.2",
"@emotion/weak-memoize": "^0.4.0",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/serialize": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
"integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
"dependencies": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
"@emotion/utils": "^1.4.2",
"csstype": "^3.0.2"
}
},
"node_modules/@emotion/sheet": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
"integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="
},
"node_modules/@emotion/styled": {
"version": "11.14.1",
"resolved": "https://registry.npmjs.org/@emotion/styled/-/styled-11.14.1.tgz",
"integrity": "sha512-qEEJt42DuToa3gurlH4Qqc1kVpNq8wO8cJtDzU46TjlzWjDlsVyevtYCRijVq3SrHsROS+gVQ8Fnea108GnKzw==",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/is-prop-valid": "^1.3.0",
"@emotion/serialize": "^1.3.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
"@emotion/utils": "^1.4.2"
},
"peerDependencies": {
"@emotion/react": "^11.0.0-rc.0",
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/unitless": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
"integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/utils": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
"integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA=="
},
"node_modules/@emotion/weak-memoize": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="
},
"node_modules/@eslint-community/eslint-utils": {
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.8.0.tgz",
@@ -2764,6 +2913,216 @@
"resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
"integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw=="
},
"node_modules/@mui/core-downloads-tracker": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-7.3.2.tgz",
"integrity": "sha512-AOyfHjyDKVPGJJFtxOlept3EYEdLoar/RvssBTWVAvDJGIE676dLi2oT/Kx+FoVXFoA/JdV7DEMq/BVWV3KHRw==",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
}
},
"node_modules/@mui/material": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mui/material/-/material-7.3.2.tgz",
"integrity": "sha512-qXvbnawQhqUVfH1LMgMaiytP+ZpGoYhnGl7yYq2x57GYzcFL/iPzSZ3L30tlbwEjSVKNYcbiKO8tANR1tadjUg==",
"dependencies": {
"@babel/runtime": "^7.28.3",
"@mui/core-downloads-tracker": "^7.3.2",
"@mui/system": "^7.3.2",
"@mui/types": "^7.4.6",
"@mui/utils": "^7.3.2",
"@popperjs/core": "^2.11.8",
"@types/react-transition-group": "^4.4.12",
"clsx": "^2.1.1",
"csstype": "^3.1.3",
"prop-types": "^15.8.1",
"react-is": "^19.1.1",
"react-transition-group": "^4.4.5"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@mui/material-pigment-css": "^7.3.2",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
},
"@mui/material-pigment-css": {
"optional": true
},
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/material/node_modules/react-is": {
"version": "19.1.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz",
"integrity": "sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA=="
},
"node_modules/@mui/private-theming": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-7.3.2.tgz",
"integrity": "sha512-ha7mFoOyZGJr75xeiO9lugS3joRROjc8tG1u4P50dH0KR7bwhHznVMcYg7MouochUy0OxooJm/OOSpJ7gKcMvg==",
"dependencies": {
"@babel/runtime": "^7.28.3",
"@mui/utils": "^7.3.2",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/styled-engine": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-7.3.2.tgz",
"integrity": "sha512-PkJzW+mTaek4e0nPYZ6qLnW5RGa0KN+eRTf5FA2nc7cFZTeM+qebmGibaTLrgQBy3UpcpemaqfzToBNkzuxqew==",
"dependencies": {
"@babel/runtime": "^7.28.3",
"@emotion/cache": "^11.14.0",
"@emotion/serialize": "^1.3.3",
"@emotion/sheet": "^1.4.0",
"csstype": "^3.1.3",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
}
}
},
"node_modules/@mui/system": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mui/system/-/system-7.3.2.tgz",
"integrity": "sha512-9d8JEvZW+H6cVkaZ+FK56R53vkJe3HsTpcjMUtH8v1xK6Y1TjzHdZ7Jck02mGXJsE6MQGWVs3ogRHTQmS9Q/rA==",
"dependencies": {
"@babel/runtime": "^7.28.3",
"@mui/private-theming": "^7.3.2",
"@mui/styled-engine": "^7.3.2",
"@mui/types": "^7.4.6",
"@mui/utils": "^7.3.2",
"clsx": "^2.1.1",
"csstype": "^3.1.3",
"prop-types": "^15.8.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@emotion/react": "^11.5.0",
"@emotion/styled": "^11.3.0",
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@emotion/react": {
"optional": true
},
"@emotion/styled": {
"optional": true
},
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/types": {
"version": "7.4.6",
"resolved": "https://registry.npmjs.org/@mui/types/-/types-7.4.6.tgz",
"integrity": "sha512-NVBbIw+4CDMMppNamVxyTccNv0WxtDb7motWDlMeSC8Oy95saj1TIZMGynPpFLePt3yOD8TskzumeqORCgRGWw==",
"dependencies": {
"@babel/runtime": "^7.28.3"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/utils": {
"version": "7.3.2",
"resolved": "https://registry.npmjs.org/@mui/utils/-/utils-7.3.2.tgz",
"integrity": "sha512-4DMWQGenOdLnM3y/SdFQFwKsCLM+mqxzvoWp9+x2XdEzXapkznauHLiXtSohHs/mc0+5/9UACt1GdugCX2te5g==",
"dependencies": {
"@babel/runtime": "^7.28.3",
"@mui/types": "^7.4.6",
"@types/prop-types": "^15.7.15",
"clsx": "^2.1.1",
"prop-types": "^15.8.1",
"react-is": "^19.1.1"
},
"engines": {
"node": ">=14.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mui-org"
},
"peerDependencies": {
"@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0",
"react": "^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@mui/utils/node_modules/react-is": {
"version": "19.1.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-19.1.1.tgz",
"integrity": "sha512-tr41fA15Vn8p4X9ntI+yCyeGSf1TlYaY5vlTZfQmeLBrFo3psOPX6HhTDnFNL9uj3EhP0KAQ80cugCl4b4BERA=="
},
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
@@ -5380,6 +5739,14 @@
"wrap-ansi": "^7.0.0"
}
},
"node_modules/clsx": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
"engines": {
"node": ">=6"
}
},
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -7697,6 +8064,11 @@
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
},
"node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
@@ -8335,6 +8707,19 @@
"he": "bin/he"
}
},
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/hoist-non-react-statics/node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
"node_modules/hoopy": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
@@ -14711,6 +15096,11 @@
"postcss": "^8.2.15"
}
},
"node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
},
"node_modules/sucrase": {
"version": "3.35.0",
"resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",

View File

@@ -3,6 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.1",
"@mui/material": "^7.3.2",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.8.0",
"@testing-library/react": "^16.3.0",

View File

@@ -136,6 +136,9 @@ export const bookAPI = {
deelteBook: (id) => {
return api.delete("/book", { params: { id } });
},
getBooksGenre: (params = {}) => {
return api.get("/genre", { params });
},
};
export const authAPI = {

View File

@@ -1,70 +1,62 @@
import { useEffect, useState } from "react";
import { bookAPI } from "../ApiRequest/ApiClient";
import axios from "axios";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap/dist/js/bootstrap.bundle.min";
import { Alert } from "react-bootstrap";
import CustomList from "./CustomList/CustomList";
function Choice() {
const data = [
{
title: "Книги про психологию",
id: "психология",
listOfElements: [
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
],
},
{
title: "Военные книги",
id: "военные",
listOfElements: [
{ title: "etgsfdz" },
{ title: "fgdsfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
],
},
{
title: "Детские книги",
id: "детские",
listOfElements: [
{ title: "etgsfdz" },
{ title: "fgdsfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
],
},
{
title: "Научная литература",
id: "наука",
listOfElements: [
{ title: "etgsfdz" },
{ title: "fgdsfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
{ title: "etgsfdz" },
{ title: "fgdsкукыавчfdz" },
],
},
];
const [genres, setGenres] = useState([]);
const [books, setBooks] = useState([]);
const [loading, setLoading] = useState(false);
const [message, setMessage] = useState(null);
const [error, setError] = useState(null);
useEffect(async () => {
try {
setLoading(true);
const responseGenres = await bookAPI.getBooksGenre();
const responseBooks = await bookAPI.getAll();
if (responseGenres.status === 200) {
setGenres(responseGenres.data);
}
if (responseBooks.status === 200) {
setBooks(responseBooks.data);
}
} catch (error) {
if (axios.isAxiosError(error)) {
setError(error.response.data.message);
} else {
setError("Ошибка загрузки с сервера");
}
} finally {
setLoading(false);
}
}, []);
return (
<main className="container">
<h1 className="text-center mb-5" style={{ color: "var(--accent)" }}>
Книги по тематикам
</h1>
{error && <Alert variant="danger">{error}</Alert>}
{message && <Alert variant="success">{message}</Alert>}
<div className="row g-4">
{data.map((item, index) => (
{genres.map((genre, index) => (
<CustomList
key={index}
genre={genre}
listOfElements={books.filter((book) => book.genre === genre)}
/>
))}
{/* {data.map((item, index) => (
<CustomList
key={index}
id={item.id}
listOfElements={item.listOfElements}
title={item.title}
/>
))}
))} */}
</div>
</main>
);

View File

@@ -3,8 +3,7 @@ import "bootstrap/dist/js/bootstrap.bundle.min";
import "../style.css";
import BookCard from "../BookCard/BookCard";
import { useEffect, useState } from "react";
import { authAPI, bookAPI } from "../ApiRequest/ApiClient";
import { setAccessToken } from "../ApiRequest/JwtUtils";
import { bookAPI } from "../ApiRequest/ApiClient";
import { Spinner } from "react-bootstrap";
function Main() {
@@ -12,11 +11,9 @@ function Main() {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const testUser = {
username: "test21",
password: "123456789",
};
useEffect(() => {
console.log("Вызвалася useEffect в Main.jsx UYGREFGJVHIEGHDJLFSHDGJSGFJL");
}, [error]);
useEffect(() => {
const fetchBooks = async () => {
try {
@@ -31,14 +28,14 @@ function Main() {
};
fetchBooks();
}, []);
if (isLoading) return <Spinner animation="border" size="sm" />;
if (isLoading) return <Spinner animation="border" size="sm" />;
if (error) return <div> Ошибка: {error}</div>;
return (
<div className="container">
<div className="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
{console.log(bookData)}
{bookData.map((book) => (
<BookCard book={book}></BookCard>
<BookCard key={book.id} book={book}></BookCard>
))}
</div>
</div>

View File

@@ -1,4 +1,4 @@
import React, { use, useState } from "react";
import React, { use, useEffect, useState } from "react";
import {
Container,
Row,
@@ -73,6 +73,7 @@ const LoginForm = () => {
username: "",
password: "",
});
useEffect(()=>{console.log("GHDPFHBGFJVK;DLJHFGKDJOHGLKL")},[formData.username])
const handleChange = (e) => {
setFormData({

View File

@@ -4,6 +4,8 @@ import "../style.css";
import BookCard from "../BookCard/BookCard";
import { useEffect, useState } from "react";
import { bookAPI } from "../ApiRequest/ApiClient";
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
function Search() {
const [books, setBooks] = useState([]);
@@ -29,18 +31,18 @@ function Search() {
return (
<main className="container">
<div className="mb-5 mx-auto" style={{ maxWidth: "6000px" }}>
<input
type="text"
<Autocomplete
id="autocompleteSearch"
freeSolo
options={books.map((book) => book.title)}
className="form-control form-control-lg"
placeholder="Введите название книги или автора"
renderInput={(params) => <TextField {...params} label="Поиск книг" />}
/>
</div>
<div className="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
<BookCard
title={"rtjdxfgvhjksfd"}
linkOnImage={"/resources/1984.jpg"}
></BookCard>
{books.map((book) => (
<BookCard key={book.id} book={book}></BookCard>
))}
</div>
</main>
);

View File

@@ -1,11 +1,45 @@
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap/dist/js/bootstrap.bundle.min";
import "../style.css";
import { NavLink } from "react-router-dom";
import { NavLink, useNavigate } from "react-router-dom";
import { HashLink } from "react-router-hash-link";
import { getAccessToken } from "../ApiRequest/JwtUtils";
import { getAccessToken, removeAccessToken } from "../ApiRequest/JwtUtils";
import { useEffect, useState } from "react";
import axios from "axios";
import { authAPI } from "../ApiRequest/ApiClient";
import "bootstrap/dist/css/bootstrap.css";
import "bootstrap/dist/js/bootstrap.bundle.min";
import { Alert } from "react-bootstrap";
function Headers() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [message, setMessage] = useState(null);
const navigate = useNavigate();
const logout = async () => {
setLoading(true);
try {
const response = await authAPI.logout();
removeAccessToken();
if (response.status === 200) {
setMessage("Вы успешно вышли!");
setTimeout(() => {}, 1500);
navigate("/");
}
} catch (error) {
if (axios.isAxiosError(error)) {
setError(error.response.data.message);
} else {
setError("Ошибка подключения");
}
} finally {
setLoading(false);
}
};
const handleClick = () => {
logout();
};
return (
<header className="mb-4">
<h1
@@ -15,7 +49,8 @@ function Headers() {
Добро пожаловать на BookHub
</h1>
<h4 className="text-center mb-4">Самые скучные книги только у нас!</h4>
{error && <Alert variant="danger">{error}</Alert>}
{message && <Alert variant="success">{message}</Alert>}
<nav className="navbar navbar-expand-lg navbar-custom p-3">
<div className="container-fluid">
<button
@@ -70,11 +105,32 @@ function Headers() {
</li>
</ul>
</li>
<li className="nav-item">
<NavLink to={getAccessToken() ? "/lk" : "/registration"} className="nav-link nav-link-custom">
{getAccessToken() ? "Личный кабинет" : "Вход/Регистрация"}
</NavLink>
</li>
{getAccessToken() ? (
<>
<li className="nav-item">
<NavLink to="/lk" className="nav-link nav-link-custom">
Личный кабинет
</NavLink>
</li>
<li className="nav-item">
<button
className="nav-link nav-link-custom"
onClick={logout}
>
Выйти
</button>
</li>
</>
) : (
<li className="nav-item">
<NavLink
to="/registration"
className="nav-link nav-link-custom"
>
Вход/Регистрация
</NavLink>
</li>
)}
</ul>
</div>
</div>