121 lines
4.6 KiB
TypeScript
121 lines
4.6 KiB
TypeScript
import {useEffect, useState} from "react";
|
|
import '../assets/styles/home.css';
|
|
import {
|
|
Box,
|
|
Divider, Fab,
|
|
TextField,
|
|
ThemeProvider, Typography,
|
|
useTheme
|
|
} from "@mui/material";
|
|
import {getAll} from '~/api';
|
|
import customTheme from "~/assets/mui/themes/home";
|
|
import {BlacklistItem} from "~/classes/blacklistItem";
|
|
import {ResponseError} from "~/classes/responseError";
|
|
import ItemList from "~/components/itemList";
|
|
import ItemDialog from "~/components/itemDialog";
|
|
import OutlinedFlagIcon from '@mui/icons-material/OutlinedFlag';
|
|
import ReportDialog from "~/components/reportDialog";
|
|
|
|
export default function Home() {
|
|
const outerTheme = useTheme();
|
|
|
|
const [searchText, setSearchText] = useState('');
|
|
const [isFetchingList, setIsFetchingList] = useState(false);
|
|
const [blacklistItems, setBlacklistItems] = useState<BlacklistItem[]>([]);
|
|
const [showDialog, setShowDialog] = useState(false);
|
|
const [currentDialogBlacklistItem, setCurrentDialogBlacklistItem] = useState<BlacklistItem|null>(null);
|
|
const [fabIsHovered, setFabIsHovered] = useState(false);
|
|
const [showReportDialog, setReportShowDialog] = useState(false);
|
|
|
|
useEffect(() => {
|
|
let isIgnore = false;
|
|
setIsFetchingList(true);
|
|
getAll(searchText).then((res: BlacklistItem[] | ResponseError | undefined)=> {
|
|
if (!isIgnore) {
|
|
if (res instanceof Array){
|
|
setBlacklistItems(res);
|
|
} else if (res instanceof ResponseError) {
|
|
// TODO error handler
|
|
console.log(res);
|
|
}
|
|
setIsFetchingList(false);
|
|
}
|
|
});
|
|
return () => {
|
|
isIgnore = true; // При следующем изменении someValue старый запрос будет проигнорирован
|
|
};
|
|
}, [searchText, showReportDialog]);
|
|
|
|
function handleSearch(text: string) {
|
|
setSearchText(text);
|
|
}
|
|
|
|
function handleItemClick(item: BlacklistItem){
|
|
setCurrentDialogBlacklistItem(item);
|
|
setShowDialog(true);
|
|
}
|
|
|
|
const handleDialogClose = () => {
|
|
setShowDialog(false);
|
|
};
|
|
|
|
const handleReportDialogOpen = () => {
|
|
setReportShowDialog(true);
|
|
};
|
|
|
|
const handleReportDialogClose = () => {
|
|
setReportShowDialog(false);
|
|
};
|
|
|
|
return (
|
|
<ThemeProvider theme={customTheme(outerTheme)}>
|
|
<div className="bg-dark">
|
|
<div className="search-container">
|
|
<TextField
|
|
id="search-field"
|
|
label="Search"
|
|
variant="outlined"
|
|
value={searchText}
|
|
onChange={(e) => handleSearch(e.target.value)}
|
|
fullWidth
|
|
/>
|
|
</div>
|
|
<div style={{justifyItems: 'center'}}>
|
|
<Divider sx={{marginTop: '10px', marginBottom: '10px'}}/>
|
|
</div>
|
|
<ItemList isFetching={isFetchingList} blacklistItems={blacklistItems} showDialog={handleItemClick}></ItemList>
|
|
<ItemDialog blacklistItem={currentDialogBlacklistItem} open={showDialog} handleClose={handleDialogClose}></ItemDialog>
|
|
<ReportDialog open={showReportDialog} handleClose={handleReportDialogClose}/>
|
|
<Fab
|
|
onClick={() => handleReportDialogOpen()}
|
|
onMouseEnter={() => setFabIsHovered(true)}
|
|
onMouseLeave={() => setFabIsHovered(false)}
|
|
variant={fabIsHovered ? 'extended' : 'circular'}
|
|
sx={{
|
|
position: 'fixed',
|
|
bottom: 16,
|
|
right: 16,
|
|
z-index: 1000,
|
|
width: fabIsHovered ? '160px' : '56px', // Переход между кругом и овалом
|
|
transition: 'width 0.3s ease-in-out',
|
|
overflow: 'hidden',
|
|
}}
|
|
>
|
|
<OutlinedFlagIcon />
|
|
<Box
|
|
sx={{
|
|
opacity: fabIsHovered ? 1 : 0,
|
|
ml: fabIsHovered ? 1 : 0,
|
|
width: fabIsHovered ? 'auto' : 0,
|
|
transition: 'all 0.1s ease-in-out',
|
|
whiteSpace: 'nowrap',
|
|
}}
|
|
>
|
|
<Typography variant="button">{fabIsHovered ? 'Send report' : ''}</Typography>
|
|
</Box>
|
|
</Fab>
|
|
</div>
|
|
</ThemeProvider>
|
|
);
|
|
}
|