This commit is contained in:
cracklesparkle
2024-07-18 11:48:56 +09:00
parent 4283bd20bb
commit cf3fda43e4
20 changed files with 259 additions and 340 deletions

View File

@ -20,6 +20,7 @@
"@mui/material": "^5.15.20",
"@mui/x-charts": "^7.8.0",
"@mui/x-data-grid": "^7.7.1",
"@uidotdev/usehooks": "^2.4.1",
"autoprefixer": "^10.4.19",
"axios": "^1.7.2",
"file-type": "^19.0.0",
@ -3897,6 +3898,18 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@uidotdev/usehooks": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz",
"integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==",
"engines": {
"node": ">=16"
},
"peerDependencies": {
"react": ">=18.0.0",
"react-dom": ">=18.0.0"
}
},
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",

View File

@ -22,6 +22,7 @@
"@mui/material": "^5.15.20",
"@mui/x-charts": "^7.8.0",
"@mui/x-data-grid": "^7.7.1",
"@uidotdev/usehooks": "^2.4.1",
"autoprefixer": "^10.4.19",
"axios": "^1.7.2",
"file-type": "^19.0.0",

View File

@ -1,5 +1,5 @@
import { Box, Chip, Divider, Paper, Typography } from '@mui/material'
import React, { PropsWithChildren, ReactElement, ReactNode } from 'react'
import { Divider, Paper, Typography } from '@mui/material'
import { PropsWithChildren } from 'react'
interface CardInfoProps extends PropsWithChildren {
label: string;

View File

@ -1,7 +1,5 @@
import { Cloud } from '@mui/icons-material';
import { Chip, SvgIconTypeMap } from '@mui/material'
import { OverridableComponent } from '@mui/material/OverridableComponent';
import React, { ReactElement } from 'react'
import { Chip } from '@mui/material'
import { ReactElement } from 'react'
interface CardInfoChipProps {
status: boolean;

View File

@ -1,6 +1,4 @@
import { Box, Typography } from '@mui/material'
import React from 'react'
interface CardInfoLabelProps {
label: string;
value: string | number;

View File

@ -1,79 +0,0 @@
import { Autocomplete, CircularProgress, TextField } from '@mui/material'
import React, { Fragment, useEffect, useState } from 'react'
interface DataGridCellAutocompleteProps {
selectedOption: any;
setSelectedOption: any;
isLoading: boolean;
setDebouncedSearch: any;
options: any;
setOptions: any;
}
export default function DataGridCellAutocomplete({
selectedOption,
setSelectedOption,
isLoading,
setDebouncedSearch,
options,
setOptions
}: DataGridCellAutocompleteProps) {
const [open, setOpen] = useState(false)
const [search, setSearch] = useState<string | null>("")
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedSearch(search)
}, 500)
return () => {
clearTimeout(handler)
}
}, [search])
const handleInputChange = (value: string) => {
setSearch(value)
}
const handleOptionChange = (value: any | null) => {
setSelectedOption(value)
}
return (
<Autocomplete
sx={{ flexGrow: '1' }}
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: any, value: any) => option.name === value.name}
getOptionLabel={(option: any) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Район"
variant='standard'
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
)
}

View File

