diff --git a/locales/en/auth.json b/locales/en/auth.json index 830b66b..abc128a 100644 --- a/locales/en/auth.json +++ b/locales/en/auth.json @@ -13,7 +13,6 @@ "newPassword": "Enter your new password", "confirmPassword": "Confirm your password", "name": "Name", - "login": "@Username", "city": "City (optionally)", "buttonSignIn": "Sign In", @@ -35,7 +34,6 @@ "messageEmailEmpty": "Please input your email", "messageNameEmpty": "Please input your name", - "messageLoginEmpty": "Please input your login", "messagePasswordEmpty": "Please input your password", "messagePasswordLength": "Minimum 8 characters", "messagePasswordDontMatch": "The passwords don't match", diff --git a/locales/ru/auth.json b/locales/ru/auth.json index a77f356..5bafa96 100644 --- a/locales/ru/auth.json +++ b/locales/ru/auth.json @@ -13,7 +13,6 @@ "newPassword": "Введите новый пароль", "confirmPassword": "Повторите пароль", "name": "Имя", - "login": "@Юзернейм", "city": "Город (необязательно)", "buttonSignIn": "Войти", @@ -35,7 +34,6 @@ "messageEmailEmpty": "Пожалуйста, введите свой e-mail", "messageNameEmpty": "Пожалуйста, введите своё имя", - "messageLoginEmpty": "Пожалуйста, введите свой логин", "messagePasswordEmpty": "Пожалуйста, введите свой пароль", "messagePasswordLength": "Минимум 8 символов", "messagePasswordDontMatch": "Пароли не совпадают", diff --git a/openapi-config.json b/openapi-config.json index a05dba8..3f478d3 100644 --- a/openapi-config.json +++ b/openapi-config.json @@ -4,5 +4,9 @@ "apiImport": "emptySplitApi", "outputFile": "./src/services/api/sharebookApi.ts", "exportName": "sharebookApi", - "hooks": true + "hooks": { + "queries": true, + "lazyQueries": true, + "mutations": true + } } \ No newline at end of file diff --git a/src/AppRouter.tsx b/src/AppRouter.tsx index 2ce501e..7587c91 100644 --- a/src/AppRouter.tsx +++ b/src/AppRouter.tsx @@ -1,4 +1,10 @@ -import { BrowserRouter, Route, Routes, StaticRouter } from "react-router"; +import { + BrowserRouter, + Navigate, + Route, + Routes, + StaticRouter, +} from "react-router"; import { Home } from "./pages/home/Home.tsx"; import { HeaderComponent } from "./components/Header"; import { Favourites } from "./pages/favourites/Favourites.tsx"; @@ -26,6 +32,7 @@ export function AppRouter({ location }: { location: string }) { } /> } /> }> + } /> } /> } /> } /> diff --git a/src/index.css b/src/index.css index 7e11fbe..6e46ad9 100644 --- a/src/index.css +++ b/src/index.css @@ -6,6 +6,10 @@ body { margin-top: 3px; } +.ant-input-password-icon { + display: flex; +} + @font-face { font-family: "Literata-Medium"; src: url("./fonts/Literata-Medium.woff") format("woff"); diff --git a/src/pages/auth/ForgotPassword/ForgotPassword.tsx b/src/pages/auth/ForgotPassword/ForgotPassword.tsx index 860fccc..b4880b5 100644 --- a/src/pages/auth/ForgotPassword/ForgotPassword.tsx +++ b/src/pages/auth/ForgotPassword/ForgotPassword.tsx @@ -1,19 +1,29 @@ -import { Button, Form, Input } from "antd"; +import { Button, Form, FormProps, Input } from "antd"; import styles from "../auth.module.scss"; import { SvgPasswordShow } from "../svg/SvgPasswordShow.tsx"; import { SvgPasswordHide } from "../svg/SvgPasswordHide.tsx"; import { useTranslation } from "react-i18next"; -import { useDisabledForm } from "../hooks/useDisabledForm.tsx"; +import { useSendResetPasswordEmailMutation } from "../../../services/api/sharebookApi.ts"; export function ForgotPassword() { const { t } = useTranslation("auth"); - const { form, disabledButton, handleFormChange } = useDisabledForm(); + const [resetPassword] = useSendResetPasswordEmailMutation(); + + const onFinish: FormProps["onFinish"] = async (values) => { + console.log("Success:", values); + try { + await resetPassword({ e }).unwrap(); + navigate("/"); + } catch (err) { + console.log("err:", err); + } + }; return (

{t("titleForgotPassword")}

-
+
{t("buttonResetPassword")} diff --git a/src/pages/auth/GoToEmail/GoToEmail.tsx b/src/pages/auth/GoToEmail/GoToEmail.tsx index 6341fe5..b9c73d2 100644 --- a/src/pages/auth/GoToEmail/GoToEmail.tsx +++ b/src/pages/auth/GoToEmail/GoToEmail.tsx @@ -1,21 +1,16 @@ -import styles from "../auth.module.scss"; import extraStyles from "./goToEmail.module.scss"; -import { Button } from "antd"; import { useTranslation } from "react-i18next"; +import { useSearchParams } from "react-router"; export function GoToEmail() { const { t } = useTranslation("auth"); + const [searchParams] = useSearchParams(); return (

- {t("titleGoToEmail")} {"sharebook.inc@gmail.com"} + {t("titleGoToEmail")} {searchParams.get("email")}

-
- -
); } diff --git a/src/pages/auth/GoToEmail/goToEmail.module.scss b/src/pages/auth/GoToEmail/goToEmail.module.scss index f5b1fe3..e3a5fff 100644 --- a/src/pages/auth/GoToEmail/goToEmail.module.scss +++ b/src/pages/auth/GoToEmail/goToEmail.module.scss @@ -6,7 +6,6 @@ } .title { - margin-bottom: 20px; width: 538px; font-family: 'Onest-SemiBold', sans-serif; diff --git a/src/pages/auth/SignIn/SignIn.tsx b/src/pages/auth/SignIn/SignIn.tsx index 5e6c1f4..f201bf5 100644 --- a/src/pages/auth/SignIn/SignIn.tsx +++ b/src/pages/auth/SignIn/SignIn.tsx @@ -7,13 +7,10 @@ import { SvgPasswordShow } from "../svg/SvgPasswordShow.tsx"; import { useTranslation } from "react-i18next"; import styles from "../auth.module.scss"; import extraStyles from "./signIn.module.scss"; -import { useDisabledForm } from "../hooks/useDisabledForm.tsx"; export function SignIn() { const { t } = useTranslation("auth"); const navigate = useNavigate(); - const { form, disabledButton, handleFormChange } = useDisabledForm(); - const [login, { isLoading }] = useAuthMutation(); const onFinish: FormProps["onFinish"] = async (values) => { @@ -31,19 +28,17 @@ export function SignIn() {

{t("titleSignIn")}

@@ -82,7 +77,6 @@ export function SignIn() { type="primary" htmlType="submit" loading={isLoading} - disabled={disabledButton} > {t("buttonSignIn")} diff --git a/src/pages/auth/SignUp/SignUp.tsx b/src/pages/auth/SignUp/SignUp.tsx index f1be491..bf5c854 100644 --- a/src/pages/auth/SignUp/SignUp.tsx +++ b/src/pages/auth/SignUp/SignUp.tsx @@ -3,14 +3,12 @@ import styles from "../auth.module.scss"; import extraStyles from "./signUp.module.scss"; import { Link, useNavigate, useSearchParams } from "react-router"; import { useTranslation } from "react-i18next"; -import { useDisabledForm } from "../hooks/useDisabledForm.tsx"; const regex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; export function SignUp() { const { t } = useTranslation("auth"); - const { form, disabledButton, handleFormChange } = useDisabledForm(); const [searchParams] = useSearchParams(); const navigate = useNavigate(); @@ -29,12 +27,10 @@ export function SignUp() {
{t("buttonNext")} diff --git a/src/pages/auth/SignUpName/SignUpName.tsx b/src/pages/auth/SignUpName/SignUpName.tsx index 02d209f..7213fa6 100644 --- a/src/pages/auth/SignUpName/SignUpName.tsx +++ b/src/pages/auth/SignUpName/SignUpName.tsx @@ -2,18 +2,16 @@ import { Button, Form, FormProps, Input } from "antd"; import styles from "../auth.module.scss"; import { useNavigate, useSearchParams } from "react-router"; import { useTranslation } from "react-i18next"; -import { useDisabledForm } from "../hooks/useDisabledForm.tsx"; export function SignUpName() { const { t } = useTranslation("auth"); - const { form, disabledButton, handleFormChange } = useDisabledForm(); const [searchParams] = useSearchParams(); const navigate = useNavigate(); const onFinish: FormProps["onFinish"] = (values) => { searchParams.set("name", values.name); - searchParams.set("login", values.login); - searchParams.set("city", values.city); + if (values.city == null) searchParams.set("city", ""); + else searchParams.set("city", values.city); navigate(`/auth/signUpPassword?${searchParams.toString()}`); }; @@ -21,16 +19,13 @@ export function SignUpName() {

{t("titleSignUp")}

- - -
- diff --git a/src/pages/auth/SignUpPassword/SignUpPassword.tsx b/src/pages/auth/SignUpPassword/SignUpPassword.tsx index 718c311..69fdcc6 100644 --- a/src/pages/auth/SignUpPassword/SignUpPassword.tsx +++ b/src/pages/auth/SignUpPassword/SignUpPassword.tsx @@ -6,11 +6,9 @@ import { useRegisterUserMutation } from "../../../services/api/sharebookApi.ts"; import { SvgPasswordShow } from "../svg/SvgPasswordShow.tsx"; import { SvgPasswordHide } from "../svg/SvgPasswordHide.tsx"; import { useTranslation } from "react-i18next"; -import { useDisabledForm } from "../hooks/useDisabledForm.tsx"; export function SignUpPassword() { const { t } = useTranslation("auth"); - const { form, disabledButton, handleFormChange } = useDisabledForm(); const navigate = useNavigate(); const [searchParams] = useSearchParams(); @@ -22,15 +20,15 @@ export function SignUpPassword() { const registerValues = { userRegistrationDto: { name: searchParams.get("name") || "", - login: searchParams.get("login") || "", + login: "test", password: values.password || "", passwordConfirm: values.passwordConfirm || "", email: searchParams.get("email") || "", city: searchParams.get("city") || "", }, }; - navigate(`/auth/goToEmail?${searchParams.toString()}`); await register(registerValues).unwrap(); + navigate(`/auth/goToEmail?${searchParams.toString()}`); } catch (err) { console.log("err:", err); } @@ -41,11 +39,9 @@ export function SignUpPassword() {

{t("titleSignUp")}

{t("buttonNext")} diff --git a/src/pages/auth/hooks/useDisabledForm.tsx b/src/pages/auth/hooks/useDisabledForm.tsx deleted file mode 100644 index b65050e..0000000 --- a/src/pages/auth/hooks/useDisabledForm.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { useForm } from "antd/lib/form/Form"; -import { FormEventHandler, useState } from "react"; - -export const useDisabledForm = () => { - const [form] = useForm(); - const [disabledButton, setDisabledButton] = useState(true); - - const isFormInvalid = () => { - const fieldsError = form.getFieldsError(); - const hasErrors = fieldsError.some((field) => field.errors.length > 0); - - return hasErrors; - }; - - const handleFormChange: FormEventHandler = () => { - setDisabledButton(isFormInvalid()); - }; - - return { form, disabledButton, handleFormChange }; -}; diff --git a/src/services/api/sharebookApi.ts b/src/services/api/sharebookApi.ts index b01e1b1..4df7423 100644 --- a/src/services/api/sharebookApi.ts +++ b/src/services/api/sharebookApi.ts @@ -1,5 +1,4 @@ import { emptySplitApi as api } from "./emptyApi"; - const injectedRtkApi = api.injectEndpoints({ endpoints: (build) => ({ getProfile: build.query({ @@ -65,6 +64,18 @@ const injectedRtkApi = api.injectEndpoints({ }, }), }), + findAttachment: build.query< + FindAttachmentApiResponse, + FindAttachmentApiArg + >({ + query: (queryArg) => ({ + url: `/user/myBook/attachment`, + params: { + id: queryArg.id, + format: queryArg.format, + }, + }), + }), saveAttachment: build.mutation< SaveAttachmentApiResponse, SaveAttachmentApiArg @@ -196,6 +207,16 @@ const injectedRtkApi = api.injectEndpoints({ }, }), }), + searchWithFilters: build.mutation< + SearchWithFiltersApiResponse, + SearchWithFiltersApiArg + >({ + query: (queryArg) => ({ + url: `/books/searchWithFilters`, + method: "POST", + body: queryArg.bookFiltersRequest, + }), + }), auth: build.mutation({ query: (queryArg) => ({ url: `/auth`, @@ -239,22 +260,16 @@ const injectedRtkApi = api.injectEndpoints({ }), }), findAllGenre: build.query({ - query: () => ({ url: `/genre` }), - }), - generateLogin: build.query({ - query: () => ({ url: `/generate-login` }), - }), - searchWithFilters: build.query< - SearchWithFiltersApiResponse, - SearchWithFiltersApiArg - >({ query: (queryArg) => ({ - url: `/books/searchWithFilters`, + url: `/genre`, params: { - filters: queryArg.filters, + locale: queryArg.locale, }, }), }), + generateLogin: build.query({ + query: () => ({ url: `/generate-login` }), + }), searchByTitle: build.query({ query: (queryArg) => ({ url: `/books/searchByTitle`, @@ -345,6 +360,12 @@ export type DeleteBookApiResponse = unknown; export type DeleteBookApiArg = { bookId: number; }; +export type FindAttachmentApiResponse = + /** status 200 Вложение отправлено */ Blob; +export type FindAttachmentApiArg = { + id: number; + format: string; +}; export type SaveAttachmentApiResponse = unknown; export type SaveAttachmentApiArg = { attachmentMultipartDto: AttachmentMultipartDto; @@ -406,6 +427,11 @@ export type RefreshApiResponse = export type RefreshApiArg = { "refresh-token": string; }; +export type SearchWithFiltersApiResponse = + /** status 200 Возвращает найденные книги */ BookModelDto[]; +export type SearchWithFiltersApiArg = { + bookFiltersRequest: BookFiltersRequest; +}; export type AuthApiResponse = /** status 200 Возвращает токены */ AuthResponse; export type AuthApiArg = { loginRequest: LoginRequest; @@ -430,15 +456,12 @@ 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; -export type SearchWithFiltersApiResponse = - /** status 200 Возвращает найденные книги */ BookModelDto[]; -export type SearchWithFiltersApiArg = { - filters: BookFiltersRequest; -}; export type SearchByTitleApiResponse = /** status 200 Возвращает найденные книги */ BookModelDto[]; export type SearchByTitleApiArg = { @@ -518,11 +541,6 @@ export type MessageRequest = { /** Текст сообщения */ text: string; }; -export type AttachmentDto = { - attachId?: number; - data?: string[]; - expansion?: string; -}; export type BookModelDto = { /** Название */ title: string; @@ -536,7 +554,8 @@ export type BookModelDto = { year?: number; /** Идентификатор */ bookId?: number; - attachment?: AttachmentDto; + /** Идентификатор вложения */ + attachmentId?: number; }; export type BookDto = { /** Название */ @@ -597,6 +616,20 @@ export type AuthResponse = { /** Токен доступа */ accessToken?: string; }; +export type BookFiltersRequest = { + /** Город */ + city?: string; + /** Название */ + title?: string; + /** Автор */ + author?: string; + /** Идентификатор жанра */ + genre?: number; + /** Издательство */ + publishingHouse?: string; + /** Год издания */ + year?: number; +}; export type LoginRequest = { /** Логин */ login: string; @@ -623,27 +656,12 @@ export type UserPublicProfileDto = { }; export type GenreDto = { id?: number; - ruName?: string; - engName?: string; + name?: string; }; export type OriginalLoginResponse = { /** Уникальный логин */ originalLogin?: string; }; -export type BookFiltersRequest = { - /** Город */ - city?: string; - /** Название */ - title?: string; - /** Автор */ - author?: string; - /** Идентификатор жанра */ - genre?: number; - /** Издательство */ - publishingHouse?: string; - /** Год издания */ - year?: number; -}; export type InfoUsersDto = { /** Идентификатор */ userId?: number; @@ -664,37 +682,52 @@ export type InfoUsersDto = { }; export const { useGetProfileQuery, + useLazyGetProfileQuery, usePutProfileMutation, usePutMessageMutation, useSendMessageMutation, useDeleteForEveryoneMessageMutation, useBookListQuery, + useLazyBookListQuery, useSaveBookMutation, useDeleteBookMutation, + useFindAttachmentQuery, + useLazyFindAttachmentQuery, useSaveAttachmentMutation, useDeleteAttachmentMutation, useGetCorrespondenceQuery, + useLazyGetCorrespondenceQuery, useCreateCorrespondenceMutation, useDeleteCorrespondenceMutation, useGetAllQuery, + useLazyGetAllQuery, useSaveBookmarksMutation, useDeleteBookmarksMutation, useUpdatePasswordMutation, useSendResetPasswordEmailMutation, useRegisterUserMutation, useRefreshMutation, + useSearchWithFiltersMutation, useAuthMutation, useNonLockedUserMutation, useLockedUserMutation, useGetAllProfileQuery, + useLazyGetAllProfileQuery, useMailConfirmQuery, + useLazyMailConfirmQuery, useFindAllGenreQuery, + useLazyFindAllGenreQuery, useGenerateLoginQuery, - useSearchWithFiltersQuery, + useLazyGenerateLoginQuery, useSearchByTitleQuery, + useLazySearchByTitleQuery, useBookInfoQuery, + useLazyBookInfoQuery, useBooksByUserQuery, + useLazyBooksByUserQuery, useBooksQuery, + useLazyBooksQuery, useUserListQuery, + useLazyUserListQuery, useDeleteForMeMessageMutation, } = injectedRtkApi;