forked from VinokurovVE/tests
Testing: fetch servers by region
This commit is contained in:
6
frontend_reactjs/package-lock.json
generated
6
frontend_reactjs/package-lock.json
generated
@ -11,6 +11,7 @@
|
||||
"-": "^0.0.1",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@fontsource/inter": "^5.0.19",
|
||||
"@fontsource/open-sans": "^5.0.28",
|
||||
"@js-preview/docx": "^1.6.2",
|
||||
"@js-preview/excel": "^1.7.8",
|
||||
@ -2495,6 +2496,11 @@
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz",
|
||||
"integrity": "sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw=="
|
||||
},
|
||||
"node_modules/@fontsource/inter": {
|
||||
"version": "5.0.19",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/inter/-/inter-5.0.19.tgz",
|
||||
"integrity": "sha512-tVU77yjKnsoUotrXGYbbYxmL9nbm/MSo3deZietmf8V2FEDlbi9fvkJHMrYbo7ZsOqR1AYBBqRYmemz4pSE5Mg=="
|
||||
},
|
||||
"node_modules/@fontsource/open-sans": {
|
||||
"version": "5.0.28",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/open-sans/-/open-sans-5.0.28.tgz",
|
||||
|
@ -13,6 +13,7 @@
|
||||
"-": "^0.0.1",
|
||||
"@emotion/react": "^11.11.4",
|
||||
"@emotion/styled": "^11.11.5",
|
||||
"@fontsource/inter": "^5.0.19",
|
||||
"@fontsource/open-sans": "^5.0.28",
|
||||
"@js-preview/docx": "^1.6.2",
|
||||
"@js-preview/excel": "^1.7.8",
|
||||
|
@ -10,8 +10,42 @@ import Tooltip from '@mui/material/Tooltip';
|
||||
import Settings from '@mui/icons-material/Settings';
|
||||
import Logout from '@mui/icons-material/Logout';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { logout } from '../store/auth';
|
||||
import { ListItem } from '@mui/material';
|
||||
import { logout, useAuthStore } from '../store/auth';
|
||||
import { ListItem, Switch, styled } from '@mui/material';
|
||||
import { setDarkMode, usePrefStore } from '../store/preferences';
|
||||
|
||||
const Android12Switch = styled(Switch)(({ theme }) => ({
|
||||
padding: 8,
|
||||
'& .MuiSwitch-track': {
|
||||
borderRadius: 22 / 2,
|
||||
'&::before, &::after': {
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
width: 16,
|
||||
height: 16,
|
||||
},
|
||||
'&::before': {
|
||||
backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 24 24"><path fill="${encodeURIComponent(
|
||||
theme.palette.getContrastText(theme.palette.primary.main),
|
||||
)}" d="M21,7L9,19L3.5,13.5L4.91,12.09L9,16.17L19.59,5.59L21,7Z"/></svg>')`,
|
||||
left: 12,
|
||||
},
|
||||
'&::after': {
|
||||
backgroundImage: `url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 24 24"><path fill="${encodeURIComponent(
|
||||
theme.palette.getContrastText(theme.palette.primary.main),
|
||||
)}" d="M19,13H5V11H19V13Z" /></svg>')`,
|
||||
right: 12,
|
||||
},
|
||||
},
|
||||
'& .MuiSwitch-thumb': {
|
||||
boxShadow: 'none',
|
||||
width: 16,
|
||||
height: 16,
|
||||
margin: 2,
|
||||
},
|
||||
}));
|
||||
|
||||
export default function AccountMenu() {
|
||||
const navigate = useNavigate()
|
||||
@ -26,6 +60,9 @@ export default function AccountMenu() {
|
||||
const handleClose = () => {
|
||||
setAnchorEl(null);
|
||||
};
|
||||
|
||||
const prefStore = usePrefStore()
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', textAlign: 'center' }}>
|
||||
@ -47,7 +84,6 @@ export default function AccountMenu() {
|
||||
id="account-menu"
|
||||
open={open}
|
||||
onClose={handleClose}
|
||||
onClick={handleClose}
|
||||
PaperProps={{
|
||||
elevation: 0,
|
||||
sx: {
|
||||
@ -77,12 +113,25 @@ export default function AccountMenu() {
|
||||
transformOrigin={{ horizontal: 'right', vertical: 'top' }}
|
||||
anchorOrigin={{ horizontal: 'right', vertical: 'bottom' }}
|
||||
>
|
||||
<MenuItem onClick={() => {
|
||||
console.log()
|
||||
}}>
|
||||
<Android12Switch
|
||||
defaultChecked={prefStore.darkMode}
|
||||
onChange={(e) => {
|
||||
setDarkMode(e.target.checked)
|
||||
}} />
|
||||
Тема
|
||||
</MenuItem>
|
||||
|
||||
|
||||
<MenuItem onClick={handleClose}>
|
||||
<ListItemIcon>
|
||||
<Settings fontSize="small" />
|
||||
</ListItemIcon>
|
||||
Настройки
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
logout()
|
||||
|
@ -116,12 +116,12 @@ export function useReport(city_id?: number) {
|
||||
}
|
||||
|
||||
|
||||
// API general
|
||||
// API general (fuel)
|
||||
|
||||
export function useAddress(limit?: number, page?: number) {
|
||||
const { data, error, isLoading } = useSWR(
|
||||
`/general/address?limit=${limit || 10}&page=${page || 1}`,
|
||||
(url) => fetcher(url, import.meta.env.VITE_API_FUEL_URL),
|
||||
(url) => fetcher(url, BASE_URL.fuel),
|
||||
{
|
||||
revalidateOnFocus: false
|
||||
}
|
||||
@ -134,9 +134,41 @@ export function useAddress(limit?: number, page?: number) {
|
||||
}
|
||||
}
|
||||
|
||||
export function useRegions(limit?: number, page?: number, search?: string) {
|
||||
const { data, error, isLoading } = useSWR(
|
||||
`/general/regions?limit=${limit || 10}&page=${page || 1}${search ? `&search=${search}` : ''}`,
|
||||
(url) => fetcher(url, BASE_URL.fuel),
|
||||
{
|
||||
revalidateOnFocus: false
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
regions: data,
|
||||
isLoading,
|
||||
isError: error
|
||||
}
|
||||
}
|
||||
|
||||
export function useCities(limit?: number, page?: number, search?: string) {
|
||||
const { data, error, isLoading } = useSWR(
|
||||
`/general/cities?limit=${limit || 10}&page=${page || 1}${search ? `&search=${search}` : ''}`,
|
||||
(url) => fetcher(url, BASE_URL.fuel),
|
||||
{
|
||||
revalidateOnFocus: false
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
cities: data,
|
||||
isLoading,
|
||||
isError: error
|
||||
}
|
||||
}
|
||||
|
||||
export function useBoilers(limit?: number, page?: number, search?: string) {
|
||||
const { data, error, isLoading } = useSWR(
|
||||
`/general/boilers?limit=${limit || 10}&page=${page || 1}&search=${search || ""}`,
|
||||
`/general/boilers?limit=${limit || 10}&page=${page || 1}${search ? `&search=${search}` : ''}`,
|
||||
(url) => fetcher(url, BASE_URL.fuel),
|
||||
{
|
||||
revalidateOnFocus: false
|
||||
|
4
frontend_reactjs/src/interfaces/fuel.ts
Normal file
4
frontend_reactjs/src/interfaces/fuel.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface IRegion {
|
||||
id: number;
|
||||
name: string;
|
||||
}
|
3
frontend_reactjs/src/interfaces/preferences.ts
Normal file
3
frontend_reactjs/src/interfaces/preferences.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export interface PreferencesState {
|
||||
darkMode: boolean;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import "@fontsource/open-sans";
|
||||
import "@fontsource/inter";
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App.tsx'
|
||||
@ -7,12 +7,13 @@ import { registerSW } from 'virtual:pwa-register'
|
||||
import { ThemeProvider } from '@emotion/react'
|
||||
import { createTheme } from '@mui/material'
|
||||
import { ruRU } from '@mui/material/locale'
|
||||
import { usePrefStore } from "./store/preferences.ts";
|
||||
|
||||
const theme = createTheme(
|
||||
{
|
||||
typography: {
|
||||
fontFamily: [
|
||||
'Open Sans'
|
||||
'Inter'
|
||||
].join(',')
|
||||
},
|
||||
components: {
|
||||
|
@ -1,21 +1,103 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { Button, Typography } from "@mui/material"
|
||||
import { useServers } from "../hooks/swrHooks"
|
||||
import { Autocomplete, Box, Button, CircularProgress, Paper, TextField, Typography } from "@mui/material"
|
||||
import { useBoilers, useCities, useRegions, useServers } from "../hooks/swrHooks"
|
||||
import { Fragment, useEffect, useState } from "react"
|
||||
import { IRegion } from "../interfaces/fuel"
|
||||
import { DataGrid, GridColDef } from "@mui/x-data-grid"
|
||||
|
||||
export default function ApiTest() {
|
||||
const [state, setState] = useState<any>(null)
|
||||
const [open, setOpen] = useState(false)
|
||||
const [options, setOptions] = useState<any>([])
|
||||
const [search, setSearch] = useState<any>(null)
|
||||
const [debouncedSearch, setDebouncedSearch] = useState("")
|
||||
const [selectedOption, setSelectedOption] = useState<IRegion | null>(null)
|
||||
const { regions, isLoading } = useRegions(10, 1, debouncedSearch)
|
||||
|
||||
const { servers } = useServers(32, 0, 10)
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedSearch(search)
|
||||
}, 500)
|
||||
|
||||
return () => {
|
||||
clearTimeout(handler)
|
||||
}
|
||||
}, [search])
|
||||
|
||||
useEffect(() => {
|
||||
if (regions) {
|
||||
setOptions([...regions])
|
||||
}
|
||||
}, [regions])
|
||||
|
||||
const handleInputChange = (event: any, value: any) => {
|
||||
setSearch(value)
|
||||
}
|
||||
|
||||
const handleOptionChange = (event: any, value: any) => {
|
||||
setSelectedOption(value)
|
||||
}
|
||||
|
||||
//const { boilers } = useBoilers(10, 1)
|
||||
//const { cities } = useCities(10, 1)
|
||||
const { servers, isLoading: serversLoading } = useServers(selectedOption?.id, 0, 10)
|
||||
|
||||
const serversColumns: GridColDef[] = [
|
||||
{ field: 'id', headerName: 'ID', type: "number" },
|
||||
{ field: 'name', headerName: 'Название', type: "string" },
|
||||
]
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography>
|
||||
<Button onClick={() => {
|
||||
|
||||
}}>
|
||||
{servers && JSON.stringify(servers)}
|
||||
</Button>
|
||||
</Typography>
|
||||
</>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px', height: '100%' }}>
|
||||
<Paper elevation={1}>
|
||||
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px', height: '100%', p: '16px'}}>
|
||||
<Typography variant='h6' fontWeight='600'>
|
||||
Get servers
|
||||
</Typography>
|
||||
|
||||
<Autocomplete
|
||||
open={open}
|
||||
onOpen={() => {
|
||||
setOpen(true)
|
||||
}}
|
||||
onClose={() => {
|
||||
setOpen(false)
|
||||
}}
|
||||
onInputChange={handleInputChange}
|
||||
onChange={handleOptionChange}
|
||||
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}
|
||||
label="Район"
|
||||
InputProps={{
|
||||
...params.InputProps,
|
||||
endAdornment: (
|
||||
<Fragment>
|
||||
{isLoading ? <CircularProgress color="inherit" size={20} /> : null}
|
||||
{params.InputProps.endAdornment}
|
||||
</Fragment>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
|
||||
{serversLoading ?
|
||||
<CircularProgress />
|
||||
:
|
||||
servers &&
|
||||
<DataGrid
|
||||
rowSelection={false}
|
||||
rows={servers}
|
||||
columns={serversColumns}
|
||||
/>
|
||||
}
|
||||
</Box>
|
||||
</Paper>
|
||||
</Box>
|
||||
)
|
||||
}
|
@ -79,5 +79,5 @@ export {
|
||||
refreshToken,
|
||||
initAuth,
|
||||
login,
|
||||
logout
|
||||
logout,
|
||||
}
|
21
frontend_reactjs/src/store/preferences.ts
Normal file
21
frontend_reactjs/src/store/preferences.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { create } from 'zustand';
|
||||
import { PreferencesState } from '../interfaces/preferences';
|
||||
|
||||
export const usePrefStore = create<PreferencesState>((set, get) => ({
|
||||
darkMode: false
|
||||
}));
|
||||
|
||||
const getDarkMode = () => {
|
||||
const darkMode = localStorage.getItem('darkMode')
|
||||
return darkMode
|
||||
}
|
||||
|
||||
const setDarkMode = (darkMode: boolean) => {
|
||||
localStorage.setItem('darkMode', JSON.stringify(darkMode))
|
||||
usePrefStore.setState(() => ({ darkMode: darkMode }))
|
||||
}
|
||||
|
||||
export {
|
||||
getDarkMode,
|
||||
setDarkMode
|
||||
}
|
@ -1148,6 +1148,11 @@
|
||||
resolved "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.2.tgz"
|
||||
integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw==
|
||||
|
||||
"@fontsource/inter@^5.0.19":
|
||||
version "5.0.19"
|
||||
resolved "https://registry.npmjs.org/@fontsource/inter/-/inter-5.0.19.tgz"
|
||||
integrity sha512-tVU77yjKnsoUotrXGYbbYxmL9nbm/MSo3deZietmf8V2FEDlbi9fvkJHMrYbo7ZsOqR1AYBBqRYmemz4pSE5Mg==
|
||||
|
||||
"@fontsource/open-sans@^5.0.28":
|
||||
version "5.0.28"
|
||||
resolved "https://registry.npmjs.org/@fontsource/open-sans/-/open-sans-5.0.28.tgz"
|
||||
|
Reference in New Issue
Block a user