|
|
@ -1,60 +1,113 @@ |
|
|
|
import { useState } from "react" |
|
|
|
import { Box, Button } from "@mui/material" |
|
|
|
import { Fragment, useEffect, useState } from "react" |
|
|
|
import { Autocomplete, Box, Button, CircularProgress, IconButton, TextField } from "@mui/material" |
|
|
|
import axiosInstance from "../http/axiosInstance" |
|
|
|
import { DataGrid } from "@mui/x-data-grid" |
|
|
|
import { BASE_URL } from "../constants" |
|
|
|
import { useCities, useReport, useReportExport } from "../hooks/swrHooks" |
|
|
|
import { useDebounce } from "@uidotdev/usehooks" |
|
|
|
import { ICity } from "../interfaces/fuel" |
|
|
|
import { Update } from "@mui/icons-material" |
|
|
|
import { mutate } from "swr" |
|
|
|
|
|
|
|
export default function Reports() { |
|
|
|
const [state, setState] = useState(null) |
|
|
|
const [download, setDownload] = useState(false) |
|
|
|
|
|
|
|
const fetch = async () => { |
|
|
|
await axiosInstance.get(`/info/reports/0?to_export=true`, { |
|
|
|
responseType: 'blob', |
|
|
|
baseURL: BASE_URL.info |
|
|
|
}).then(response => { |
|
|
|
const url = window.URL.createObjectURL(response.data) |
|
|
|
const [options, setOptions] = useState<ICity[]>([]) |
|
|
|
const [search, setSearch] = useState<string | null>("") |
|
|
|
const debouncedSearch = useDebounce(search, 500) |
|
|
|
const [selectedOption, setSelectedOption] = useState<ICity | null>(null) |
|
|
|
const { cities, isLoading } = useCities(10, 1, debouncedSearch) |
|
|
|
|
|
|
|
const { report, isLoading: reportLoading } = useReport(selectedOption?.id) |
|
|
|
|
|
|
|
const { reportExported } = useReportExport(selectedOption?.id, download) |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
if (cities) { |
|
|
|
setOptions([...cities]) |
|
|
|
} |
|
|
|
}, [cities]) |
|
|
|
|
|
|
|
const refreshReport = async () => { |
|
|
|
mutate(`/info/reports/${selectedOption?.id}?to_export=false`) |
|
|
|
} |
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
if (selectedOption && reportExported && download) { |
|
|
|
const url = window.URL.createObjectURL(reportExported) |
|
|
|
const link = document.createElement('a') |
|
|
|
link.href = url |
|
|
|
link.setAttribute('download', 'report.xlsx') |
|
|
|
document.body.appendChild(link); |
|
|
|
link.click(); |
|
|
|
link.remove(); |
|
|
|
}) |
|
|
|
setDownload(false) |
|
|
|
} |
|
|
|
}, [selectedOption, reportExported, download]) |
|
|
|
|
|
|
|
const fetchBlob = async () => { |
|
|
|
await axiosInstance.get(`/info/reports/0`).then(response => { |
|
|
|
setState(JSON.parse(response.data)) |
|
|
|
}) |
|
|
|
const exportReport = async () => { |
|
|
|
setDownload(true) |
|
|
|
} |
|
|
|
|
|
|
|
return ( |
|
|
|
<> |
|
|
|
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> |
|
|
|
<Box> |
|
|
|
<Button onClick={() => fetchBlob()}> |
|
|
|
Получить отчет |
|
|
|
</Button> |
|
|
|
<Box sx={{ display: 'flex', gap: '16px' }}> |
|
|
|
<Autocomplete |
|
|
|
fullWidth |
|
|
|
onInputChange={(_, value) => setSearch(value)} |
|
|
|
onChange={(_, value) => setSelectedOption(value)} |
|
|
|
isOptionEqualToValue={(option: ICity, value: ICity) => option.id === value.id} |
|
|
|
getOptionLabel={(option: ICity) => 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> |
|
|
|
) |
|
|
|
}} |
|
|
|
/> |
|
|
|
)} |
|
|
|
/> |
|
|
|
|
|
|
|
<Button onClick={() => fetch()}> |
|
|
|
<IconButton onClick={() => refreshReport()}> |
|
|
|
<Update /> |
|
|
|
</IconButton> |
|
|
|
|
|
|
|
<Button onClick={() => exportReport()}> |
|
|
|
Экспорт |
|
|
|
</Button> |
|
|
|
</Box> |
|
|
|
|
|
|
|
{state && |
|
|
|
<DataGrid |
|
|
|
autoHeight |
|
|
|
style={{ width: "100%" }} |
|
|
|
rows={[...new Set(Object.keys(state).flatMap(key => Object.keys(state[key])))].map(id => { |
|
|
|
loading={reportLoading} |
|
|
|
rows={ |
|
|
|
report ? |
|
|
|
[...new Set(Object.keys(report).flatMap(key => Object.keys(report[key])))].map(id => { |
|
|
|
const row: any = { id: Number(id) }; |
|
|
|
Object.keys(state).forEach(key => { |
|
|
|
row[key] = state[key][id]; |
|
|
|
Object.keys(report).forEach(key => { |
|
|
|
row[key] = report[key][id]; |
|
|
|
}); |
|
|
|
return row; |
|
|
|
})} |
|
|
|
}) |
|
|
|
: |
|
|
|
[] |
|
|
|
} |
|
|
|
columns={[ |
|
|
|
{ field: 'id', headerName: '№', width: 70 }, |
|
|
|
...Object.keys(state).map(key => ({ |
|
|
|
...Object.keys(report).map(key => ({ |
|
|
|
field: key, |
|
|
|
headerName: key.charAt(0).toUpperCase() + key.slice(1), |
|
|
|
width: 150 |
|
|
@ -76,7 +129,6 @@ export default function Reports() { |
|
|
|
onProcessRowUpdateError={() => { |
|
|
|
}} |
|
|
|
/> |
|
|
|
} |
|
|
|
</Box> |
|
|
|
</> |
|
|
|
) |