Cleanup, shared create modal

This commit is contained in:
cracklesparkle
2024-07-22 16:42:17 +09:00
parent e1f9dc762c
commit 0ac0534486
11 changed files with 157 additions and 480 deletions

View File

@ -17,6 +17,7 @@ import Boilers from "./pages/Boilers"
import Servers from "./pages/Servers"
import { Api, Assignment, Cloud, Factory, Home, Login, People, Shield, Storage } from "@mui/icons-material"
// Определение страниц с путями и компонентом для рендера
export const pages = [
{
label: "",

View File

@ -1,125 +0,0 @@
import { SubmitHandler, useForm } from 'react-hook-form';
import RoleService from '../../services/RoleService';
import { Box, Button, Modal, Select, TextField, Typography } from '@mui/material';
import { ICompany } from '../../interfaces/documents';
import { useCompanies } from '../../hooks/swrHooks';
interface Props {
open: boolean;
setOpen: (state: boolean) => void;
}
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: 2,
p: 4,
display: "flex",
flexDirection: "column",
gap: "8px"
}
export default function CreateCompanyModal({
open,
setOpen
}: Props) {
const { companies } = useCompanies()
const { register, handleSubmit, formState: { errors } } = useForm<ICompany>({
defaultValues: {
name: '',
fullname: '',
description: '',
}
})
const onSubmit: SubmitHandler<ICompany> = async (data) => {
try {
await RoleService.createRole(data)
} catch (error) {
console.error(error)
}
}
return (
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={style}>
<Typography variant="h6" component="h6" gutterBottom>
Создание компании
</Typography>
<TextField
fullWidth
margin="normal"
label="Наименование"
required
{...register('name', { required: 'Наименование обязательно' })}
error={!!errors.name}
helperText={errors.name?.message}
/>
<TextField
fullWidth
margin="normal"
label="Полное наименование"
required
{...register('fullname', { required: 'Полное наименование обязательно' })}
error={!!errors.fullname}
helperText={errors.fullname?.message}
/>
<TextField
fullWidth
margin="normal"
label="Описание"
{...register('description')}
error={!!errors.description}
helperText={errors.description?.message}
/>
{companies}
<Select
label="owner_id"
{...register('owner_id', { required: '' })}
error={!!errors.owner_id}
>
{/* {companies &&
companies.map((item, index) => {
<MenuItem>
{index}
</MenuItem>
})
} */}
</Select>
<Box sx={{
display: "flex",
justifyContent: "space-between",
gap: "8px"
}}>
<Button type="submit" variant="contained" color="primary">
Добавить роль
</Button>
<Button type="button" variant="outlined" color="primary" onClick={() => setOpen(false)}>
Отмена
</Button>
</Box>
</Box>
</form>
</Modal>
)
}

View File

@ -1,106 +0,0 @@
import { SubmitHandler, useForm } from 'react-hook-form';
import RoleService from '../../services/RoleService';
import { Box, Button, Modal, TextField, Typography } from '@mui/material';
import { ICompany } from '../../interfaces/documents';
interface Props {
open: boolean;
setOpen: (state: boolean) => void;
}
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: 2,
p: 4,
display: "flex",
flexDirection: "column",
gap: "8px"
}
export default function CreateDepartmentModal({
open,
setOpen
}: Props) {
const { register, handleSubmit, formState: { errors } } = useForm<ICompany>({
defaultValues: {
name: '',
fullname: '',
description: '',
}
})
const onSubmit: SubmitHandler<ICompany> = async (data) => {
try {
await RoleService.createRole(data)
} catch (error) {
console.error(error)
}
}
return (
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={style}>
<Typography variant="h6" component="h6" gutterBottom>
Создание компании
</Typography>
<TextField
fullWidth
margin="normal"
label="Наименование"
required
{...register('name', { required: 'Наименование обязательно' })}
error={!!errors.name}
helperText={errors.name?.message}
/>
<TextField
fullWidth
margin="normal"
label="Полное наименование"
required
{...register('fullname', { required: 'Полное наименование обязательно' })}
error={!!errors.fullname}
helperText={errors.fullname?.message}
/>
<TextField
fullWidth
margin="normal"
label="Описание"
{...register('description')}
error={!!errors.description}
helperText={errors.description?.message}
/>
<Box sx={{
display: "flex",
justifyContent: "space-between",
gap: "8px"
}}>
<Button type="submit" variant="contained" color="primary">
Добавить роль
</Button>
<Button type="button" variant="outlined" color="primary" onClick={() => setOpen(false)}>
Отмена
</Button>
</Box>
</Box>
</form>
</Modal>
)
}

View File

@ -1,7 +0,0 @@
function CreateFromGridColModal() {
return (
<div>CreateFromGridColModal</div>
)
}
export default CreateFromGridColModal

View File

