forked from VinokurovVE/tests
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