feat(flows): add flow filters

This commit is contained in:
Ali BARIN
2025-03-19 16:13:36 +00:00
parent d00c5e166f
commit 3d060df5bd
10 changed files with 275 additions and 34 deletions

View File

@@ -0,0 +1,121 @@
import { useState } from 'react';
import {
Box,
Button,
FormControl,
InputLabel,
MenuItem,
Select,
Typography,
useMediaQuery,
Collapse,
} from '@mui/material';
import FilterAltIcon from '@mui/icons-material/FilterAlt';
import { useTheme } from '@mui/material/styles';
import Can from 'components/Can';
import useCurrentUserRuleConditions from 'hooks/useCurrentUserRuleConditions';
import useFlowFilters from 'hooks/useFlowFilters';
import useFormatMessage from 'hooks/useFormatMessage';
export default function FlowFilters({ onFilterChange }) {
const theme = useTheme();
const formatMessage = useFormatMessage();
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
const currentUserRuleConditions = useCurrentUserRuleConditions();
const { filters, filterByStatus, filterByOwnership } = useFlowFilters();
const [mobileFiltersOpen, setMobileFiltersOpen] = useState(false);
const currentUserReadFlowsConditions = currentUserRuleConditions(
'read',
'Flow',
);
return (
<Box>
{/* Mobile: Toggle Button for Filters */}
{isMobile && (
<Button
variant="contained"
startIcon={<FilterAltIcon />}
onClick={() => setMobileFiltersOpen((prev) => !prev)}
fullWidth
sx={{ mb: 2 }}
>
{mobileFiltersOpen
? formatMessage('flowFilters.hideFilters')
: formatMessage('flowFilters.showFilters')}
</Button>
)}
{/* Filters Box (Always Visible on Large Screens) */}
<Collapse in={!isMobile || mobileFiltersOpen}>
<Box
sx={{
display: 'flex',
flexDirection: { xs: 'column', md: 'row' },
gap: 2,
mb: 2,
alignItems: { md: 'center' },
}}
>
{/* User Flows Filter */}
{currentUserReadFlowsConditions &&
!currentUserReadFlowsConditions?.isCreator && (
<FormControl
fullWidth
sx={{ maxWidth: { md: 200 } }}
variant="outlined"
>
<InputLabel shrink>
{formatMessage('flowFilters.flowsFilterLabel')}
</InputLabel>
<Select
label={formatMessage('flowFilters.flowsFilterLabel')}
value={filters.onlyOwnedFlows}
displayEmpty
onChange={(e) => filterByOwnership(e.target.value)}
key={filters.onlyOwnedFlows}
>
<MenuItem value={undefined}>
{formatMessage('flowFilters.flowsFilterAllOption')}
</MenuItem>
<MenuItem value={true}>
{formatMessage('flowFilters.flowsFilterOnlyMineOption')}
</MenuItem>
</Select>
</FormControl>
)}
{/* Status Filter */}
<FormControl fullWidth sx={{ maxWidth: { md: 200 } }}>
<InputLabel shrink>
{formatMessage('flowFilters.statusFilterLabel')}
</InputLabel>
<Select
label={formatMessage('flowFilters.statusFilterLabel')}
value={filters.status}
displayEmpty
onChange={(e) => filterByStatus(e.target.value)}
key={filters.status}
>
<MenuItem value={undefined}>
{formatMessage('flowFilters.statusFilterAnyOption')}
</MenuItem>
<MenuItem value="published">
{formatMessage('flowFilters.statusFilterPublishedOption')}
</MenuItem>
<MenuItem value="draft">
{formatMessage('flowFilters.statusFilterDraftOption')}
</MenuItem>
</Select>
</FormControl>
</Box>
</Collapse>
</Box>
);
}

View File

@@ -3,6 +3,7 @@ import { Link, useSearchParams, useNavigate } from 'react-router-dom';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import Card from '@mui/material/Card';
import Typography from '@mui/material/Typography';
import IconButton from '@mui/material/IconButton';
import DeleteIcon from '@mui/icons-material/Delete';
import EditIcon from '@mui/icons-material/Edit';
@@ -23,6 +24,8 @@ import useFormatMessage from 'hooks/useFormatMessage';
import useFolders from 'hooks/useFolders';
import useDeleteFolder from 'hooks/useDeleteFolder';
import useEnqueueSnackbar from 'hooks/useEnqueueSnackbar';
import objectifyUrlSearchParams from 'helpers/objectifyUrlSearchParams';
import useFlowFilters from 'hooks/useFlowFilters';
import { ListItemIcon } from './style';
@@ -35,6 +38,8 @@ export default function Folders() {
const { data: folders } = useFolders();
const enqueueSnackbar = useEnqueueSnackbar();
const { enhanceExistingSearchParams } = useFlowFilters();
const {
mutateAsync: deleteFolder,
error: deleteFolderError,
@@ -53,8 +58,8 @@ export default function Folders() {
(folder) => folder.id === selectedFolderId,
);
const allFlowsFolder = new URLSearchParams().toString();
const unassignedFlowsFolder = new URLSearchParams('folderId=null').toString();
const allFlowsFolder = enhanceExistingSearchParams('folderId', undefined);
const unassignedFlowsFolder = enhanceExistingSearchParams('folderId', 'null');
const allFlowsFolderSelected = selectedFolderId === null;
const unassignedFlowsFolderSelected = selectedFolderId === 'null'; // intendedly stringified
@@ -86,9 +91,7 @@ export default function Folders() {
};
const getFolderSearchParams = (folderId) => {
const searchParams = new URLSearchParams(`folderId=${folderId}`);
return searchParams.toString();
return enhanceExistingSearchParams('folderId', folderId).toString();
};
const generateFolderItem = (folder) => {
@@ -148,10 +151,7 @@ export default function Folders() {
return (
<>
<Box
component={Card}
// sx={{ width: '100%', maxWidth: 360, bgcolor: 'background.paper' }}
>
<Box component={Card}>
<List component="nav" aria-label="static folders">
<ListItemButton
component={Link}