@ -1,94 +0,0 @@
import { SubmitHandler, useForm } from 'react-hook-form';
import { IRoleCreate } from '../../interfaces/role';
import RoleService from '../../services/RoleService';
import { Box, Button, Modal, TextField, Typography } from '@mui/material';
interface Props {
open: boolean;
setOpen: (state: boolean) => void;
}
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: 2,
p: 4,
display: "flex",
flexDirection: "column",
gap: "8px"
}
export default function CreateRoleModal({
open,
setOpen
}: Props) {
const { register, handleSubmit, formState: { errors } } = useForm<IRoleCreate>({
defaultValues: {
name: '',
description: ''
}
})
const onSubmit: SubmitHandler<IRoleCreate> = async (data) => {
try {
await RoleService.createRole(data)
} catch (error) {
console.error(error)
}
}
return (
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={style}>
<Typography variant="h6" component="h6" gutterBottom>
Создание роли
</Typography>
<TextField
fullWidth
margin="normal"
label="Название"
required
{...register('name', { required: 'Название обязательно' })}
error={!!errors.name}
helperText={errors.name?.message}
/>
<TextField
fullWidth
margin="normal"
label="Описание"
{...register('description')}
error={!!errors.description}
helperText={errors.description?.message}
/>
<Box sx={{
display: "flex",
justifyContent: "space-between",
gap: "8px"
}}>
<Button type="submit" variant="contained" color="primary">
Добавить роль
</Button>
<Button type="button" variant="outlined" color="primary" onClick={() => setOpen(false)}>
Отмена
</Button>
</Box>
</Box>
</form>
</Modal>
)
}

View File

@ -1,138 +0,0 @@
import { Box, Button, Modal, TextField, Typography } from '@mui/material'
import { SubmitHandler, useForm } from 'react-hook-form';
import UserService from '../../services/UserService';
import { IUserCreate } from '../../interfaces/user';
interface Props {
open: boolean;
setOpen: (state: boolean) => void;
}
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: 2,
p: 4,
display: "flex",
flexDirection: "column",
gap: "8px"
}
export default function CreateUserModal({
open,
setOpen,
}: Props) {
const { register, handleSubmit, formState: { errors } } = useForm<IUserCreate>({
defaultValues: {
email: '',
login: '',
phone: '',
name: '',
surname: '',
is_active: true,
password: '',
}
})
const onSubmit: SubmitHandler<IUserCreate> = async (data) => {
try {
await UserService.createUser(data)
} catch (error) {
console.error(error)
}
}
return (
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={style}>
<Typography variant="h6" component="h6" gutterBottom>
Создание пользователя
</Typography>
<TextField
fullWidth
margin="normal"
label="Email"
required
{...register('email', { required: 'Email обязателен' })}
error={!!errors.email}
helperText={errors.email?.message}
/>
<TextField
fullWidth
margin="normal"
label="Логин"
required
{...register('login', { required: 'Логин обязателен' })}
error={!!errors.login}
helperText={errors.login?.message}
/>
<TextField
fullWidth
margin="normal"
label="Телефон"
{...register('phone')}
error={!!errors.phone}
helperText={errors.phone?.message}
/>
<TextField
fullWidth
margin="normal"
label="Имя"
{...register('name')}
error={!!errors.name}
helperText={errors.name?.message}
/>
<TextField
fullWidth
margin="normal"
label="Фамилия"
{...register('surname')}
error={!!errors.surname}
helperText={errors.surname?.message}
/>
<TextField
fullWidth
margin="normal"
type="password"
label="Пароль"
required
{...register('password', { required: 'Пароль обязателен' })}
error={!!errors.password}
helperText={errors.password?.message}
/>
<Box sx={{
display: "flex",
justifyContent: "space-between",
gap: "8px"
}}>
<Button type="submit" variant="contained" color="primary">
Добавить пользователя
</Button>
<Button type="button" variant="outlined" color="primary" onClick={() => setOpen(false)}>
Отмена
</Button>
</Box>
</Box>
</form>
</Modal>
)
}

View File

@ -0,0 +1,108 @@
import { Box, Button, Modal, TextField, Typography } from '@mui/material';
import { SubmitHandler, useForm } from 'react-hook-form';
import { CreateField } from '../../interfaces/create';
interface Props {
title?: string;
open: boolean;
setOpen: (state: boolean) => void;
submitHandler?: any;
fields: CreateField[];
submitButtonText?: string;
mutateHandler?: any;
}
const style = {
position: 'absolute',
top: '50%',
left: '50%',
transform: 'translate(-50%, -50%)',
width: 400,
bgcolor: 'background.paper',
boxShadow: 24,
borderRadius: 2,
p: 4,
display: "flex",
flexDirection: "column",
gap: "8px"
}
function ModalCreate({
title = '',
open,
setOpen,
submitHandler,
fields,
submitButtonText = 'Сохранить',
mutateHandler
}: Props) {
const getDefaultValues = (fields: CreateField[]) => {
let result: { [key: string]: string | boolean } = {}
fields.forEach((field: CreateField) => {
result[field.key] = field.defaultValue
})
return result
}
const { register, handleSubmit, formState: { errors } } = useForm({
defaultValues: getDefaultValues(fields)
})
const onSubmit: SubmitHandler<any> = async (data) => {
try {
await submitHandler?.(data).then(() => {
mutateHandler?.()
})
} catch (error) {
console.error(error)
}
}
return (
<Modal
open={open}
onClose={() => setOpen(false)}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description"
>
<form onSubmit={handleSubmit(onSubmit)}>
<Box sx={style}>
<Typography variant="h6" component="h6" gutterBottom>
{title}
</Typography>
{fields.map((field: CreateField) => {
return (
<TextField
key={field.key}
fullWidth
margin='normal'
label={field.headerName || field.key.charAt(0).toUpperCase() + field.key.slice(1)}
required={field.required || false}
{...register(field.key, { required: `${field.key} обязателен` })}
error={!!errors[field.key]}
/>
)
})}
<Box sx={{
display: "flex",
justifyContent: "space-between",
gap: "8px"
}}>
<Button type="submit" variant="contained" color="primary">
{submitButtonText}
</Button>
<Button type="button" variant="outlined" color="primary" onClick={() => setOpen(false)}>
Отмена
</Button>
</Box>
</Box>
</form>
</Modal>
)
}
export default ModalCreate

