Settings & FormFields
This commit is contained in:
		@ -1,11 +1,11 @@
 | 
				
			|||||||
import { SubmitHandler, useForm } from 'react-hook-form'
 | 
					import { SubmitHandler, useForm } from 'react-hook-form'
 | 
				
			||||||
import { CreateField } from '../interfaces/create'
 | 
					import { CreateField } from '../interfaces/create'
 | 
				
			||||||
import { Box, Button, CircularProgress, Stack, TextField, Typography } from '@mui/material';
 | 
					import { Box, Button, CircularProgress, Stack, TextField, Typography } from '@mui/material';
 | 
				
			||||||
import { useEffect } from 'react';
 | 
					import { AxiosResponse } from 'axios';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface Props {
 | 
					interface Props {
 | 
				
			||||||
    title?: string;
 | 
					    title?: string;
 | 
				
			||||||
    submitHandler?: any;
 | 
					    submitHandler?: (data: any) => Promise<AxiosResponse<any, any>>;
 | 
				
			||||||
    fields: CreateField[];
 | 
					    fields: CreateField[];
 | 
				
			||||||
    submitButtonText?: string;
 | 
					    submitButtonText?: string;
 | 
				
			||||||
    mutateHandler?: any;
 | 
					    mutateHandler?: any;
 | 
				
			||||||
@ -29,15 +29,21 @@ function FormFields({
 | 
				
			|||||||
        return result
 | 
					        return result
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const { register, handleSubmit, watch, formState: { errors, isSubmitting, dirtyFields } } = useForm({
 | 
					    const { register, handleSubmit, reset, watch, formState: { errors, isSubmitting, dirtyFields, isValid } } = useForm({
 | 
				
			||||||
        defaultValues: getDefaultValues(fields)
 | 
					        mode: 'onChange',
 | 
				
			||||||
 | 
					        defaultValues: defaultValues ? getDefaultValues(fields) : {}
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const onSubmit: SubmitHandler<any> = async (data) => {
 | 
					    const onSubmit: SubmitHandler<any> = async (data) => {
 | 
				
			||||||
 | 
					        fields.forEach((field: CreateField) => {
 | 
				
			||||||
 | 
					            if (field.include === false) {
 | 
				
			||||||
 | 
					                delete data[field.key]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            await submitHandler?.(data).then(() => {
 | 
					            const submitResponse = await submitHandler?.(data)
 | 
				
			||||||
                mutateHandler?.()
 | 
					            mutateHandler?.(JSON.stringify(submitResponse?.data))
 | 
				
			||||||
            })
 | 
					            reset(submitResponse?.data)
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
            console.error(error)
 | 
					            console.error(error)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -60,16 +66,17 @@ function FormFields({
 | 
				
			|||||||
                            label={field.headerName || field.key.charAt(0).toUpperCase() + field.key.slice(1)}
 | 
					                            label={field.headerName || field.key.charAt(0).toUpperCase() + field.key.slice(1)}
 | 
				
			||||||
                            required={field.required || false}
 | 
					                            required={field.required || false}
 | 
				
			||||||
                            {...register(field.key, {
 | 
					                            {...register(field.key, {
 | 
				
			||||||
                                required: `${field.key} обязателен`,
 | 
					                                required: field.required ? `${field.headerName} обязателен` : false,
 | 
				
			||||||
                                validate: (val: string | boolean) => {
 | 
					                                validate: (val: string | boolean) => {
 | 
				
			||||||
                                    if (field.watch) {
 | 
					                                    if (field.watch) {
 | 
				
			||||||
                                        if (watch(field.watch) != val) {
 | 
					                                        if (watch(field.watch) != val) {
 | 
				
			||||||
                                            return field.watchMessage || ''
 | 
					                                            return field.watchMessage || ''
 | 
				
			||||||
                                        }
 | 
					                                        }
 | 
				
			||||||
                                    }
 | 
					                                    }
 | 
				
			||||||
                                }
 | 
					                                },
 | 
				
			||||||
                            })}
 | 
					                            })}
 | 
				
			||||||
                            error={!!errors[field.key]}
 | 
					                            error={!!errors[field.key]}
 | 
				
			||||||
 | 
					                            helperText={errors[field.key]?.message}
 | 
				
			||||||
                        />
 | 
					                        />
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                })}
 | 
					                })}
 | 
				
			||||||
@ -79,7 +86,7 @@ function FormFields({
 | 
				
			|||||||
                    justifyContent: "space-between",
 | 
					                    justifyContent: "space-between",
 | 
				
			||||||
                    gap: "8px"
 | 
					                    gap: "8px"
 | 
				
			||||||
                }}>
 | 
					                }}>
 | 
				
			||||||
                    <Button disabled={isSubmitting} type="submit" variant="contained" color="primary">
 | 
					                    <Button disabled={isSubmitting || Object.keys(dirtyFields).length === 0 || !isValid} type="submit" variant="contained" color="primary">
 | 
				
			||||||
                        {isSubmitting ? <CircularProgress size={16} /> : submitButtonText}
 | 
					                        {isSubmitting ? <CircularProgress size={16} /> : submitButtonText}
 | 
				
			||||||
                    </Button>
 | 
					                    </Button>
 | 
				
			||||||
                </Box>
 | 
					                </Box>
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,10 @@ export interface CreateField {
 | 
				
			|||||||
    defaultValue?: any;
 | 
					    defaultValue?: any;
 | 
				
			||||||
    inputType?: InputType;
 | 
					    inputType?: InputType;
 | 
				
			||||||
    validate?: Validate<string, boolean>;
 | 
					    validate?: Validate<string, boolean>;
 | 
				
			||||||
 | 
					    /** Watch for field */
 | 
				
			||||||
    watch?: string;
 | 
					    watch?: string;
 | 
				
			||||||
 | 
					    /** Message on watch */
 | 
				
			||||||
    watchMessage?: string;
 | 
					    watchMessage?: string;
 | 
				
			||||||
 | 
					    /** Should field be included in the request */
 | 
				
			||||||
 | 
					    include?: boolean;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1,10 +1,11 @@
 | 
				
			|||||||
import { Box, Stack, Typography } from "@mui/material"
 | 
					import { Box, Stack } from "@mui/material"
 | 
				
			||||||
import UserService from "../services/UserService"
 | 
					import UserService from "../services/UserService"
 | 
				
			||||||
import { useAuthStore } from "../store/auth"
 | 
					import { setUserData, useAuthStore } from "../store/auth"
 | 
				
			||||||
import { useEffect, useState } from "react"
 | 
					import { useEffect, useState } from "react"
 | 
				
			||||||
import { CreateField } from "../interfaces/create"
 | 
					import { CreateField } from "../interfaces/create"
 | 
				
			||||||
import { IUser } from "../interfaces/user"
 | 
					import { IUser } from "../interfaces/user"
 | 
				
			||||||
import FormFields from "../components/FormFields"
 | 
					import FormFields from "../components/FormFields"
 | 
				
			||||||
 | 
					import AuthService from "../services/AuthService"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default function Settings() {
 | 
					export default function Settings() {
 | 
				
			||||||
    const { token } = useAuthStore()
 | 
					    const { token } = useAuthStore()
 | 
				
			||||||
@ -25,8 +26,8 @@ export default function Settings() {
 | 
				
			|||||||
    }, [token])
 | 
					    }, [token])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const profileFields: CreateField[] = [
 | 
					    const profileFields: CreateField[] = [
 | 
				
			||||||
        { key: 'email', headerName: 'E-mail', type: 'string', required: true },
 | 
					        //{ key: 'email', headerName: 'E-mail', type: 'string', required: true },
 | 
				
			||||||
        { key: 'login', headerName: 'Логин', type: 'string', required: true },
 | 
					        //{ key: 'login', headerName: 'Логин', type: 'string', required: true },
 | 
				
			||||||
        { key: 'phone', headerName: 'Телефон', type: 'string', required: false },
 | 
					        { key: 'phone', headerName: 'Телефон', type: 'string', required: false },
 | 
				
			||||||
        { key: 'name', headerName: 'Имя', type: 'string', required: true },
 | 
					        { key: 'name', headerName: 'Имя', type: 'string', required: true },
 | 
				
			||||||
        { key: 'surname', headerName: 'Фамилия', type: 'string', required: true },
 | 
					        { key: 'surname', headerName: 'Фамилия', type: 'string', required: true },
 | 
				
			||||||
@ -34,16 +35,17 @@ export default function Settings() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const passwordFields: CreateField[] = [
 | 
					    const passwordFields: CreateField[] = [
 | 
				
			||||||
        { key: 'password', headerName: 'Новый пароль', type: 'string', required: true, inputType: 'password' },
 | 
					        { key: 'password', headerName: 'Новый пароль', type: 'string', required: true, inputType: 'password' },
 | 
				
			||||||
        { key: 'password_confirm', headerName: 'Подтверждение пароля', type: 'string', required: true, inputType: 'password', watch: 'password', watchMessage: 'Пароли не совпадают' },
 | 
					        { key: 'password_confirm', headerName: 'Подтверждение пароля', type: 'string', required: true, inputType: 'password', watch: 'password', watchMessage: 'Пароли не совпадают', include: false },
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
        <Box sx={{
 | 
					        <Box
 | 
				
			||||||
            display: "flex",
 | 
					            sx={{
 | 
				
			||||||
            flexDirection: "column",
 | 
					                display: "flex",
 | 
				
			||||||
            alignItems: "flex-start",
 | 
					                flexDirection: "column",
 | 
				
			||||||
            gap: "16px",
 | 
					                alignItems: "flex-start",
 | 
				
			||||||
        }}
 | 
					                gap: "16px",
 | 
				
			||||||
 | 
					            }}
 | 
				
			||||||
        >
 | 
					        >
 | 
				
			||||||
            {currentUser &&
 | 
					            {currentUser &&
 | 
				
			||||||
                <Stack spacing={2} width='100%'>
 | 
					                <Stack spacing={2} width='100%'>
 | 
				
			||||||
@ -51,21 +53,22 @@ export default function Settings() {
 | 
				
			|||||||
                        <FormFields
 | 
					                        <FormFields
 | 
				
			||||||
                            fields={profileFields}
 | 
					                            fields={profileFields}
 | 
				
			||||||
                            defaultValues={currentUser}
 | 
					                            defaultValues={currentUser}
 | 
				
			||||||
                            //submitHandler={RoleService.createRole}
 | 
					                            mutateHandler={(data: any) => {
 | 
				
			||||||
 | 
					                                setUserData(data)
 | 
				
			||||||
 | 
					                            }}
 | 
				
			||||||
 | 
					                            submitHandler={(data) => UserService.updateUser({ id: currentUser.id, ...data })}
 | 
				
			||||||
                            title="Пользователь"
 | 
					                            title="Пользователь"
 | 
				
			||||||
                        />
 | 
					                        />
 | 
				
			||||||
                    </Stack>
 | 
					                    </Stack>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    <Stack width='100%'>
 | 
					                    <Stack width='100%'>
 | 
				
			||||||
                        <FormFields
 | 
					                        <FormFields
 | 
				
			||||||
                            fields={passwordFields}
 | 
					                            fields={passwordFields}
 | 
				
			||||||
                            defaultValues={currentUser}
 | 
					                            submitHandler={(data) => AuthService.updatePassword({ id: currentUser.id, ...data })}
 | 
				
			||||||
                            watchValues={['password, password_confirm']}
 | 
					 | 
				
			||||||
                            //submitHandler={RoleService.createRole}
 | 
					 | 
				
			||||||
                            title="Смена пароля"
 | 
					                            title="Смена пароля"
 | 
				
			||||||
                        />
 | 
					                        />
 | 
				
			||||||
                    </Stack>
 | 
					                    </Stack>
 | 
				
			||||||
                </Stack>
 | 
					                </Stack>
 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        </Box>
 | 
					        </Box>
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
import { useForm, SubmitHandler } from 'react-hook-form';
 | 
					import { useForm, SubmitHandler } from 'react-hook-form';
 | 
				
			||||||
import { TextField, Button, Container, Typography, Box, Stack, Link } from '@mui/material';
 | 
					import { TextField, Button, Container, Typography, Box, Stack, Link, CircularProgress } from '@mui/material';
 | 
				
			||||||
import { AxiosResponse } from 'axios';
 | 
					import { AxiosResponse } from 'axios';
 | 
				
			||||||
import { ApiResponse, LoginFormData } from '../../interfaces/auth';
 | 
					import { ApiResponse, LoginFormData } from '../../interfaces/auth';
 | 
				
			||||||
import { login, setUserData } from '../../store/auth';
 | 
					import { login, setUserData } from '../../store/auth';
 | 
				
			||||||
@ -8,7 +8,7 @@ import AuthService from '../../services/AuthService';
 | 
				
			|||||||
import UserService from '../../services/UserService';
 | 
					import UserService from '../../services/UserService';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const SignIn = () => {
 | 
					const SignIn = () => {
 | 
				
			||||||
  const { register, handleSubmit, formState: { errors } } = useForm<LoginFormData>({
 | 
					  const { register, handleSubmit, formState: { errors, isSubmitting } } = useForm<LoginFormData>({
 | 
				
			||||||
    defaultValues: {
 | 
					    defaultValues: {
 | 
				
			||||||
      username: '',
 | 
					      username: '',
 | 
				
			||||||
      password: '',
 | 
					      password: '',
 | 
				
			||||||
@ -82,7 +82,7 @@ const SignIn = () => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            <Box sx={{ display: 'flex', gap: '16px' }}>
 | 
					            <Box sx={{ display: 'flex', gap: '16px' }}>
 | 
				
			||||||
              <Button fullWidth type="submit" variant="contained" color="primary">
 | 
					              <Button fullWidth type="submit" variant="contained" color="primary">
 | 
				
			||||||
                Вход
 | 
					                {isSubmitting ? <CircularProgress size={16} /> : 'Вход'}
 | 
				
			||||||
              </Button>
 | 
					              </Button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              <Button fullWidth href="/auth/signup" type="button" variant="text" color="primary">
 | 
					              <Button fullWidth href="/auth/signup" type="button" variant="text" color="primary">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,12 @@
 | 
				
			|||||||
import { AxiosRequestConfig } from "axios";
 | 
					import { AxiosRequestConfig } from "axios";
 | 
				
			||||||
import { BASE_URL } from "../constants";
 | 
					import { BASE_URL } from "../constants";
 | 
				
			||||||
import axiosInstance from "../http/axiosInstance";
 | 
					import axiosInstance from "../http/axiosInstance";
 | 
				
			||||||
import { IUser } from "../interfaces/user";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const config: AxiosRequestConfig = {
 | 
					const config: AxiosRequestConfig = {
 | 
				
			||||||
    baseURL: BASE_URL.auth,
 | 
					    baseURL: BASE_URL.auth,
 | 
				
			||||||
    headers: {
 | 
					    // headers: {
 | 
				
			||||||
        'Content-Type': 'application/x-www-form-urlencoded'
 | 
					    //     'Content-Type': 'application/x-www-form-urlencoded'
 | 
				
			||||||
    }
 | 
					    // }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class AuthService {
 | 
					export default class AuthService {
 | 
				
			||||||
@ -27,7 +26,7 @@ export default class AuthService {
 | 
				
			|||||||
        return await axiosInstance.put(`/auth/user/reset_password?email=${email}`, null, config)
 | 
					        return await axiosInstance.put(`/auth/user/reset_password?email=${email}`, null, config)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static async updatePassword(data: IUser) {
 | 
					    static async updatePassword(data: { id: number, password: string }) {
 | 
				
			||||||
        return await axiosInstance.put(`/auth/user/password_change`, data, config)
 | 
					        return await axiosInstance.put(`/auth/user/password_change`, data, config)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user