@ -3,8 +3,9 @@ import { IServer } from '../interfaces/servers'
import { useServerIps } from '../hooks/swrHooks'
import FullFeaturedCrudGrid from './TableEditable'
import { GridColDef } from '@mui/x-data-grid'
import { AxiosResponse } from 'axios'
function ServerData({ id, name, region_id }: IServer) {
function ServerData({ id }: IServer) {
const { serverIps } = useServerIps(id, 0, 10)
const serverIpsColumns: GridColDef[] = [
@ -24,9 +25,16 @@ function ServerData({ id, name, region_id }: IServer) {
columns={serverIpsColumns}
actions
onRowClick={(params, event, details) => {
console.log(params.id, event, details)
//setCurrentServerData(params.row)
//setServerDataOpen(true)
}}
onSave={undefined}
onDelete={function (data: any): Promise<AxiosResponse<any, any>> {
console.log(data)
throw new Error('Function not implemented.')
}}
loading={false}
/>
}
</Box>

View File

@ -1,7 +1,7 @@
import { AppBar, Autocomplete, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material'
import React, { Fragment, useEffect, useState } from 'react'
import { Fragment, useEffect, useState } from 'react'
import { IRegion } from '../interfaces/fuel'
import { useHardwares, useRegions, useServerIps, useServers } from '../hooks/swrHooks'
import { useHardwares, useServers } from '../hooks/swrHooks'
import FullFeaturedCrudGrid from './TableEditable'
import ServerService from '../services/ServersService'
import { GridColDef } from '@mui/x-data-grid'
@ -95,41 +95,37 @@ export default function ServerHardware() {
:
hardwares &&
<FullFeaturedCrudGrid
autoComplete={
<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
label="Сервер"
size='small'
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
}
autoComplete={<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
label="Сервер"
size='small'
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}} />
)} />}
onSave={(id: any) => {
console.log(id)
}}
@ -140,8 +136,7 @@ export default function ServerHardware() {
onRowClick={(params, event, details) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
/>
}} loading={false} />
}
</>
)

View File

@ -1,7 +1,7 @@
import { AppBar, Autocomplete, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material'
import React, { Fragment, useEffect, useState } from 'react'
import { Fragment, useEffect, useState } from 'react'
import { IRegion } from '../interfaces/fuel'
import { useRegions, useServerIps, useServers } from '../hooks/swrHooks'
import { useServerIps, useServers } from '../hooks/swrHooks'
import FullFeaturedCrudGrid from './TableEditable'
import ServerService from '../services/ServersService'
import { GridColDef } from '@mui/x-data-grid'
@ -93,41 +93,37 @@ export default function ServerIpsView() {
:
serverIps &&
<FullFeaturedCrudGrid
autoComplete={
<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Сервер"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
}
autoComplete={<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Сервер"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}} />
)} />}
onSave={(id: any) => {
console.log(id)
}}
@ -138,8 +134,7 @@ export default function ServerIpsView() {
onRowClick={(params, event, details) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
/>
}} loading={false} />
}
</>
)

View File

