import classes from './RepoList.module.css'; import React, { useState, useEffect } from 'react'; import { IconPlus, IconSortAscendingLetters, IconSortDescendingLetters, IconSortAscending2, IconSortDescending2, IconDatabase, IconX, IconClock, IconCalendarUp, IconCalendarDown, IconSortAscendingSmallBig, IconSortDescendingSmallBig, IconSortDescending2Filled, } from '@tabler/icons-react'; import { useRouter } from 'next/router'; import Link from 'next/link'; import useSWR, { useSWRConfig } from 'swr'; import { ToastContainer, ToastOptions, toast } from 'react-toastify'; import 'react-toastify/dist/ReactToastify.css'; import Repo from '~/Components/Repo/Repo'; import RepoManage from '../RepoManage/RepoManage'; import ShimmerRepoList from '~/Components/UI/ShimmerRepoList/ShimmerRepoList'; import { Repository, WizardEnvType, Optional } from '~/types'; type SortOption = | 'alias-asc' | 'alias-desc' | 'status-true' | 'status-false' | 'storage-used-asc' | 'storage-used-desc' | 'last-save-asc' | 'last-save-desc'; export default function RepoList() { const router = useRouter(); const { mutate } = useSWRConfig(); const [displayRepoAdd, setDisplayRepoAdd] = useState(false); const [displayRepoEdit, setDisplayRepoEdit] = useState(false); const [wizardEnv, setWizardEnv] = useState>(); const [sortOption, setSortOption] = useState(() => { const savedSort = localStorage.getItem('repoSort'); return (savedSort as SortOption) || 'alias-asc'; }); const [searchQuery, setSearchQuery] = useState(() => { const savedSearch = localStorage.getItem('repoSearch'); return savedSearch || ''; }); const toastOptions: ToastOptions = { position: 'top-right', autoClose: 8000, hideProgressBar: false, closeOnClick: true, pauseOnHover: true, draggable: true, progress: undefined, }; useEffect(() => { // eslint-disable-next-line react-hooks/set-state-in-effect setDisplayRepoAdd(router.pathname === '/manage-repo/add'); setDisplayRepoEdit(router.pathname.startsWith('/manage-repo/edit')); const fetchWizardEnv = async () => { try { const response = await fetch('/api/v1/account/wizard-env'); const data: WizardEnvType = await response.json(); setWizardEnv(data); } catch (error) { console.log('Fetching wizard env error'); } }; fetchWizardEnv(); }, [router.pathname]); const fetcher = async (url: string) => await fetch(url).then((res) => res.json()); const { data, error } = useSWR('/api/v1/repositories', fetcher); if (!data) { mutate('/api/v1/repositories'); return ; } if (error || data.status == 500) { toast.error('Error loading repositories.', toastOptions); return ; } const handleSortChange = (option: SortOption) => { setSortOption(option); localStorage.setItem('repoSort', option); }; const handleSearchChange = (e: React.ChangeEvent) => { const query = e.target.value; setSearchQuery(query); localStorage.setItem('repoSearch', query); }; const getSortedRepoList = () => { let repoList = [...data.repoList]; // Filter if (searchQuery) { repoList = repoList.filter((repo) => `${repo.alias} ${repo.comment} ${repo.repositoryName}` .toLowerCase() .includes(searchQuery.toLowerCase()) ); } // Sort switch (sortOption) { case 'alias-asc': return repoList.sort((a, b) => a.alias.localeCompare(b.alias)); case 'alias-desc': return repoList.sort((a, b) => b.alias.localeCompare(a.alias)); case 'status-true': return repoList.sort((a, b) => Number(b.status) - Number(a.status)); case 'status-false': return repoList.sort((a, b) => Number(a.status) - Number(b.status)); case 'storage-used-asc': return repoList.sort((a, b) => { const aRatio = a.storageSize ? a.storageUsed / a.storageSize : 0; const bRatio = b.storageSize ? b.storageUsed / b.storageSize : 0; return aRatio - bRatio; }); case 'storage-used-desc': return repoList.sort((a, b) => { const aRatio = a.storageSize ? a.storageUsed / a.storageSize : 0; const bRatio = b.storageSize ? b.storageUsed / b.storageSize : 0; return bRatio - aRatio; }); case 'last-save-asc': return repoList.sort((a, b) => { const aDate = a.lastSave ? new Date(a.lastSave).getTime() : 0; const bDate = b.lastSave ? new Date(b.lastSave).getTime() : 0; return aDate - bDate; }); case 'last-save-desc': return repoList.sort((a, b) => { const aDate = a.lastSave ? new Date(a.lastSave).getTime() : 0; const bDate = b.lastSave ? new Date(b.lastSave).getTime() : 0; return bDate - aDate; }); default: return repoList; } }; const manageRepoAddHandler = () => router.replace('/manage-repo/add'); const manageRepoEditHandler = (id: number) => router.replace('/manage-repo/edit/' + id); const closeRepoManageBoxHandler = () => router.replace('/'); const displayBlur = () => displayRepoAdd || displayRepoEdit ? classes.containerBlur : classes.container; const renderRepoList = getSortedRepoList().map((repo: Repository) => ( manageRepoEditHandler(repo.id)} wizardEnv={wizardEnv} /> )); return ( <>
Add a repository
{searchQuery && ( )}
handleSortChange('alias-asc')} title='Alias A-Z' /> handleSortChange('alias-desc')} title='Alias Z-A' /> handleSortChange('status-true')} title='Status OK → KO' /> handleSortChange('status-false')} title='Status KO → OK' /> handleSortChange('last-save-desc')} title='Last save (recent → old)' /> handleSortChange('last-save-asc')} title='Last save (old → recent)' /> handleSortChange('storage-used-asc')} title='Storage usage % low → high' /> handleSortChange('storage-used-desc')} title='Storage usage % high → low' />
{renderRepoList}
{displayRepoAdd && ( )} {displayRepoEdit && ( )} ); }