From f9bc95460af749ae5a6bf7a06ef4f5fc65927b15 Mon Sep 17 00:00:00 2001 From: NookieGrey Date: Fri, 7 Feb 2025 23:18:42 +0400 Subject: [PATCH] Genre WIP --- package-lock.json | 47 +++++++++++++++++-- package.json | 2 + src/AppRouter.tsx | 16 ++++++- src/mainSlice.ts | 36 ++++++++++++++ src/pages/genre/Genre.tsx | 22 +++++++++ src/pages/genre/index.ts | 1 + .../BookCard/components/BookCard.tsx | 6 ++- .../Filter/components/FilterGenre.tsx | 11 ++--- src/services/api/sharebookApi.ts | 14 ++++-- src/services/auth/baseQueryWithReauth.ts | 4 ++ src/store.ts | 2 + 11 files changed, 145 insertions(+), 16 deletions(-) create mode 100644 src/mainSlice.ts create mode 100644 src/pages/genre/Genre.tsx create mode 100644 src/pages/genre/index.ts diff --git a/package-lock.json b/package-lock.json index be55bc8..40c4c46 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "i18next-fs-backend": "^2.6.0", "i18next-http-backend": "^3.0.2", "i18next-http-middleware": "^3.7.1", + "qs": "^6.14.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^15.4.0", @@ -31,6 +32,7 @@ "devDependencies": { "@eslint/js": "^9.17.0", "@rtk-query/codegen-openapi": "^2.0.0", + "@types/qs": "^6.9.18", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@vitejs/plugin-react": "^4.3.4", @@ -1856,6 +1858,13 @@ "devOptional": true, "license": "MIT" }, + "node_modules/@types/qs": { + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/react": { "version": "18.3.18", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", @@ -2346,6 +2355,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -3246,6 +3270,21 @@ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -4729,12 +4768,12 @@ } }, "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.6" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" diff --git a/package.json b/package.json index 397b4e8..0da5d98 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "i18next-fs-backend": "^2.6.0", "i18next-http-backend": "^3.0.2", "i18next-http-middleware": "^3.7.1", + "qs": "^6.14.0", "react": "^18.3.1", "react-dom": "^18.3.1", "react-i18next": "^15.4.0", @@ -38,6 +39,7 @@ "devDependencies": { "@eslint/js": "^9.17.0", "@rtk-query/codegen-openapi": "^2.0.0", + "@types/qs": "^6.9.18", "@types/react": "^18.3.18", "@types/react-dom": "^18.3.5", "@vitejs/plugin-react": "^4.3.4", diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 4ce72df..4a94893 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -6,16 +6,30 @@ import { Favourites } from "./pages/favourites/Favourites.tsx"; import { CreateBook } from "./pages/createBook"; import { Chat } from "./pages/chat/Chat.tsx"; import { Profile } from "./pages/profile"; +import { + useFindAllGenreQuery, + useGetProfileQuery, +} from "./services/api/sharebookApi.ts"; +import { useTranslation } from "react-i18next"; +import { Genre } from "./pages/genre"; const Router = import.meta.env.SSR ? StaticRouter : BrowserRouter; export function AppRouter({ location }: { location: string }) { + const { i18n } = useTranslation(); + + useFindAllGenreQuery({ locale: i18n.language.split("-")[0] }); + useGetProfileQuery({ + userId: "-1", + zone: new Date().getTimezoneOffset() / -60, + }); + return ( } /> - } /> + } /> } /> } /> } /> diff --git a/src/mainSlice.ts b/src/mainSlice.ts new file mode 100644 index 0000000..2c414de --- /dev/null +++ b/src/mainSlice.ts @@ -0,0 +1,36 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { GenreDto, sharebookApi } from "./services/api/sharebookApi.ts"; + +interface MainState { + genreMap: Record; +} + +const initialState: MainState = { + genreMap: {}, +}; + +const mainSlice = createSlice({ + name: "main", + initialState, + reducers: {}, + extraReducers: (builder) => { + builder.addMatcher( + sharebookApi.endpoints.findAllGenre.matchFulfilled, + (state, { payload }) => { + const genreMap: Record = {}; + + payload.forEach((item) => { + if (item.id && item.name) { + genreMap[item.id] = item; + } + }); + + state.genreMap = genreMap; + }, + ); + }, +}); + +// export const {} = mainSlice.actions; + +export const mainReducer = mainSlice.reducer; diff --git a/src/pages/genre/Genre.tsx b/src/pages/genre/Genre.tsx new file mode 100644 index 0000000..7cdbb66 --- /dev/null +++ b/src/pages/genre/Genre.tsx @@ -0,0 +1,22 @@ +import styles from "../home/home.module.scss"; +import { FilterComponent } from "../home/components/Filter"; +import { BookCardComponent } from "../home/components/BookCard"; +import { useSearchWithFiltersQuery } from "../../services/api/sharebookApi.ts"; +import { useParams } from "react-router"; + +export function Genre() { + const { genreId } = useParams(); + + const { data } = useSearchWithFiltersQuery({ + filters: { + genre: +(genreId ?? 1), + }, + }); + + return ( +
+ + +
+ ); +} diff --git a/src/pages/genre/index.ts b/src/pages/genre/index.ts new file mode 100644 index 0000000..4e72f6c --- /dev/null +++ b/src/pages/genre/index.ts @@ -0,0 +1 @@ +export { Genre } from "./Genre.tsx"; diff --git a/src/pages/home/components/BookCard/components/BookCard.tsx b/src/pages/home/components/BookCard/components/BookCard.tsx index 858343b..430a277 100644 --- a/src/pages/home/components/BookCard/components/BookCard.tsx +++ b/src/pages/home/components/BookCard/components/BookCard.tsx @@ -2,10 +2,12 @@ import styles from "../bookCard.module.scss"; import { Card } from "antd"; import img1 from "../img/Image1.png"; import { BookDto } from "../../../../../services/api/sharebookApi.ts"; +import { useAppSelector } from "../../../../../store.ts"; export function BookCard({ book }: { book: BookDto }) { // @ts-expect-error WIP const attachment = book.attachment; + const genreMap = useAppSelector((state) => state.main.genreMap); return ( <> @@ -30,7 +32,9 @@ export function BookCard({ book }: { book: BookDto }) {
{book.title}
{book.author} -

{book.genre}

+ {!!book.genre && ( +

{genreMap[book.genre].name}

+ )} diff --git a/src/pages/home/components/Filter/components/FilterGenre.tsx b/src/pages/home/components/Filter/components/FilterGenre.tsx index de396fc..22b587b 100644 --- a/src/pages/home/components/Filter/components/FilterGenre.tsx +++ b/src/pages/home/components/Filter/components/FilterGenre.tsx @@ -9,12 +9,11 @@ interface Genre { const genres: Genre[] = [ { title: "Все", url: "/", id: "1" }, - { title: "От ShareBook", url: "/filter/FromShareBook", id: "2" }, - { title: "Детективы", url: "/filter/Detectives", id: "3" }, - { title: "Романы", url: "/filter/Novels", id: "4" }, - { title: "Научные", url: "/filter/Scientific", id: "5" }, - { title: "Исскуство", url: "/filter/Art", id: "6" }, - { title: "Учебные", url: "/filter/Tutorials", id: "7" }, + { title: "Детективы", url: "/genre/11", id: "3" }, + { title: "Романы", url: "/genre/1", id: "4" }, + { title: "Научные", url: "/genre/29", id: "5" }, + { title: "Ужасы", url: "/genre/15", id: "6" }, + { title: "Учебник", url: "/genre/28", id: "7" }, ]; export function FilterGenre() { diff --git a/src/services/api/sharebookApi.ts b/src/services/api/sharebookApi.ts index b01e1b1..22094ea 100644 --- a/src/services/api/sharebookApi.ts +++ b/src/services/api/sharebookApi.ts @@ -239,7 +239,12 @@ const injectedRtkApi = api.injectEndpoints({ }), }), findAllGenre: build.query({ - query: () => ({ url: `/genre` }), + query: (queryArg) => ({ + url: `/genre`, + params: { + locale: queryArg.locale, + }, + }), }), generateLogin: build.query({ query: () => ({ url: `/generate-login` }), @@ -430,7 +435,9 @@ export type MailConfirmApiArg = { }; export type FindAllGenreApiResponse = /** status 200 Список жанров */ GenreDto[]; -export type FindAllGenreApiArg = void; +export type FindAllGenreApiArg = { + locale: string; +}; export type GenerateLoginApiResponse = /** status 200 Уникальный на данный момент логин */ OriginalLoginResponse; export type GenerateLoginApiArg = void; @@ -623,8 +630,7 @@ export type UserPublicProfileDto = { }; export type GenreDto = { id?: number; - ruName?: string; - engName?: string; + name?: string; }; export type OriginalLoginResponse = { /** Уникальный логин */ diff --git a/src/services/auth/baseQueryWithReauth.ts b/src/services/auth/baseQueryWithReauth.ts index e82999e..28e5b79 100644 --- a/src/services/auth/baseQueryWithReauth.ts +++ b/src/services/auth/baseQueryWithReauth.ts @@ -12,6 +12,7 @@ import { startRefresh, } from "./authSlice"; import type { RootState } from "../../store"; +import qs from "qs"; // const baseUrl = import.meta.env.PROD ? "https://194.67.125.199:8443/" : "https://frontend-wmyr.onrender.com/" // Исходный fetchBaseQuery @@ -37,6 +38,9 @@ const rawBaseQuery = fetchBaseQuery({ return headers; }, + paramsSerializer: (params) => { + return qs.stringify(params); + }, }); // Наша обёртка diff --git a/src/store.ts b/src/store.ts index 3806d14..0fced9c 100644 --- a/src/store.ts +++ b/src/store.ts @@ -3,11 +3,13 @@ import { authReducer } from "./services/auth/authSlice"; import { sharebookApi } from "./services/api/sharebookApi"; import { chatReducer } from "./pages/chat/chatSlice.ts"; import { useDispatch, useSelector } from "react-redux"; +import { mainReducer } from "./mainSlice.ts"; const rootReducer = combineReducers({ [sharebookApi.reducerPath]: sharebookApi.reducer, auth: authReducer, chat: chatReducer, + main: mainReducer, }); export type RootState = ReturnType;