From c5238bf1a09179f68c1e92e2fbf85eb10ea7528e Mon Sep 17 00:00:00 2001 From: Ivan <8611739+IRBorisov@users.noreply.github.com> Date: Sat, 22 Feb 2025 19:21:10 +0300 Subject: [PATCH] F: Rework users API --- .../src/features/users/backend/api.ts | 16 +++++-- .../src/features/users/backend/types.ts | 44 +++++++++++++------ .../features/users/components/TableUsers.tsx | 2 +- .../src/features/users/models/user.ts | 26 ----------- .../src/features/users/models/userAPI.ts | 2 +- .../users/pages/RegisterPage/FormSignup.tsx | 6 +-- 6 files changed, 47 insertions(+), 49 deletions(-) delete mode 100644 rsconcept/frontend/src/features/users/models/user.ts diff --git a/rsconcept/frontend/src/features/users/backend/api.ts b/rsconcept/frontend/src/features/users/backend/api.ts index 9eb28c23..a007334b 100644 --- a/rsconcept/frontend/src/features/users/backend/api.ts +++ b/rsconcept/frontend/src/features/users/backend/api.ts @@ -1,12 +1,18 @@ import { queryOptions } from '@tanstack/react-query'; +import { z } from 'zod'; import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport'; import { DELAYS, KEYS } from '@/backend/configuration'; import { infoMsg } from '@/utils/labels'; -import { type IUserInfo, type IUserProfile } from '../models/user'; - -import { type IUpdateProfileDTO, type IUserSignupDTO } from './types'; +import { + type IUpdateProfileDTO, + type IUserInfo, + type IUserProfile, + type IUserSignupDTO, + schemaUserInfo, + schemaUserProfile +} from './types'; export const usersApi = { baseKey: KEYS.users, @@ -17,6 +23,7 @@ export const usersApi = { staleTime: DELAYS.staleMedium, queryFn: meta => axiosGet({ + schema: z.array(schemaUserInfo), endpoint: '/users/api/active-users', options: { signal: meta.signal } }) @@ -27,6 +34,7 @@ export const usersApi = { staleTime: DELAYS.staleShort, queryFn: meta => axiosGet({ + schema: schemaUserProfile, endpoint: '/users/api/profile', options: { signal: meta.signal } }) @@ -34,6 +42,7 @@ export const usersApi = { signup: (data: IUserSignupDTO) => axiosPost({ + schema: schemaUserProfile, endpoint: '/users/api/signup', request: { data: data, @@ -43,6 +52,7 @@ export const usersApi = { updateProfile: (data: IUpdateProfileDTO) => axiosPatch({ + schema: schemaUserProfile, endpoint: '/users/api/profile', request: { data: data, diff --git a/rsconcept/frontend/src/features/users/backend/types.ts b/rsconcept/frontend/src/features/users/backend/types.ts index 2943daaa..ead246b6 100644 --- a/rsconcept/frontend/src/features/users/backend/types.ts +++ b/rsconcept/frontend/src/features/users/backend/types.ts @@ -4,8 +4,37 @@ import { patterns } from '@/utils/constants'; import { errorMsg } from '@/utils/labels'; /** - * Represents signup data, used to create new users. + * Represents user detailed information. + * Some information should only be accessible to authorized users */ +export type IUser = z.infer; + +/** Represents user profile for viewing and editing {@link IUser}. */ +export type IUserProfile = z.infer; + +/** Represents user reference information. */ +export type IUserInfo = z.infer; + +/** Represents signup data, used to create new users. */ +export type IUserSignupDTO = z.infer; + +/** Represents user data, intended to update user profile in persistent storage. */ +export type IUpdateProfileDTO = z.infer; + +// ========= SCHEMAS ======== +export const schemaUser = z.object({ + id: z.coerce.number(), + username: z.string().nonempty(errorMsg.requiredField), + is_staff: z.boolean(), + email: z.string().email(errorMsg.emailField), + first_name: z.string(), + last_name: z.string() +}); + +export const schemaUserProfile = schemaUser.omit({ is_staff: true }); + +export const schemaUserInfo = schemaUser.omit({ username: true, email: true, is_staff: true }); + export const schemaUserSignup = z .object({ username: z.string().nonempty(errorMsg.requiredField).regex(RegExp(patterns.login), errorMsg.loginFormat), @@ -18,21 +47,8 @@ export const schemaUserSignup = z }) .refine(schema => schema.password === schema.password2, { path: ['password2'], message: errorMsg.passwordsMismatch }); -/** - * Represents signup data, used to create new users. - */ -export type IUserSignupDTO = z.infer; -/** - * Represents user data, intended to update user profile in persistent storage. - */ - export const schemaUpdateProfile = z.object({ email: z.string().email(errorMsg.emailField), first_name: z.string(), last_name: z.string() }); - -/** - * Represents user data, intended to update user profile in persistent storage. - */ -export type IUpdateProfileDTO = z.infer; diff --git a/rsconcept/frontend/src/features/users/components/TableUsers.tsx b/rsconcept/frontend/src/features/users/components/TableUsers.tsx index b70fb816..584ad5c7 100644 --- a/rsconcept/frontend/src/features/users/components/TableUsers.tsx +++ b/rsconcept/frontend/src/features/users/components/TableUsers.tsx @@ -4,7 +4,7 @@ import { MiniButton } from '@/components/Control'; import { createColumnHelper, DataTable } from '@/components/DataTable'; import { IconRemove } from '@/components/Icons'; -import { type IUserInfo } from '../models/user'; +import { type IUserInfo } from '../backend/types'; interface TableUsersProps { items: IUserInfo[]; diff --git a/rsconcept/frontend/src/features/users/models/user.ts b/rsconcept/frontend/src/features/users/models/user.ts deleted file mode 100644 index 5b3bae34..00000000 --- a/rsconcept/frontend/src/features/users/models/user.ts +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Module: Models for Users. - */ - -/** - * Represents user detailed information. - * Some information should only be accessible to authorized users - */ -export interface IUser { - id: number; - username: string; - is_staff: boolean; - email: string; - first_name: string; - last_name: string; -} - -/** - * Represents user profile for viewing and editing {@link IUser}. - */ -export interface IUserProfile extends Omit {} - -/** - * Represents user reference information. - */ -export interface IUserInfo extends Omit {} diff --git a/rsconcept/frontend/src/features/users/models/userAPI.ts b/rsconcept/frontend/src/features/users/models/userAPI.ts index 9937e449..daf5ddcb 100644 --- a/rsconcept/frontend/src/features/users/models/userAPI.ts +++ b/rsconcept/frontend/src/features/users/models/userAPI.ts @@ -4,7 +4,7 @@ import { TextMatcher } from '@/utils/utils'; -import { type IUserInfo } from './user'; +import { type IUserInfo } from '../backend/types'; /** * Checks if a given target {@link IConstituenta} matches the specified query using the provided matching mode. diff --git a/rsconcept/frontend/src/features/users/pages/RegisterPage/FormSignup.tsx b/rsconcept/frontend/src/features/users/pages/RegisterPage/FormSignup.tsx index 9f95731e..914820f8 100644 --- a/rsconcept/frontend/src/features/users/pages/RegisterPage/FormSignup.tsx +++ b/rsconcept/frontend/src/features/users/pages/RegisterPage/FormSignup.tsx @@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import clsx from 'clsx'; -import { urls, useBlockNavigation, useConceptNavigation } from '@/app'; +import { urls, useConceptNavigation } from '@/app'; import { HelpTopic } from '@/features/help'; import { isAxiosError } from '@/backend/apiTransport'; @@ -30,13 +30,11 @@ export function FormSignup() { register, handleSubmit, clearErrors, - formState: { errors, isDirty } + formState: { errors } } = useForm({ resolver: zodResolver(schemaUserSignup) }); - useBlockNavigation(isDirty); - function resetErrors() { clearServerError(); clearErrors();