Browse Source

Settings & FormFields

mantine
cracklesparkle 10 months ago
parent
commit
748aa81a99
  1. 27
      frontend_reactjs/src/components/FormFields.tsx
  2. 4
      frontend_reactjs/src/interfaces/create.ts
  3. 35
      frontend_reactjs/src/pages/Settings.tsx
  4. 6
      frontend_reactjs/src/pages/auth/SignIn.tsx
  5. 9
      frontend_reactjs/src/services/AuthService.ts

27
frontend_reactjs/src/components/FormFields.tsx

@ -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({
defaultValues: getDefaultValues(fields)
const { register, handleSubmit, reset, watch, formState: { errors, isSubmitting, dirtyFields, isValid } } = useForm({
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(() => {
mutateHandler?.()
})
const submitResponse = await submitHandler?.(data)
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>

4
frontend_reactjs/src/interfaces/create.ts

@ -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;
} }

35
frontend_reactjs/src/pages/Settings.tsx

@ -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: 'login', headerName: 'Логин', type: 'string', required: true },
//{ key: 'email', headerName: 'E-mail', 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={{
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
gap: "16px",
}}
<Box
sx={{
display: "flex",
flexDirection: "column",
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}
watchValues={['password, password_confirm']}
//submitHandler={RoleService.createRole}
submitHandler={(data) => AuthService.updatePassword({ id: currentUser.id, ...data })}
title="Смена пароля" title="Смена пароля"
/> />
</Stack> </Stack>
</Stack> </Stack>
} }
</Box> </Box>
) )

6
frontend_reactjs/src/pages/auth/SignIn.tsx

@ -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">

9
frontend_reactjs/src/services/AuthService.ts

@ -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: {
'Content-Type': 'application/x-www-form-urlencoded'
}
// headers: {
// '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)
} }
} }
Loading…
Cancel
Save