Tables, cards, (servers)

This commit is contained in:
cracklesparkle
2024-07-12 17:44:44 +09:00
parent f9de1124c3
commit 416e2e39b5
9 changed files with 802 additions and 86 deletions

View File

@ -0,0 +1,275 @@
import { AppBar, Autocomplete, Box, Chip, CircularProgress, Dialog, Divider, Grid, IconButton, Paper, TextField, Toolbar, Typography, colors } from "@mui/material"
import { useBoilers, useCities, useRegions, useServers, useServersInfo } from "../hooks/swrHooks"
import { Fragment, useEffect, useState } from "react"
import { IBoiler, ICity, IRegion } from "../interfaces/fuel"
import { DataGrid, GridColDef } from "@mui/x-data-grid"
import ServerData from "../components/ServerData"
import { IServer, IServersInfo } from "../interfaces/servers"
import { Close, Cloud, CloudOff, Storage } from "@mui/icons-material"
import { BarChart } from "@mui/x-charts"
import FullFeaturedCrudGrid from "../components/TableEditable"
export default function Servers() {
const [open, setOpen] = useState(false)
const [options, setOptions] = useState<IRegion[]>([])
const [search, setSearch] = useState<string | null>(null)
const [debouncedSearch, setDebouncedSearch] = useState<string | null>("")
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
const { regions, isLoading } = useRegions(10, 1, debouncedSearch)
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 [citiesOpen, setCitiesOpen] = useState(false)
const [citiesPage, setCitiesPage] = useState(1)
const [citiesSearch, setCitiesSearch] = useState('')
const [debouncedCitySearch, setDebouncedCitySearch] = useState('')
const { cities, isLoading: citiesLoading } = useCities(10, citiesPage, debouncedCitySearch)
const [citiesOptions, setCitiesOptions] = useState<ICity[]>([])
const [selectedCityOption, setSelectedCityOption] = useState<ICity | null>(null)
const handleCityInputChange = (value: string) => {
setCitiesSearch(value)
}
const handleCityOptionChange = (value: ICity | null) => {
setSelectedCityOption(value)
}
useEffect(() => {
if (cities) {
setCitiesOptions([...cities])
}
}, [cities])
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedCitySearch(citiesSearch)
}, 500)
return () => {
clearTimeout(handler)
}
}, [citiesSearch])
useEffect(() => {
setCitiesPage(1)
setCitiesSearch("")
}, [])
const { servers, isLoading: serversLoading } = useServers(selectedOption?.id, 0, 10)
const serversColumns: GridColDef[] = [
//{ field: 'id', headerName: 'ID', type: "number" },
{ field: 'name', headerName: 'Название', type: "string", editable: true },
]
const [serverDataOpen, setServerDataOpen] = useState(false)
const [currentServerData, setCurrentServerData] = useState<any | null>(null)
const { serversInfo } = useServersInfo(selectedOption?.id)
return (
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px', height: '100%' }}>
<Dialog
fullScreen
open={serverDataOpen}
onClose={() => {
setServerDataOpen(false)
}}
aria-labelledby="modal-modal-title"
aria-describedby="modal-modal-description">
<AppBar sx={{ position: 'sticky' }}>
<Toolbar>
<IconButton
edge="start"
color="inherit"
onClick={() => {
setServerDataOpen(false)
}}
aria-label="close"
>
<Close />
</IconButton>
</Toolbar>
</AppBar>
{currentServerData &&
<ServerData
id={currentServerData?.id}
region_id={currentServerData?.region_id}
name={currentServerData?.name}
/>
}
</Dialog>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px', height: '100%', p: '16px' }}>
<Typography variant='h6' fontWeight='600'>
Servers by region
</Typography>
<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="Район"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
<Autocomplete
hidden
open={citiesOpen}
onOpen={() => {
setCitiesOpen(true)
}}
onClose={() => {
setCitiesOpen(false)
}}
onInputChange={(_, value) => handleCityInputChange(value)}
onChange={(_, value) => handleCityOptionChange(value)}
filterOptions={(x) => x}
isOptionEqualToValue={(option: ICity, value: ICity) => option.name === value.name}
getOptionLabel={(option: ICity) => option.name ? option.name : ""}
options={citiesOptions}
loading={citiesLoading}
value={selectedCityOption}
renderInput={(params) => (
<TextField
{...params}
label="Город"
InputProps={{
...params.InputProps,
endAdornment: (
<Fragment>
{citiesLoading ? <CircularProgress color="inherit" size={20} /> : null}
{params.InputProps.endAdornment}
</Fragment>
)
}}
/>
)}
/>
{servers &&
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px', height: '100%' }}>
<Typography variant='h6' fontWeight='600'>
Информация
</Typography>
{serversInfo &&
<Grid container spacing={{ xs: 2, md: 3 }} columns={{ xs: 1, sm: 1, md: 2, lg: 3, xl: 4 }}>
{serversInfo.map((serverInfo: IServersInfo) => (
<Grid key={`si-${serverInfo.id}`} item xs={1} sm={1} md={1}>
<Paper sx={{ display: 'flex', flexDirection: 'column', gap: '16px', p: '16px' }}>
<Typography fontWeight={600}>
{serverInfo.name}
</Typography>
<Divider />
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography>
Количество IP:
</Typography>
<Typography variant="h6" fontWeight={600}>
{serverInfo.IPs_count}
</Typography>
</Box>
<Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<Typography>
Количество серверов:
</Typography>
<Typography variant="h6" fontWeight={600}>
{serverInfo.servers_count}
</Typography>
</Box>
<Chip
icon={serverInfo.status === "Online" ? <Cloud /> : serverInfo.status === "Offline" ? <CloudOff /> : <CloudOff />}
variant="outlined"
label={serverInfo.status}
color={serverInfo.status === "Online" ? "success" : serverInfo.status === "Offline" ? "error" : "error"}
/>
</Paper>
</Grid>
))}
</Grid>
}
</Box>
}
{serversLoading ?
<CircularProgress />
:
servers &&
<FullFeaturedCrudGrid
initialRows={servers}
columns={serversColumns}
actions
onRowClick={(params, event, details) => {
setCurrentServerData(params.row)
setServerDataOpen(true)
}}
/>
}
{/* <BarChart
xAxis={[{ scaleType: 'band', data: ['group A', 'group B', 'group C'] }]}
series={[{ data: [4, 3, 5] }, { data: [1, 6, 3] }, { data: [2, 5, 6] }]}
width={500}
height={300}
/> */}
</Box>
</Box>
)
}