diff --git a/frontend_reactjs/package-lock.json b/frontend_reactjs/package-lock.json index 49c1c3b..b4adc0f 100644 --- a/frontend_reactjs/package-lock.json +++ b/frontend_reactjs/package-lock.json @@ -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", diff --git a/frontend_reactjs/package.json b/frontend_reactjs/package.json index 3b55bdd..df05058 100644 --- a/frontend_reactjs/package.json +++ b/frontend_reactjs/package.json @@ -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", diff --git a/frontend_reactjs/src/components/AccountMenu.tsx b/frontend_reactjs/src/components/AccountMenu.tsx index d558ea0..c204649 100644 --- a/frontend_reactjs/src/components/AccountMenu.tsx +++ b/frontend_reactjs/src/components/AccountMenu.tsx @@ -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,')`, + left: 12, + }, + '&::after': { + backgroundImage: `url('data:image/svg+xml;utf8,')`, + 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 ( @@ -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' }} > + { + console.log() + }}> + { + setDarkMode(e.target.checked) + }} /> + Тема + + + Настройки + { logout() diff --git a/frontend_reactjs/src/hooks/swrHooks.ts b/frontend_reactjs/src/hooks/swrHooks.ts index 7b00b7a..0dfd365 100644 --- a/frontend_reactjs/src/hooks/swrHooks.ts +++ b/frontend_reactjs/src/hooks/swrHooks.ts @@ -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 diff --git a/frontend_reactjs/src/interfaces/fuel.ts b/frontend_reactjs/src/interfaces/fuel.ts new file mode 100644 index 0000000..bfc814f --- /dev/null +++ b/frontend_reactjs/src/interfaces/fuel.ts @@ -0,0 +1,4 @@ +export interface IRegion { + id: number; + name: string; +} \ No newline at end of file diff --git a/frontend_reactjs/src/interfaces/preferences.ts b/frontend_reactjs/src/interfaces/preferences.ts new file mode 100644 index 0000000..62adc40 --- /dev/null +++ b/frontend_reactjs/src/interfaces/preferences.ts @@ -0,0 +1,3 @@ +export interface PreferencesState { + darkMode: boolean; +} \ No newline at end of file diff --git a/frontend_reactjs/src/main.tsx b/frontend_reactjs/src/main.tsx index 21916d7..ca9fe4d 100644 --- a/frontend_reactjs/src/main.tsx +++ b/frontend_reactjs/src/main.tsx @@ -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: { diff --git a/frontend_reactjs/src/pages/ApiTest.tsx b/frontend_reactjs/src/pages/ApiTest.tsx index bcd8db2..34450f4 100644 --- a/frontend_reactjs/src/pages/ApiTest.tsx +++ b/frontend_reactjs/src/pages/ApiTest.tsx @@ -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(null) + const [open, setOpen] = useState(false) + const [options, setOptions] = useState([]) + const [search, setSearch] = useState(null) + const [debouncedSearch, setDebouncedSearch] = useState("") + const [selectedOption, setSelectedOption] = useState(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 ( - <> - - - - + + + + + Get servers + + + { + 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) => ( + + {isLoading ? : null} + {params.InputProps.endAdornment} + + ) + }} + /> + )} + /> + + {serversLoading ? + + : + servers && + + } + + + ) } \ No newline at end of file diff --git a/frontend_reactjs/src/store/auth.ts b/frontend_reactjs/src/store/auth.ts index 2e07a82..e5af9b1 100644 --- a/frontend_reactjs/src/store/auth.ts +++ b/frontend_reactjs/src/store/auth.ts @@ -79,5 +79,5 @@ export { refreshToken, initAuth, login, - logout + logout, } \ No newline at end of file diff --git a/frontend_reactjs/src/store/preferences.ts b/frontend_reactjs/src/store/preferences.ts new file mode 100644 index 0000000..81e1c0f --- /dev/null +++ b/frontend_reactjs/src/store/preferences.ts @@ -0,0 +1,21 @@ +import { create } from 'zustand'; +import { PreferencesState } from '../interfaces/preferences'; + +export const usePrefStore = create((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 +} \ No newline at end of file diff --git a/frontend_reactjs/yarn.lock b/frontend_reactjs/yarn.lock index 89d0664..cedd0ba 100644 --- a/frontend_reactjs/yarn.lock +++ b/frontend_reactjs/yarn.lock @@ -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"