1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-04-06 01:15:28 +02:00
unleash.unleash/frontend/src/component/project/ProjectList/ArchiveProjectList.tsx
2024-08-19 13:33:00 +00:00

170 lines
5.8 KiB
TypeScript

import { type FC, useEffect, useMemo, useState } from 'react';
import { useSearchParams } from 'react-router-dom';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { PageContent } from 'component/common/PageContent/PageContent';
import { PageHeader } from 'component/common/PageHeader/PageHeader';
import ApiError from 'component/common/ApiError/ApiError';
import { styled, useMediaQuery } from '@mui/material';
import theme from 'themes/theme';
import { Search } from 'component/common/Search/Search';
import { ProjectGroup } from './ProjectGroup';
import {
ProjectArchiveCard,
type ProjectArchiveCardProps,
} from '../NewProjectCard/ProjectArchiveCard';
import useProjects from 'hooks/api/getters/useProjects/useProjects';
import { ReviveProjectDialog } from './ReviveProjectDialog/ReviveProjectDialog';
import { DeleteProjectDialogue } from '../Project/DeleteProject/DeleteProjectDialogue';
import { SearchHighlightProvider } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
import { safeRegExp } from '@server/util/escape-regex';
const StyledApiError = styled(ApiError)(({ theme }) => ({
maxWidth: '500px',
marginBottom: theme.spacing(2),
}));
const StyledContainer = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
gap: theme.spacing(4),
}));
type PageQueryType = Partial<Record<'search', string>>;
export const ArchiveProjectList: FC = () => {
const { projects, loading, error, refetch } = useProjects({
archived: true,
});
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'));
const [searchParams, setSearchParams] = useSearchParams();
const [searchValue, setSearchValue] = useState(
searchParams.get('search') || '',
);
const [reviveProject, setReviveProject] = useState<{
isOpen: boolean;
id?: string;
name?: string;
}>({ isOpen: false });
const [deleteProject, setDeleteProject] = useState<{
isOpen: boolean;
id?: string;
name?: string;
}>({ isOpen: false });
useEffect(() => {
const tableState: PageQueryType = {};
if (searchValue) {
tableState.search = searchValue;
}
setSearchParams(tableState, {
replace: true,
});
}, [searchValue, setSearchParams]);
const ProjectCard: FC<
Omit<ProjectArchiveCardProps, 'onRevive' | 'onDelete'>
> = ({ id, ...props }) => (
<ProjectArchiveCard
onRevive={() =>
setReviveProject({
isOpen: true,
id,
name: projects?.find((project) => project.id === id)?.name,
})
}
onDelete={() =>
setDeleteProject({
id,
name: projects?.find((project) => project.id === id)?.name,
isOpen: true,
})
}
id={id}
{...props}
/>
);
const filteredProjects = useMemo(
() =>
searchValue
? projects.filter((project) =>
safeRegExp(searchValue, 'i').test(project.name),
)
: projects,
[projects, searchValue],
);
return (
<PageContent
isLoading={loading}
header={
<PageHeader
title={`Projects archive (${projects.length || 0})`}
actions={
<ConditionallyRender
condition={!isSmallScreen}
show={
<Search
initialValue={searchValue}
onChange={setSearchValue}
/>
}
/>
}
>
<ConditionallyRender
condition={isSmallScreen}
show={
<Search
initialValue={searchValue}
onChange={setSearchValue}
/>
}
/>
</PageHeader>
}
>
<StyledContainer>
<ConditionallyRender
condition={error}
show={() => (
<StyledApiError
onClick={refetch}
text='Error fetching projects'
/>
)}
/>
<SearchHighlightProvider value={searchValue}>
<ProjectGroup
loading={loading}
searchValue={searchValue}
projects={filteredProjects}
placeholder='No archived projects found'
ProjectCardComponent={ProjectCard}
link={false}
/>
</SearchHighlightProvider>
</StyledContainer>
<ReviveProjectDialog
id={reviveProject.id || ''}
name={reviveProject.name || ''}
open={reviveProject.isOpen}
onClose={() =>
setReviveProject((state) => ({ ...state, isOpen: false }))
}
/>
<DeleteProjectDialogue
projectId={deleteProject.id || ''}
projectName={deleteProject.name || ''}
open={deleteProject.isOpen}
onClose={() => {
setDeleteProject((state) => ({ ...state, isOpen: false }));
}}
/>
</PageContent>
);
};