View File

@ -0,0 +1,20 @@
export interface CreateFieldTypes {
string: 'string';
number: 'number';
date: 'date';
dateTime: 'dateTime';
boolean: 'boolean';
singleSelect: 'singleSelect';
actions: 'actions';
custom: 'custom';
}
export type CreateFieldType = CreateFieldTypes[keyof CreateFieldTypes]
export interface CreateField {
key: string;
headerName?: string;
type: CreateFieldType;
required?: boolean;
defaultValue?: any;
}

View File

@ -2,13 +2,20 @@ import { useState } from 'react'
import { Box, Button, CircularProgress } from '@mui/material'
import { DataGrid, GridColDef } from '@mui/x-data-grid'
import { useRoles } from '../hooks/swrHooks'
import CreateRoleModal from '../components/modals/CreateRoleModal'
import { CreateField } from '../interfaces/create'
import ModalCreate from '../components/modals/ModalCreate'
import RoleService from '../services/RoleService'
export default function Roles() {
const { roles, isError, isLoading } = useRoles()
const [open, setOpen] = useState(false)
const createFields: CreateField[] = [
{ key: 'name', headerName: 'Название', type: 'string', required: true, defaultValue: '' },
{ key: 'description', headerName: 'Описание', type: 'string', required: false, defaultValue: '' },
]
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID', type: "number", width: 70 },
{ field: 'name', headerName: 'Название', width: 90, editable: true },
@ -30,9 +37,12 @@ export default function Roles() {
Добавить роль
</Button>
<CreateRoleModal
<ModalCreate
open={open}
setOpen={setOpen}
fields={createFields}
submitHandler={RoleService.createRole}
title="Создание роли"
/>
<DataGrid

View File

@ -3,7 +3,6 @@ import { DataGrid, GridColDef } from "@mui/x-data-grid"
import { useRoles, useUsers } from "../hooks/swrHooks"
import { IRole } from "../interfaces/role"
import { useState } from "react"
import CreateUserModal from "../components/modals/CreateUserModal"
export default function Settings() {
const { users, isError, isLoading } = useUsers()
@ -50,11 +49,6 @@ export default function Settings() {
Добавить пользователя
</Button>
<CreateUserModal
open={open}
setOpen={setOpen}
/>
<DataGrid
autoHeight
style={{ width: "100%" }}

View File

@ -3,7 +3,9 @@ import { DataGrid, GridColDef } from "@mui/x-data-grid"
import { useRoles, useUsers } from "../hooks/swrHooks"
import { IRole } from "../interfaces/role"
import { useState } from "react"
import CreateUserModal from "../components/modals/CreateUserModal"
import { CreateField } from "../interfaces/create"
import ModalCreate from "../components/modals/ModalCreate"
import UserService from "../services/UserService"
export default function Users() {
const { users, isError, isLoading } = useUsers()
@ -12,6 +14,15 @@ export default function Users() {
const [open, setOpen] = useState(false)
const createFields: CreateField[] = [
{ key: 'email', headerName: 'E-mail', type: 'string', required: true, defaultValue: '' },
{ key: 'login', headerName: 'Логин', type: 'string', required: true, defaultValue: '' },
{ key: 'phone', headerName: 'Телефон', type: 'string', required: false, defaultValue: '' },
{ key: 'name', headerName: 'Имя', type: 'string', required: true, defaultValue: '' },
{ key: 'surname', headerName: 'Фамилия', type: 'string', required: true, defaultValue: '' },
{ key: 'password', headerName: 'Пароль', type: 'string', required: true, defaultValue: '' },
]
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID', type: "number", width: 70 },
{ field: 'email', headerName: 'Email', width: 130, editable: true },
@ -45,9 +56,12 @@ export default function Users() {
Добавить пользователя
</Button>
<CreateUserModal
<ModalCreate
open={open}
setOpen={setOpen}
fields={createFields}
submitHandler={UserService.createUser}
title="Создание пользователя"
/>
<DataGrid