@ -1,34 +1,26 @@
import { AppBar, Autocomplete, CircularProgress, Dialog, IconButton, TextField, Toolbar } from '@mui/material'
import React, { Fragment, useEffect, useState } from 'react'
import { Fragment, useEffect, useState } from 'react'
import { IRegion } from '../interfaces/fuel'
import { useHardwares, useRegions, useServerIps, useServers, useStorages } from '../hooks/swrHooks'
import { useHardwares, useStorages } from '../hooks/swrHooks'
import FullFeaturedCrudGrid from './TableEditable'
import ServerService from '../services/ServersService'
import { GridColDef } from '@mui/x-data-grid'
import { Close } from '@mui/icons-material'
import ServerData from './ServerData'
import { useDebounce } from '@uidotdev/usehooks'
export default function ServerStorage() {
const [open, setOpen] = useState(false)
const [options, setOptions] = useState<IRegion[]>([])
const [search, setSearch] = useState<string | null>("")
const [debouncedSearch, setDebouncedSearch] = useState<string | null>("")
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
const { hardwares, isLoading } = useHardwares()
const debouncedSearch = useDebounce(search, 500)
const [serverDataOpen, setServerDataOpen] = useState(false)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedSearch(search)
}, 500)
return () => {
clearTimeout(handler)
}
}, [search])
useEffect(() => {
if (hardwares) {
setOptions([...hardwares])
@ -92,41 +84,37 @@ export default function ServerStorage() {
:
storages &&
<FullFeaturedCrudGrid
autoComplete={
<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Hardware"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
}
autoComplete={<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Hardware"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}} />
)} />}
onSave={(id: any) => {
console.log(id)
}}
@ -138,6 +126,7 @@ export default function ServerStorage() {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
loading={false}
/>
}
</>

View File

@ -1,5 +1,5 @@
import { AppBar, Autocomplete, Box, Chip, CircularProgress, Dialog, Divider, Grid, IconButton, Paper, TextField, Toolbar, Typography } from '@mui/material'
import React, { Fragment, useEffect, useState } from 'react'
import { AppBar, Autocomplete, Box, CircularProgress, Dialog, Grid, IconButton, TextField, Toolbar } from '@mui/material'
import { Fragment, useEffect, useState } from 'react'
import { IRegion } from '../interfaces/fuel'
import { useRegions, useServers, useServersInfo } from '../hooks/swrHooks'
import FullFeaturedCrudGrid from './TableEditable'
@ -11,47 +11,30 @@ import { IServersInfo } from '../interfaces/servers'
import CardInfo from './CardInfo/CardInfo'
import CardInfoLabel from './CardInfo/CardInfoLabel'
import CardInfoChip from './CardInfo/CardInfoChip'
import DataGridCellAutocomplete from './DataGridCellAutocomplete'
import { useDebounce } from '@uidotdev/usehooks'
export default function ServersView() {
const [open, setOpen] = useState(false)
const [editOpen, setEditOpen] = useState(false)
const [options, setOptions] = useState<IRegion[]>([])
const [search, setSearch] = useState<string | null>("")
const [debouncedSearch, setDebouncedSearch] = useState<string | null>("")
//const [debouncedSearch, setDebouncedSearch] = useState<string | null>("")
const debouncedSearch = useDebounce(search, 500)
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
const { regions, isLoading } = useRegions(10, 1, debouncedSearch)
const { serversInfo } = useServersInfo(selectedOption?.id)
const [serverDataOpen, setServerDataOpen] = useState(false)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedSearch(search)
}, 500)
return () => {
clearTimeout(handler)
}
}, [search])
useEffect(() => {
if (regions) {
setOptions([...regions])
}
}, [regions])
const handleInputChange = (value: string) => {
setSearch(value)
}
const handleOptionChange = (value: IRegion | null) => {
setSelectedOption(value)
}
const { servers, isLoading: serversLoading } = useServers(selectedOption?.id, 0, 10)
const serversColumns: GridColDef[] = [
@ -60,16 +43,40 @@ export default function ServersView() {
{
field: 'region_id',
editable: true,
renderCell: (params) => (
<div>
{params.value}
</div>
),
renderEditCell: (params: GridRenderCellParams) => (
<DataGridCellAutocomplete
selectedOption={params.value}
setSelectedOption={(value: any) => {
<Autocomplete
sx={{ display: 'flex', flexGrow: '1' }}
onInputChange={(_, value) => setSearch(value)}
onChange={(_, value) => {
params.value = value
}}
isLoading={isLoading}
setDebouncedSearch={setDebouncedSearch}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
setOptions={setOptions}
loading={isLoading}
value={params.value}
renderInput={(params) => (
<TextField
{...params}
size='small'
variant='standard'
label="Район"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
),
width: 200
@ -131,59 +138,47 @@ export default function ServersView() {
</Box>
}
{serversLoading ?
<CircularProgress />
:
servers &&
<FullFeaturedCrudGrid
autoComplete={
<Autocomplete
open={open}
onOpen={() => {
setOpen(true)
}}
onClose={() => {
setOpen(false)
}}
onInputChange={(_, value) => handleInputChange(value)}
onChange={(_, value) => handleOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.name === value.name}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Район"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
}
onSave={(id: any) => {
console.log(id)
}}
onDelete={ServerService.removeServer}
initialRows={servers}
columns={serversColumns}
actions
onRowClick={(params, event, details) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
/>
}
<FullFeaturedCrudGrid
loading={serversLoading}
autoComplete={
<Autocomplete
onInputChange={(_, value) => setSearch(value)}
onChange={(_, value) => setSelectedOption(value)}
isOptionEqualToValue={(option: IRegion, value: IRegion) => option.id === value.id}
getOptionLabel={(option: IRegion) => option.name ? option.name : ""}
options={options}
loading={isLoading}
value={selectedOption}
renderInput={(params) => (
<TextField
{...params}
size='small'
label="Район"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
}
onSave={(id: any) => {
console.log(id)
}}
onDelete={ServerService.removeServer}
initialRows={servers}
columns={serversColumns}
actions
onRowClick={(params, event, details) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
/>
</>
)
}

View File

@ -1,4 +1,4 @@
import * as React from 'react';
import { useEffect, useState } from 'react';
import Box from '@mui/material/Box';
import Button from '@mui/material/Button';
import AddIcon from '@mui/icons-material/Add';
@ -19,12 +19,8 @@ import {
GridRowModel,
GridRowEditStopReasons,
GridSlots,
GridRowProps,
GridRow,
useGridApiContext,
} from '@mui/x-data-grid';
import { AxiosResponse } from 'axios';
import { Autocomplete } from '@mui/material';
interface EditToolbarProps {
setRows: (newRows: (oldRows: GridRowsProp) => GridRowsProp) => void;
@ -90,6 +86,7 @@ interface DataGridProps {
onSave: any;
onDelete: (data: any) => Promise<AxiosResponse<any, any>>;
autoComplete?: React.ReactElement | null;
loading: boolean;
}
export default function FullFeaturedCrudGrid({
@ -99,10 +96,11 @@ export default function FullFeaturedCrudGrid({
onRowClick,
onSave,
onDelete,
autoComplete
autoComplete,
loading
}: DataGridProps) {
const [rows, setRows] = React.useState(initialRows);
const [rowModesModel, setRowModesModel] = React.useState<GridRowModesModel>({});
const [rows, setRows] = useState(initialRows);
const [rowModesModel, setRowModesModel] = useState<GridRowModesModel>({});
const handleRowEditStop: GridEventListener<'rowEditStop'> = (params, event) => {
if (params.reason === GridRowEditStopReasons.rowFocusOut) {
@ -147,6 +145,12 @@ export default function FullFeaturedCrudGrid({
setRowModesModel(newRowModesModel);
};
useEffect(() => {
if (initialRows) {
setRows(initialRows)
}
}, [initialRows])
const actionColumns: GridColDef[] = [
{
field: 'actions',
@ -210,7 +214,8 @@ export default function FullFeaturedCrudGrid({
}}
>
<DataGrid
rows={rows}
loading={loading}
rows={rows || []}
columns={actions ? [...columns, ...actionColumns] : columns}
editMode="row"
rowModesModel={rowModesModel}

View File

@ -184,12 +184,12 @@ export function useBoilers(limit?: number, page?: number, search?: string) {
// Servers
export function useServers(region_id?: number, offset?: number, limit?: number) {
export function useServers(region_id?: number | null, offset?: number, limit?: number) {
const { data, error, isLoading } = useSWR(
region_id ? `/api/servers?region_id=${region_id}&offset=${offset || 0}&limit=${limit || 10}` : `/api/servers?offset=${offset || 0}&limit=${limit || 10}`,
(url: string) => fetcher(url, BASE_URL.servers),
{
revalidateOnFocus: false
revalidateOnFocus: false,
}
)

View File

@ -11,7 +11,6 @@ import Divider from '@mui/material/Divider';
import IconButton from '@mui/material/IconButton';
import Container from '@mui/material/Container';
import MenuIcon from '@mui/icons-material/Menu';
import { Api, Assignment, Cloud, Dashboard, Factory, Home, People, Shield, Storage, } from '@mui/icons-material';
import { colors, ListItem, ListItemButton, ListItemIcon, ListItemText, } from '@mui/material';
import { Outlet, useNavigate } from 'react-router-dom';
import { UserData } from '../interfaces/auth';

View File

@ -9,7 +9,7 @@ import { createTheme } from '@mui/material'
import { ruRU } from '@mui/material/locale'
import { getDarkMode, usePrefStore } from "./store/preferences.ts";
const darkTheme = createTheme(
const mainTheme = createTheme(
{
typography: {
fontFamily: [
@ -28,6 +28,11 @@ const darkTheme = createTheme(
}
}
},
}
)
const darkTheme = createTheme(
{
palette: {
mode: "dark",
primary: { main: '#1976d2' },
@ -38,23 +43,6 @@ const darkTheme = createTheme(
const lightTheme = createTheme(
{
typography: {
fontFamily: [
'Inter'
].join(',')
},
components: {
MuiButtonBase: {
defaultProps: {
//disableRipple: true,
}
},
MuiButtonGroup: {
defaultProps: {
//disableRipple: true,
}
}
},
palette: {
mode: "light",
primary: { main: '#1976d2' },
@ -82,7 +70,7 @@ function ThemedApp() {
}, [])
return (
<ThemeProvider theme={prefStore.darkMode ? darkTheme : lightTheme}>
<ThemeProvider theme={prefStore.darkMode ? { ...mainTheme, ...darkTheme } : { ...mainTheme, ...lightTheme }}>
<App />
</ThemeProvider>
)

View File

@ -1,6 +1,6 @@
import { Box, Typography } from '@mui/material'
import { DataGrid, GridColDef } from '@mui/x-data-grid'
import React, { useEffect, useState } from 'react'
import { useEffect, useState } from 'react'
import { IBoiler } from '../interfaces/fuel'
import { useBoilers } from '../hooks/swrHooks'

View File

@ -9,6 +9,7 @@ export default function Servers() {
const [currentTab, setCurrentTab] = useState(0)
const handleTabChange = (event: React.SyntheticEvent, newValue: number) => {
console.log(event)
setCurrentTab(newValue);
}

View File

@ -10,7 +10,7 @@ const config: AxiosRequestConfig = {
}
export default class AuthService {
static async login(data: FormData) {
static async login(data: URLSearchParams) {
return await axiosInstance.post(`/auth/login`, data, config)
}

View File

@ -5,10 +5,13 @@
],
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
@ -16,13 +19,18 @@
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
"include": [
"src"
],
"references": [
{
"path": "./tsconfig.node.json"
}
]
}

View File

@ -1706,6 +1706,11 @@
"@typescript-eslint/types" "7.13.0"
eslint-visitor-keys "^3.4.3"
"@uidotdev/usehooks@^2.4.1":
version "2.4.1"
resolved "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz"
integrity sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==
"@ungap/structured-clone@^1.2.0":
version "1.2.0"
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz"
@ -4167,7 +4172,7 @@ randomfill@^1.0.3:
randombytes "^2.0.5"
safe-buffer "^5.1.0"
"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", react-dom@^18.2.0, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0:
"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom@^17.0.0 || ^18.0.0", react-dom@^18.2.0, react-dom@>=16.6.0, react-dom@>=16.8, react-dom@>=16.8.0, react-dom@>=18.0.0:
version "18.3.1"
resolved "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz"
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
@ -4220,7 +4225,7 @@ react-transition-group@^4.4.5:
loose-envify "^1.4.0"
prop-types "^15.6.2"
"react@^16.11.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", react@^18.2.0, react@^18.3.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0:
"react@^16.11.0 || ^17.0.0 || ^18.0.0", "react@^16.8.0 || ^17 || ^18 || ^19", "react@^16.8.0 || ^17.0.0 || ^18.0.0", "react@^17.0.0 || ^18.0.0", react@^18.2.0, react@^18.3.1, react@>=16.6.0, react@>=16.8, react@>=16.8.0, react@>=18.0.0:
version "18.3.1"
resolved "https://registry.npmjs.org/react/-/react-18.3.1.tgz"
integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==