({
+ resolver: zodResolver(ConfirmFormSchema),
+ defaultValues: {
+ code: '',
+ },
+ });
+
+ function setFormErrors(errors: { message: string; path: P[] }[]) {
+ errors.forEach(({ message, path: [path] }) => {
+ const typedPath = path as FieldPath;
+
+ form.setError(typedPath, { message });
+ });
+ }
+
+ const onSubmit = (data: FSchema) => {
+ const body: BSchema = {
+ code: data.code,
+ email: email,
+ };
+
+ sendConfirm.mutate(body, {
+ onSuccess: (res) => {
+ onSuccess?.(body, res);
+ },
+ onError: (err) => {
+ //ошибка валидации локальная
+ if (isAxiosValidationError(err)) {
+ setFormErrors(err?.issues ?? []);
+ }
+ //ошибка валидации серверная
+ if (isAxiosError(err)) {
+ setFormErrors(err?.response?.data?.details ?? []);
+ }
+ },
+ });
+ };
+
+ const disabled = sendConfirm.isPending || sendConfirm.isSuccess;
+
+ return (
+
+
+ Введите код
+ Код подтверждения отправлен на вашу почту.
+
+
+
+
+
+ );
+}
diff --git a/src/pages/signup/ui/SignupForm.tsx b/src/pages/signup/ui/SignupForm.tsx
new file mode 100644
index 0000000..7d1d9b7
--- /dev/null
+++ b/src/pages/signup/ui/SignupForm.tsx
@@ -0,0 +1,199 @@
+'use client';
+
+import type { FieldPath } from 'react-hook-form';
+import { Controller, useForm } from 'react-hook-form';
+import { zodResolver } from '@hookform/resolvers/zod';
+import {
+ Button,
+ Card,
+ CardContent,
+ CardDescription,
+ CardHeader,
+ CardTitle,
+ Field,
+ FieldDescription,
+ FieldError,
+ FieldGroup,
+ FieldLabel,
+ Input,
+ InputEmail,
+ InputPassword,
+ Link,
+ Spinner,
+} from 'shared/ui';
+import { SignupBody, SignupFormSchema, SignupResponse } from '../model/schemas/signup-schema';
+import { cn } from 'shared/lib/utils';
+import { routes } from 'shared/config';
+import { z } from 'zod';
+import { useState } from 'react';
+import { useMutation } from '@tanstack/react-query';
+import { signup } from '../model/services/signup';
+import { fieldNameMapper } from '../model/utils/field-name-mapper';
+import { prepareFullName } from '../model/utils/prepare-fullname';
+import { extractValidationIssues, ValidationIssue } from 'shared/api';
+
+type FSchema = z.infer;
+type BSchema = z.infer;
+type RSchema = z.infer;
+
+interface SignupFormProps extends Omit, 'children' | 'onSubmit'> {
+ onSuccess?: (body: BSchema, res: RSchema) => void;
+}
+
+export function SignupForm({ className, onSuccess, ...props }: SignupFormProps) {
+ const [showPassword, setShowPassword] = useState(false);
+ const sendUserData = useMutation({
+ mutationFn: (data: BSchema) => {
+ return signup(data);
+ },
+ meta: {
+ skipGlobalValidationToast: true,
+ },
+ });
+
+ const form = useForm({
+ resolver: zodResolver(SignupFormSchema),
+ defaultValues: {
+ name: '',
+ email: '',
+ password: '',
+ confirmPassword: '',
+ },
+ });
+
+ function setFormErrors(errors: ValidationIssue[]) {
+ if (Array.isArray(errors)) {
+ errors.forEach(({ message, path: [path] }) => {
+ const typedPath = path as FieldPath;
+ const filedName = fieldNameMapper(typedPath);
+
+ form.setError(filedName, { message });
+ });
+ }
+ }
+
+ const onSubmit = (data: FSchema) => {
+ const body: BSchema = {
+ email: data.email,
+ password: data.password,
+ ...prepareFullName(data.name),
+ };
+
+ sendUserData.mutate(body, {
+ onSuccess: (res) => {
+ onSuccess?.(body, res);
+ },
+ onError: (err) => {
+ setFormErrors(extractValidationIssues(err));
+ },
+ });
+ };
+
+ return (
+
+
+ Создать аккаунт
+ Заполните форму ниже, чтобы начать работу.
+
+
+
+
+
+ );
+}
diff --git a/src/pages/signup/ui/SignupPage.tsx b/src/pages/signup/ui/SignupPage.tsx
new file mode 100644
index 0000000..ed43aa9
--- /dev/null
+++ b/src/pages/signup/ui/SignupPage.tsx
@@ -0,0 +1,45 @@
+'use client';
+
+import { Link, Logo } from 'shared/ui';
+import { SignupForm } from './SignupForm';
+import { OTPForm } from './OTPForm';
+import { useState } from 'react';
+import { useRouter } from 'next/navigation';
+import { accessToken } from 'shared/api';
+import { routes } from 'shared/config';
+import { toast } from 'sonner';
+
+function SignupPage() {
+ const [email, setEmail] = useState('');
+ const router = useRouter();
+
+ return (
+
+
+
+
+
+
+ {!email ? (
+ setEmail(email)} />
+ ) : (
+ {
+ if (res.success) {
+ accessToken.token = res.token;
+ router.replace(routes.team.profile());
+ if (res.message) {
+ toast.success(res.message);
+ }
+ }
+ }}
+ />
+ )}
+
+
+ );
+}
+
+export { SignupPage };
diff --git a/src/shared/api/endpoints/auth/auth.ts b/src/shared/api/endpoints/auth/auth.ts
new file mode 100644
index 0000000..dc2a5ee
--- /dev/null
+++ b/src/shared/api/endpoints/auth/auth.ts
@@ -0,0 +1,709 @@
+/**
+ * Generated by orval v8.7.0 🍺
+ * Do not edit manually.
+ * Task Tracker API
+ * API бэкенда таск-трекера
+ * OpenAPI spec version: 0.1.0
+ */
+import { useMutation } from '@tanstack/react-query';
+import type {
+ MutationFunction,
+ QueryClient,
+ UseMutationOptions,
+ UseMutationResult,
+} from '@tanstack/react-query';
+
+import type {
+ ActionResponseOutput,
+ GlobalErrorResponseOutput,
+ PasswordResetConfirmDtoOutput,
+ RefreshTokenResponseOutput,
+ ResetPasswordDtoOutput,
+ SignInDtoOutput,
+ SignUpDtoOutput,
+ VerifyDtoOutput,
+ VerifyResetCodeDtoOutput,
+} from '../../schemas';
+
+import { instance } from '../../instance';
+import type { ErrorType, BodyType } from '../../instance';
+
+type SecondParameter unknown> = Parameters[1];
+
+/**
+ * Создает пользователя, базовые настройки безопасности и уведомлений.
+ * @summary Регистрация нового пользователя
+ */
+export const authControllerSignUp = (
+ signUpDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/auth/sign-up`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: signUpDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getAuthControllerSignUpMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['authControllerSignUp'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return authControllerSignUp(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerSignUpMutationResult = NonNullable<
+ Awaited>
+>;
+export type AuthControllerSignUpMutationBody = BodyType;
+export type AuthControllerSignUpMutationError = ErrorType;
+
+/**
+ * @summary Регистрация нового пользователя
+ */
+export const useAuthControllerSignUp = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getAuthControllerSignUpMutationOptions(options), queryClient);
+};
+/**
+ * Проверяет OTP из письма, создаёт аккаунт, выдаёт access-токен в теле ответа и устанавливает refresh в httpOnly cookie.
+ * @summary Подтверждение регистрации по коду
+ */
+export const authControllerVerify = (
+ verifyDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/auth/sign-up/confirm`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: verifyDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getAuthControllerVerifyMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['authControllerVerify'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return authControllerVerify(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerVerifyMutationResult = NonNullable<
+ Awaited>
+>;
+export type AuthControllerVerifyMutationBody = BodyType;
+export type AuthControllerVerifyMutationError = ErrorType;
+
+/**
+ * @summary Подтверждение регистрации по коду
+ */
+export const useAuthControllerVerify = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getAuthControllerVerifyMutationOptions(options), queryClient);
+};
+/**
+ * Возвращает Access/Refresh токены. Если у пользователя включена 2FA, вернет временный токен.
+ * @summary Вход в систему
+ */
+export const authControllerSignIn = (
+ signInDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/auth/sign-in`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: signInDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getAuthControllerSignInMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['authControllerSignIn'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return authControllerSignIn(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerSignInMutationResult = NonNullable<
+ Awaited>
+>;
+export type AuthControllerSignInMutationBody = BodyType;
+export type AuthControllerSignInMutationError = ErrorType;
+
+/**
+ * @summary Вход в систему
+ */
+export const useAuthControllerSignIn = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getAuthControllerSignInMutationOptions(options), queryClient);
+};
+/**
+ * Удаляет текущую сессию пользователя из Redis.
+ * @summary Выход из системы
+ */
+export const authControllerLogout = (
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ { url: `/api/v1/auth/sign-out`, method: 'POST', signal },
+ options
+ );
+};
+
+export const getAuthControllerLogoutMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ void,
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ void,
+ TContext
+> => {
+ const mutationKey = ['authControllerLogout'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ void
+ > = () => {
+ return authControllerLogout(requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerLogoutMutationResult = NonNullable<
+ Awaited>
+>;
+
+export type AuthControllerLogoutMutationError = ErrorType;
+
+/**
+ * @summary Выход из системы
+ */
+export const useAuthControllerLogout = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ void,
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult>, TError, void, TContext> => {
+ return useMutation(getAuthControllerLogoutMutationOptions(options), queryClient);
+};
+/**
+ * Выдает новую пару Access и Refresh токенов.
+ * @summary Обновление токенов
+ */
+export const authControllerRefresh = (
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ { url: `/api/v1/auth/refresh`, method: 'POST', signal },
+ options
+ );
+};
+
+export const getAuthControllerRefreshMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ void,
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ void,
+ TContext
+> => {
+ const mutationKey = ['authControllerRefresh'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ void
+ > = () => {
+ return authControllerRefresh(requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerRefreshMutationResult = NonNullable<
+ Awaited>
+>;
+
+export type AuthControllerRefreshMutationError = ErrorType;
+
+/**
+ * @summary Обновление токенов
+ */
+export const useAuthControllerRefresh = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ void,
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult>, TError, void, TContext> => {
+ return useMutation(getAuthControllerRefreshMutationOptions(options), queryClient);
+};
+/**
+ * Отправляет одноразовый код на email, если пользователь существует.
+ * @summary Запрос кода восстановления пароля
+ */
+export const authControllerResetPasswordRequest = (
+ resetPasswordDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/auth/password/reset`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: resetPasswordDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getAuthControllerResetPasswordRequestMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['authControllerResetPasswordRequest'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return authControllerResetPasswordRequest(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerResetPasswordRequestMutationResult = NonNullable<
+ Awaited>
+>;
+export type AuthControllerResetPasswordRequestMutationBody = BodyType;
+export type AuthControllerResetPasswordRequestMutationError = ErrorType;
+
+/**
+ * @summary Запрос кода восстановления пароля
+ */
+export const useAuthControllerResetPasswordRequest = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getAuthControllerResetPasswordRequestMutationOptions(options), queryClient);
+};
+/**
+ * Проверяет код из письма и помечает сессию сброса как подтверждённую.
+ * @summary Проверка кода восстановления пароля
+ */
+export const authControllerVerifyResetCode = (
+ verifyResetCodeDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/auth/password/reset/verify`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: verifyResetCodeDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getAuthControllerVerifyResetCodeMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['authControllerVerifyResetCode'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return authControllerVerifyResetCode(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerVerifyResetCodeMutationResult = NonNullable<
+ Awaited>
+>;
+export type AuthControllerVerifyResetCodeMutationBody = BodyType;
+export type AuthControllerVerifyResetCodeMutationError = ErrorType;
+
+/**
+ * @summary Проверка кода восстановления пароля
+ */
+export const useAuthControllerVerifyResetCode = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getAuthControllerVerifyResetCodeMutationOptions(options), queryClient);
+};
+/**
+ * Доступно только после успешной проверки кода на шаге verify.
+ * @summary Установка нового пароля после сброса
+ */
+export const authControllerConfirmPasswordReset = (
+ passwordResetConfirmDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/auth/password/reset/confirm`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: passwordResetConfirmDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getAuthControllerConfirmPasswordResetMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['authControllerConfirmPasswordReset'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return authControllerConfirmPasswordReset(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type AuthControllerConfirmPasswordResetMutationResult = NonNullable<
+ Awaited>
+>;
+export type AuthControllerConfirmPasswordResetMutationBody =
+ BodyType;
+export type AuthControllerConfirmPasswordResetMutationError = ErrorType;
+
+/**
+ * @summary Установка нового пароля после сброса
+ */
+export const useAuthControllerConfirmPasswordReset = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getAuthControllerConfirmPasswordResetMutationOptions(options), queryClient);
+};
diff --git a/src/shared/api/endpoints/teams/teams.ts b/src/shared/api/endpoints/teams/teams.ts
new file mode 100644
index 0000000..e677733
--- /dev/null
+++ b/src/shared/api/endpoints/teams/teams.ts
@@ -0,0 +1,1552 @@
+/**
+ * Generated by orval v8.7.0 🍺
+ * Do not edit manually.
+ * Task Tracker API
+ * API бэкенда таск-трекера
+ * OpenAPI spec version: 0.1.0
+ */
+import { useMutation, useQuery } from '@tanstack/react-query';
+import type {
+ DataTag,
+ DefinedInitialDataOptions,
+ DefinedUseQueryResult,
+ MutationFunction,
+ QueryClient,
+ QueryFunction,
+ QueryKey,
+ UndefinedInitialDataOptions,
+ UseMutationOptions,
+ UseMutationResult,
+ UseQueryOptions,
+ UseQueryResult,
+} from '@tanstack/react-query';
+
+import type {
+ ActionResponseOutput,
+ CheckSlugResponseOutput,
+ CreateTeamDtoOutput,
+ FileUploadResponseOutput,
+ GlobalErrorResponseOutput,
+ InviteMemberDtoOutput,
+ SyncTagsDtoOutput,
+ TeamMemberResponseOutput,
+ TeamsControllerFindOne200,
+ TeamsControllerUpdateTeamAvatarBody,
+ TeamsControllerUpdateTeamBannerBody,
+ UpdateMemberDtoOutput,
+ UpdateTeamDtoOutput,
+ UserInviteResponseOutput,
+ UserTeamResponseOutput,
+} from '../../schemas';
+
+import { instance } from '../../instance';
+import type { ErrorType, BodyType } from '../../instance';
+
+type SecondParameter unknown> = Parameters[1];
+
+/**
+ * @summary Создать новую команду
+ */
+export const teamsControllerCreate = (
+ createTeamDtoOutput: BodyType,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ {
+ url: `/api/v1/teams`,
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ data: createTeamDtoOutput,
+ signal,
+ },
+ options
+ );
+};
+
+export const getTeamsControllerCreateMutationOptions = <
+ TError = ErrorType,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ const mutationKey = ['teamsControllerCreate'];
+ const { mutation: mutationOptions, request: requestOptions } = options
+ ? options.mutation && 'mutationKey' in options.mutation && options.mutation.mutationKey
+ ? options
+ : { ...options, mutation: { ...options.mutation, mutationKey } }
+ : { mutation: { mutationKey }, request: undefined };
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: BodyType }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return teamsControllerCreate(data, requestOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type TeamsControllerCreateMutationResult = NonNullable<
+ Awaited>
+>;
+export type TeamsControllerCreateMutationBody = BodyType;
+export type TeamsControllerCreateMutationError = ErrorType;
+
+/**
+ * @summary Создать новую команду
+ */
+export const useTeamsControllerCreate = <
+ TError = ErrorType,
+ TContext = unknown,
+>(
+ options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: BodyType },
+ TContext
+> => {
+ return useMutation(getTeamsControllerCreateMutationOptions(options), queryClient);
+};
+/**
+ * Проверяет, свободен ли уникальный адрес команды для использования.
+ * @summary Проверить доступность слага
+ */
+export const teamsControllerCheckSlug = (
+ slug: string,
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ { url: `/api/v1/teams/check-slug/${slug}`, method: 'GET', signal },
+ options
+ );
+};
+
+export const getTeamsControllerCheckSlugQueryKey = (slug: string) => {
+ return [`/api/v1/teams/check-slug/${slug}`] as const;
+};
+
+export const getTeamsControllerCheckSlugQueryOptions = <
+ TData = Awaited>,
+ TError = ErrorType,
+>(
+ slug: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions>, TError, TData>
+ >;
+ request?: SecondParameter;
+ }
+) => {
+ const { query: queryOptions, request: requestOptions } = options ?? {};
+
+ const queryKey = queryOptions?.queryKey ?? getTeamsControllerCheckSlugQueryKey(slug);
+
+ const queryFn: QueryFunction>> = ({
+ signal,
+ }) => teamsControllerCheckSlug(slug, requestOptions, signal);
+
+ return { queryKey, queryFn, enabled: !!slug, ...queryOptions } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type TeamsControllerCheckSlugQueryResult = NonNullable<
+ Awaited>
+>;
+export type TeamsControllerCheckSlugQueryError = ErrorType;
+
+export function useTeamsControllerCheckSlug<
+ TData = Awaited>,
+ TError = ErrorType,
+>(
+ slug: string,
+ options: {
+ query: Partial<
+ UseQueryOptions>, TError, TData>
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ Awaited>
+ >,
+ 'initialData'
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): DefinedUseQueryResult & { queryKey: DataTag };
+export function useTeamsControllerCheckSlug<
+ TData = Awaited>,
+ TError = ErrorType,
+>(
+ slug: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions>, TError, TData>
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ Awaited>
+ >,
+ 'initialData'
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseQueryResult & { queryKey: DataTag };
+export function useTeamsControllerCheckSlug<
+ TData = Awaited>,
+ TError = ErrorType,
+>(
+ slug: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions>, TError, TData>
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Проверить доступность слага
+ */
+
+export function useTeamsControllerCheckSlug<
+ TData = Awaited>,
+ TError = ErrorType,
+>(
+ slug: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions>, TError, TData>
+ >;
+ request?: SecondParameter;
+ },
+ queryClient?: QueryClient
+): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getTeamsControllerCheckSlugQueryOptions(slug, options);
+
+ const query = useQuery(queryOptions, queryClient) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ return { ...query, queryKey: queryOptions.queryKey };
+}
+
+/**
+ * Возвращает все команды, в которых текущий пользователь является участником или владельцем.
+ * @summary Получить список команд пользователя
+ */
+export const teamsControllerFindAll = (
+ options?: SecondParameter,
+ signal?: AbortSignal
+) => {
+ return instance(
+ { url: `/api/v1/teams/my`, method: 'GET', signal },
+ options
+ );
+};
+
+export const getTeamsControllerFindAllQueryKey = () => {
+ return [`/api/v1/teams/my`] as const;
+};
+
+export const getTeamsControllerFindAllQueryOptions = <
+ TData = Awaited>,
+ TError = ErrorType,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions>, TError, TData>
+ >;
+ request?: SecondParameter;
+}) => {
+ const { query: queryOptions, request: requestOptions } = options ?? {};
+
+ const queryKey = queryOptions?.queryKey ?? getTeamsControllerFindAllQueryKey();
+
+ const queryFn: QueryFunction