forked from VinokurovVE/tests
Rename interfaces, AppBar changes
This commit is contained in:
@ -10,7 +10,7 @@ import ApiTest from "./pages/ApiTest"
|
|||||||
import SignUp from "./pages/auth/SignUp"
|
import SignUp from "./pages/auth/SignUp"
|
||||||
import { initAuth, useAuthStore } from "./store/auth"
|
import { initAuth, useAuthStore } from "./store/auth"
|
||||||
import { useEffect, useState } from "react"
|
import { useEffect, useState } from "react"
|
||||||
import { CircularProgress } from "@mui/material"
|
import { Box, CircularProgress, Container } from "@mui/material"
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const auth = useAuthStore()
|
const auth = useAuthStore()
|
||||||
@ -33,7 +33,10 @@ function App() {
|
|||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<>
|
<Box sx={{
|
||||||
|
width: "100%",
|
||||||
|
height: "100vh"
|
||||||
|
}}>
|
||||||
<Router>
|
<Router>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route element={<MainLayout />}>
|
<Route element={<MainLayout />}>
|
||||||
@ -50,7 +53,7 @@ function App() {
|
|||||||
</Route>
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
</Router>
|
</Router>
|
||||||
</>
|
</Box>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,7 @@ import MenuItem from '@mui/material/MenuItem';
|
|||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
import Divider from '@mui/material/Divider';
|
import Divider from '@mui/material/Divider';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
import PersonAdd from '@mui/icons-material/PersonAdd';
|
|
||||||
import Settings from '@mui/icons-material/Settings';
|
import Settings from '@mui/icons-material/Settings';
|
||||||
import Logout from '@mui/icons-material/Logout';
|
import Logout from '@mui/icons-material/Logout';
|
||||||
|
|
||||||
|
@ -9,7 +9,8 @@ export default function DataTable(props: Props) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<DataGrid
|
<DataGrid
|
||||||
style={{ width: "100%", height: "100%" }}
|
autoHeight
|
||||||
|
style={{ width: "100%" }}
|
||||||
rows={props.rows}
|
rows={props.rows}
|
||||||
columns={props.columns}
|
columns={props.columns}
|
||||||
initialState={{
|
initialState={{
|
||||||
@ -19,9 +20,16 @@ export default function DataTable(props: Props) {
|
|||||||
}}
|
}}
|
||||||
pageSizeOptions={[10, 20, 50, 100]}
|
pageSizeOptions={[10, 20, 50, 100]}
|
||||||
checkboxSelection
|
checkboxSelection
|
||||||
|
|
||||||
disableRowSelectionOnClick
|
disableRowSelectionOnClick
|
||||||
|
|
||||||
|
processRowUpdate={(updatedRow, originalRow) => {
|
||||||
|
console.log(updatedRow)
|
||||||
|
return updatedRow
|
||||||
|
}}
|
||||||
|
|
||||||
|
onProcessRowUpdateError={(error)=>{
|
||||||
|
console.log(error)
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
@ -1,11 +1,97 @@
|
|||||||
import React from 'react'
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
|
import { IRoleCreate } from '../../interfaces/role';
|
||||||
|
import { AxiosResponse } from 'axios';
|
||||||
|
import { ApiResponse } from '../../interfaces/auth';
|
||||||
|
import RoleService from '../../services/RoleService';
|
||||||
|
import { Box, Button, Modal, TextField, Typography } from '@mui/material';
|
||||||
|
|
||||||
const CreateRoleModal = () => {
|
interface Props {
|
||||||
return (
|
open: boolean;
|
||||||
<div>
|
setOpen: (state: boolean) => void;
|
||||||
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CreateRoleModal
|
const style = {
|
||||||
|
position: 'absolute' as '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 {
|
||||||
|
const response: AxiosResponse<ApiResponse> = await RoleService.createRole(data)
|
||||||
|
console.log(response.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",
|
||||||
|
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>
|
||||||
|
)
|
||||||
|
}
|
@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
|
|||||||
import { SubmitHandler, useForm } from 'react-hook-form';
|
import { SubmitHandler, useForm } from 'react-hook-form';
|
||||||
import { ApiResponse } from '../../interfaces/auth';
|
import { ApiResponse } from '../../interfaces/auth';
|
||||||
import UserService from '../../services/UserService';
|
import UserService from '../../services/UserService';
|
||||||
import { CreateUserFormData } from '../../interfaces/user';
|
import { IUserCreate } from '../../interfaces/user';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
@ -29,7 +29,7 @@ export default function CreateUserModal({
|
|||||||
open,
|
open,
|
||||||
setOpen,
|
setOpen,
|
||||||
}: Props) {
|
}: Props) {
|
||||||
const { register, handleSubmit, formState: { errors } } = useForm<CreateUserFormData>({
|
const { register, handleSubmit, formState: { errors } } = useForm<IUserCreate>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
email: '',
|
email: '',
|
||||||
login: '',
|
login: '',
|
||||||
@ -41,7 +41,7 @@ export default function CreateUserModal({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const onSubmit: SubmitHandler<CreateUserFormData> = async (data) => {
|
const onSubmit: SubmitHandler<IUserCreate> = async (data) => {
|
||||||
try {
|
try {
|
||||||
const response: AxiosResponse<ApiResponse> = await UserService.createUser(data)
|
const response: AxiosResponse<ApiResponse> = await UserService.createUser(data)
|
||||||
console.log(response.data)
|
console.log(response.data)
|
||||||
|
@ -16,18 +16,6 @@ export interface UserCreds extends User {
|
|||||||
password: string;
|
password: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export interface Role {
|
|
||||||
name: string;
|
|
||||||
description?: string | null;
|
|
||||||
id: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface RoleCreate {
|
|
||||||
name: string;
|
|
||||||
description?: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AuthState {
|
export interface AuthState {
|
||||||
isAuthenticated: boolean;
|
isAuthenticated: boolean;
|
||||||
token: string | null;
|
token: string | null;
|
||||||
|
10
frontend_reactjs/src/interfaces/role.ts
Normal file
10
frontend_reactjs/src/interfaces/role.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
export interface IRole {
|
||||||
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
|
id: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRoleCreate {
|
||||||
|
name: string;
|
||||||
|
description?: string | null;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
export interface CreateUserFormData {
|
export interface IUserCreate {
|
||||||
email: string;
|
email: string;
|
||||||
login: string;
|
login: string;
|
||||||
phone: string;
|
phone: string;
|
||||||
|
@ -128,7 +128,10 @@ export default function DashboardLayout() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeProvider theme={innerTheme}>
|
<ThemeProvider theme={innerTheme}>
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{
|
||||||
|
display: 'flex',
|
||||||
|
height: "100%"
|
||||||
|
}}>
|
||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AppBar position="absolute" open={open}>
|
<AppBar position="absolute" open={open}>
|
||||||
<Toolbar
|
<Toolbar
|
||||||
@ -143,7 +146,7 @@ export default function DashboardLayout() {
|
|||||||
onClick={toggleDrawer}
|
onClick={toggleDrawer}
|
||||||
sx={{
|
sx={{
|
||||||
marginRight: '36px',
|
marginRight: '36px',
|
||||||
...(open && { display: 'none' }),
|
//...(open && { display: 'none' }),
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<MenuIcon />
|
<MenuIcon />
|
||||||
@ -172,7 +175,7 @@ export default function DashboardLayout() {
|
|||||||
</Badge>
|
</Badge>
|
||||||
</IconButton> */}
|
</IconButton> */}
|
||||||
|
|
||||||
<AccountMenu/>
|
<AccountMenu />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
@ -187,16 +190,18 @@ export default function DashboardLayout() {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Box display="flex" justifyContent={'space-between'} width={"100%"}>
|
<Box display="flex" justifyContent={'space-between'} width={"100%"}>
|
||||||
<IconButton onClick={toggleDrawer}>
|
|
||||||
<ChevronLeftIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<List component="nav">
|
<List component="nav">
|
||||||
{pages.map((item, index) => (
|
{pages.map((item, index) => (
|
||||||
<ListItem key={index} disablePadding>
|
<ListItem
|
||||||
|
key={index}
|
||||||
|
disablePadding
|
||||||
|
>
|
||||||
<ListItemButton
|
<ListItemButton
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
navigate(item.path)
|
navigate(item.path)
|
||||||
@ -207,7 +212,9 @@ export default function DashboardLayout() {
|
|||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
{item.icon}
|
{item.icon}
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary={item.label} />
|
<ListItemText
|
||||||
|
primary={item.label}
|
||||||
|
/>
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
))}
|
||||||
|
@ -1,32 +1,24 @@
|
|||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import RoleCard from '../components/RoleCard'
|
import { Box, Button, CircularProgress } from '@mui/material'
|
||||||
import Modal from '../components/Modal'
|
|
||||||
import useDataFetching from '../components/FetchingData'
|
|
||||||
import RoleService from '../services/RoleService'
|
|
||||||
import { Box, Button } from '@mui/material'
|
|
||||||
import DataTable from '../components/DataTable'
|
import DataTable from '../components/DataTable'
|
||||||
import { GridColDef } from '@mui/x-data-grid'
|
import { GridColDef } from '@mui/x-data-grid'
|
||||||
|
import { useRoles } from '../hooks/swrHooks'
|
||||||
|
import CreateRoleModal from '../components/modals/CreateRoleModal'
|
||||||
|
|
||||||
interface IRoleCard {
|
export default function Roles() {
|
||||||
id: number
|
const { roles, isError, isLoading } = useRoles()
|
||||||
name: string
|
|
||||||
description: string
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Props {
|
const [open, setOpen] = useState(false)
|
||||||
showModal: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
function Roles() {
|
|
||||||
const [showModal, setShowModal] = useState<Props>({ showModal: false });
|
|
||||||
const cards = useDataFetching<IRoleCard[]>(`${import.meta.env.VITE_API_AUTH_URL}/auth/roles/`, [])
|
|
||||||
|
|
||||||
const columns: GridColDef[] = [
|
const columns: GridColDef[] = [
|
||||||
{ field: 'id', headerName: 'ID', type: "number", width: 70 },
|
{ field: 'id', headerName: 'ID', type: "number", width: 70 },
|
||||||
{ field: 'name', headerName: 'Название', width: 90 },
|
{ field: 'name', headerName: 'Название', width: 90, editable: true },
|
||||||
{ field: 'description', headerName: 'Описание', width: 90 },
|
{ field: 'description', headerName: 'Описание', width: 90, editable: true },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (isError) return <div>Произошла ошибка при получении данных.</div>
|
||||||
|
if (isLoading) return <CircularProgress />
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box sx={{
|
<Box sx={{
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@ -35,23 +27,16 @@ function Roles() {
|
|||||||
gap: '16px',
|
gap: '16px',
|
||||||
flexGrow: 1
|
flexGrow: 1
|
||||||
}}>
|
}}>
|
||||||
<Button onClick={() => console.log("TODO: Add")}>
|
<Button onClick={() => setOpen(true)}>
|
||||||
Добавить роль
|
Добавить роль
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{cards &&
|
<CreateRoleModal
|
||||||
<DataTable rows={cards} columns={columns} />
|
open={open}
|
||||||
}
|
setOpen={setOpen}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<DataTable rows={roles} columns={columns} />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{cards.length > 0 && cards.map((card, index) => <RoleCard key={index} {...card} />)}
|
|
||||||
<button className='absolute w-0 h-0' onClick={() => setShowModal({ showModal: true })}>+</button>
|
|
||||||
<Modal {...showModal} />
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Roles
|
|
@ -2,7 +2,7 @@ import { Box, Button, CircularProgress } from "@mui/material"
|
|||||||
import DataTable from "../components/DataTable"
|
import DataTable from "../components/DataTable"
|
||||||
import { GridColDef } from "@mui/x-data-grid"
|
import { GridColDef } from "@mui/x-data-grid"
|
||||||
import { useRoles, useUsers } from "../hooks/swrHooks"
|
import { useRoles, useUsers } from "../hooks/swrHooks"
|
||||||
import { Role } from "../interfaces/auth"
|
import { IRole } from "../interfaces/role"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import CreateUserModal from "../components/modals/CreateUserModal"
|
import CreateUserModal from "../components/modals/CreateUserModal"
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ export default function Users() {
|
|||||||
headerName: 'Роль',
|
headerName: 'Роль',
|
||||||
valueGetter: (value, row) => {
|
valueGetter: (value, row) => {
|
||||||
if (roles) {
|
if (roles) {
|
||||||
const roleName = roles.find((role: Role) => role.id === value).name
|
const roleName = roles.find((role: IRole) => role.id === value).name
|
||||||
return roleName
|
return roleName
|
||||||
} else {
|
} else {
|
||||||
return value
|
return value
|
||||||
|
@ -3,10 +3,10 @@ import { TextField, Button, Container, Typography, Box } from '@mui/material';
|
|||||||
import { AxiosResponse } from 'axios';
|
import { AxiosResponse } from 'axios';
|
||||||
import { ApiResponse } from '../../interfaces/auth';
|
import { ApiResponse } from '../../interfaces/auth';
|
||||||
import UserService from '../../services/UserService';
|
import UserService from '../../services/UserService';
|
||||||
import { CreateUserFormData } from '../../interfaces/user';
|
import { IUserCreate } from '../../interfaces/user';
|
||||||
|
|
||||||
const SignUp = () => {
|
const SignUp = () => {
|
||||||
const { register, handleSubmit, formState: { errors } } = useForm<CreateUserFormData>({
|
const { register, handleSubmit, formState: { errors } } = useForm<IUserCreate>({
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
email: '',
|
email: '',
|
||||||
login: '',
|
login: '',
|
||||||
@ -19,7 +19,7 @@ const SignUp = () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
const onSubmit: SubmitHandler<CreateUserFormData> = async (data) => {
|
const onSubmit: SubmitHandler<IUserCreate> = async (data) => {
|
||||||
try {
|
try {
|
||||||
const response: AxiosResponse<ApiResponse> = await UserService.createUser(data)
|
const response: AxiosResponse<ApiResponse> = await UserService.createUser(data)
|
||||||
console.log('Успешная регистрация:', response.data);
|
console.log('Успешная регистрация:', response.data);
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
import axiosInstance from "../http/axiosInstance";
|
import axiosInstance from "../http/axiosInstance";
|
||||||
import { Role, RoleCreate } from "../interfaces/auth";
|
import { IRoleCreate } from "../interfaces/role";
|
||||||
|
|
||||||
export default class RoleService {
|
export default class RoleService {
|
||||||
static async getRoles() {
|
static async getRoles() {
|
||||||
return await axiosInstance.get(`/auth/roles`)
|
return await axiosInstance.get(`/auth/roles`)
|
||||||
}
|
}
|
||||||
|
|
||||||
static async createRole(data: RoleCreate) {
|
static async createRole(data: IRoleCreate) {
|
||||||
return await axiosInstance.post(`/auth/roles/`, data)
|
return await axiosInstance.post(`/auth/roles/`, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user