mirror of
https://github.com/IRBorisov/ConceptPortal.git
synced 2025-06-26 13:00:39 +03:00
This commit is contained in:
parent
b29a4e7b49
commit
fbdd561344
|
@ -1,12 +1,18 @@
|
||||||
import { queryOptions } from '@tanstack/react-query';
|
import { queryOptions } from '@tanstack/react-query';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
import { axiosGet, axiosPatch, axiosPost } from '@/backend/apiTransport';
|
||||||
import { DELAYS, KEYS } from '@/backend/configuration';
|
import { DELAYS, KEYS } from '@/backend/configuration';
|
||||||
import { infoMsg } from '@/utils/labels';
|
import { infoMsg } from '@/utils/labels';
|
||||||
|
|
||||||
import { type IUserInfo, type IUserProfile } from '../models/user';
|
import {
|
||||||
|
type IUpdateProfileDTO,
|
||||||
import { type IUpdateProfileDTO, type IUserSignupDTO } from './types';
|
type IUserInfo,
|
||||||
|
type IUserProfile,
|
||||||
|
type IUserSignupDTO,
|
||||||
|
schemaUserInfo,
|
||||||
|
schemaUserProfile
|
||||||
|
} from './types';
|
||||||
|
|
||||||
export const usersApi = {
|
export const usersApi = {
|
||||||
baseKey: KEYS.users,
|
baseKey: KEYS.users,
|
||||||
|
@ -17,6 +23,7 @@ export const usersApi = {
|
||||||
staleTime: DELAYS.staleMedium,
|
staleTime: DELAYS.staleMedium,
|
||||||
queryFn: meta =>
|
queryFn: meta =>
|
||||||
axiosGet<IUserInfo[]>({
|
axiosGet<IUserInfo[]>({
|
||||||
|
schema: z.array(schemaUserInfo),
|
||||||
endpoint: '/users/api/active-users',
|
endpoint: '/users/api/active-users',
|
||||||
options: { signal: meta.signal }
|
options: { signal: meta.signal }
|
||||||
})
|
})
|
||||||
|
@ -27,6 +34,7 @@ export const usersApi = {
|
||||||
staleTime: DELAYS.staleShort,
|
staleTime: DELAYS.staleShort,
|
||||||
queryFn: meta =>
|
queryFn: meta =>
|
||||||
axiosGet<IUserProfile>({
|
axiosGet<IUserProfile>({
|
||||||
|
schema: schemaUserProfile,
|
||||||
endpoint: '/users/api/profile',
|
endpoint: '/users/api/profile',
|
||||||
options: { signal: meta.signal }
|
options: { signal: meta.signal }
|
||||||
})
|
})
|
||||||
|
@ -34,6 +42,7 @@ export const usersApi = {
|
||||||
|
|
||||||
signup: (data: IUserSignupDTO) =>
|
signup: (data: IUserSignupDTO) =>
|
||||||
axiosPost<IUserSignupDTO, IUserProfile>({
|
axiosPost<IUserSignupDTO, IUserProfile>({
|
||||||
|
schema: schemaUserProfile,
|
||||||
endpoint: '/users/api/signup',
|
endpoint: '/users/api/signup',
|
||||||
request: {
|
request: {
|
||||||
data: data,
|
data: data,
|
||||||
|
@ -43,6 +52,7 @@ export const usersApi = {
|
||||||
|
|
||||||
updateProfile: (data: IUpdateProfileDTO) =>
|
updateProfile: (data: IUpdateProfileDTO) =>
|
||||||
axiosPatch<IUpdateProfileDTO, IUserProfile>({
|
axiosPatch<IUpdateProfileDTO, IUserProfile>({
|
||||||
|
schema: schemaUserProfile,
|
||||||
endpoint: '/users/api/profile',
|
endpoint: '/users/api/profile',
|
||||||
request: {
|
request: {
|
||||||
data: data,
|
data: data,
|
||||||
|
|
|
@ -4,8 +4,37 @@ import { patterns } from '@/utils/constants';
|
||||||
import { errorMsg } from '@/utils/labels';
|
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<typeof schemaUser>;
|
||||||
|
|
||||||
|
/** Represents user profile for viewing and editing {@link IUser}. */
|
||||||
|
export type IUserProfile = z.infer<typeof schemaUserProfile>;
|
||||||
|
|
||||||
|
/** Represents user reference information. */
|
||||||
|
export type IUserInfo = z.infer<typeof schemaUserInfo>;
|
||||||
|
|
||||||
|
/** Represents signup data, used to create new users. */
|
||||||
|
export type IUserSignupDTO = z.infer<typeof schemaUserSignup>;
|
||||||
|
|
||||||
|
/** Represents user data, intended to update user profile in persistent storage. */
|
||||||
|
export type IUpdateProfileDTO = z.infer<typeof schemaUpdateProfile>;
|
||||||
|
|
||||||
|
// ========= 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
|
export const schemaUserSignup = z
|
||||||
.object({
|
.object({
|
||||||
username: z.string().nonempty(errorMsg.requiredField).regex(RegExp(patterns.login), errorMsg.loginFormat),
|
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 });
|
.refine(schema => schema.password === schema.password2, { path: ['password2'], message: errorMsg.passwordsMismatch });
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents signup data, used to create new users.
|
|
||||||
*/
|
|
||||||
export type IUserSignupDTO = z.infer<typeof schemaUserSignup>;
|
|
||||||
/**
|
|
||||||
* Represents user data, intended to update user profile in persistent storage.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const schemaUpdateProfile = z.object({
|
export const schemaUpdateProfile = z.object({
|
||||||
email: z.string().email(errorMsg.emailField),
|
email: z.string().email(errorMsg.emailField),
|
||||||
first_name: z.string(),
|
first_name: z.string(),
|
||||||
last_name: z.string()
|
last_name: z.string()
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents user data, intended to update user profile in persistent storage.
|
|
||||||
*/
|
|
||||||
export type IUpdateProfileDTO = z.infer<typeof schemaUpdateProfile>;
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { MiniButton } from '@/components/Control';
|
||||||
import { createColumnHelper, DataTable } from '@/components/DataTable';
|
import { createColumnHelper, DataTable } from '@/components/DataTable';
|
||||||
import { IconRemove } from '@/components/Icons';
|
import { IconRemove } from '@/components/Icons';
|
||||||
|
|
||||||
import { type IUserInfo } from '../models/user';
|
import { type IUserInfo } from '../backend/types';
|
||||||
|
|
||||||
interface TableUsersProps {
|
interface TableUsersProps {
|
||||||
items: IUserInfo[];
|
items: IUserInfo[];
|
||||||
|
|
|
@ -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<IUser, 'is_staff'> {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents user reference information.
|
|
||||||
*/
|
|
||||||
export interface IUserInfo extends Omit<IUserProfile, 'email' | 'username'> {}
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
import { TextMatcher } from '@/utils/utils';
|
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.
|
* Checks if a given target {@link IConstituenta} matches the specified query using the provided matching mode.
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { useForm } from 'react-hook-form';
|
||||||
import { zodResolver } from '@hookform/resolvers/zod';
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
|
|
||||||
import { urls, useBlockNavigation, useConceptNavigation } from '@/app';
|
import { urls, useConceptNavigation } from '@/app';
|
||||||
import { HelpTopic } from '@/features/help';
|
import { HelpTopic } from '@/features/help';
|
||||||
|
|
||||||
import { isAxiosError } from '@/backend/apiTransport';
|
import { isAxiosError } from '@/backend/apiTransport';
|
||||||
|
@ -30,13 +30,11 @@ export function FormSignup() {
|
||||||
register,
|
register,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
clearErrors,
|
clearErrors,
|
||||||
formState: { errors, isDirty }
|
formState: { errors }
|
||||||
} = useForm<IUserSignupDTO>({
|
} = useForm<IUserSignupDTO>({
|
||||||
resolver: zodResolver(schemaUserSignup)
|
resolver: zodResolver(schemaUserSignup)
|
||||||
});
|
});
|
||||||
|
|
||||||
useBlockNavigation(isDirty);
|
|
||||||
|
|
||||||
function resetErrors() {
|
function resetErrors() {
|
||||||
clearServerError();
|
clearServerError();
|
||||||
clearErrors();
|
clearErrors();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user