Reports: city autocomplete, mutation, refresh

This commit is contained in:
cracklesparkle
2024-07-22 15:51:37 +09:00
parent 748cf89b35
commit ae2213b188
2 changed files with 126 additions and 58 deletions

View File

@ -99,17 +99,33 @@ export function useFileType(fileName?: string | null, file?: Blob | null) {
} }
} }
export function useReport(city_id?: number) { export function useReport(city_id?: number | null) {
const { data, error, isLoading } = useSWR( const { data, error, isLoading } = useSWR(
city_id ? `/info/reports/${city_id}?to_export=false` : null, city_id ? `/info/reports/${city_id}?to_export=false` : null,
fetcher, (url) => fetcher(url, BASE_URL.info),
{ {
revalidateOnFocus: false revalidateOnFocus: false
} }
) )
return { return {
report: JSON.parse(data), report: data ? JSON.parse(data) : [],
isLoading,
isError: error
}
}
export function useReportExport(city_id?: number | null, to_export?: boolean) {
const { data, error, isLoading } = useSWR(
city_id && to_export ? `/info/reports/${city_id}?to_export=${to_export}` : null,
(url) => fetcher(url, BASE_URL.info, 'blob'),
{
revalidateOnFocus: false
}
)
return {
reportExported: data ? data : null,
isLoading, isLoading,
isError: error isError: error
} }
@ -150,7 +166,7 @@ export function useRegions(limit?: number, page?: number, search?: string | null
} }
} }
export function useCities(limit?: number, page?: number, search?: string) { export function useCities(limit?: number, page?: number, search?: string | null) {
const { data, error, isLoading } = useSWR( const { data, error, isLoading } = useSWR(
`/general/cities?limit=${limit || 10}&page=${page || 1}${search ? `&search=${search}` : ''}`, `/general/cities?limit=${limit || 10}&page=${page || 1}${search ? `&search=${search}` : ''}`,
(url) => fetcher(url, BASE_URL.fuel), (url) => fetcher(url, BASE_URL.fuel),

View File

@ -1,82 +1,134 @@
import { useState } from "react" import { Fragment, useEffect, useState } from "react"
import { Box, Button } from "@mui/material" import { Autocomplete, Box, Button, CircularProgress, IconButton, TextField } from "@mui/material"
import axiosInstance from "../http/axiosInstance" import axiosInstance from "../http/axiosInstance"
import { DataGrid } from "@mui/x-data-grid" import { DataGrid } from "@mui/x-data-grid"
import { BASE_URL } from "../constants" 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() { export default function Reports() {
const [state, setState] = useState(null) const [download, setDownload] = useState(false)
const fetch = async () => { const [options, setOptions] = useState<ICity[]>([])
await axiosInstance.get(`/info/reports/0?to_export=true`, { const [search, setSearch] = useState<string | null>("")
responseType: 'blob', const debouncedSearch = useDebounce(search, 500)
baseURL: BASE_URL.info const [selectedOption, setSelectedOption] = useState<ICity | null>(null)
}).then(response => { const { cities, isLoading } = useCities(10, 1, debouncedSearch)
const url = window.URL.createObjectURL(response.data)
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') const link = document.createElement('a')
link.href = url link.href = url
link.setAttribute('download', 'report.xlsx') link.setAttribute('download', 'report.xlsx')
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
link.remove(); link.remove();
}) setDownload(false)
} }
}, [selectedOption, reportExported, download])
const fetchBlob = async () => { const exportReport = async () => {
await axiosInstance.get(`/info/reports/0`).then(response => { setDownload(true)
setState(JSON.parse(response.data))
})
} }
return ( return (
<> <>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px' }}> <Box sx={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
<Box> <Box sx={{ display: 'flex', gap: '16px' }}>
<Button onClick={() => fetchBlob()}> <Autocomplete
Получить отчет fullWidth
</Button> 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> </Button>
</Box> </Box>
{state && <DataGrid
<DataGrid autoHeight
autoHeight style={{ width: "100%" }}
style={{ width: "100%" }} loading={reportLoading}
rows={[...new Set(Object.keys(state).flatMap(key => Object.keys(state[key])))].map(id => { rows={
const row: any = { id: Number(id) }; report ?
Object.keys(state).forEach(key => { [...new Set(Object.keys(report).flatMap(key => Object.keys(report[key])))].map(id => {
row[key] = state[key][id]; const row: any = { id: Number(id) };
}); Object.keys(report).forEach(key => {
return row; row[key] = report[key][id];
})} });
columns={[ return row;
{ field: 'id', headerName: '№', width: 70 }, })
...Object.keys(state).map(key => ({ :
field: key, []
headerName: key.charAt(0).toUpperCase() + key.slice(1), }
width: 150 columns={[
})) { field: 'id', headerName: '№', width: 70 },
]} ...Object.keys(report).map(key => ({
initialState={{ field: key,
pagination: { headerName: key.charAt(0).toUpperCase() + key.slice(1),
paginationModel: { page: 0, pageSize: 10 }, width: 150
}, }))
}} ]}
pageSizeOptions={[10, 20, 50, 100]} initialState={{
checkboxSelection={false} pagination: {
disableRowSelectionOnClick paginationModel: { page: 0, pageSize: 10 },
},
}}
pageSizeOptions={[10, 20, 50, 100]}
checkboxSelection={false}
disableRowSelectionOnClick
processRowUpdate={(updatedRow) => { processRowUpdate={(updatedRow) => {
return updatedRow return updatedRow
}} }}
onProcessRowUpdateError={() => { onProcessRowUpdateError={() => {
}} }}
/> />
}
</Box> </Box>
</> </>
) )