import Button from '@app/components/Common/Button'; import Header from '@app/components/Common/Header'; import LoadingSpinner from '@app/components/Common/LoadingSpinner'; import PageTitle from '@app/components/Common/PageTitle'; import Tooltip from '@app/components/Common/Tooltip'; import RequestItem from '@app/components/RequestList/RequestItem'; import { useUpdateQueryParams } from '@app/hooks/useUpdateQueryParams'; import { Permission, useUser } from '@app/hooks/useUser'; import globalMessages from '@app/i18n/globalMessages'; import defineMessages from '@app/utils/defineMessages'; import { ExclamationTriangleIcon } from '@heroicons/react/24/outline'; import { ArrowDownIcon, ArrowUpIcon, Bars3BottomLeftIcon, ChevronLeftIcon, ChevronRightIcon, CircleStackIcon, FunnelIcon, } from '@heroicons/react/24/solid'; import type { RequestResultsResponse } from '@server/interfaces/api/requestInterfaces'; import Link from 'next/link'; import { useRouter } from 'next/router'; import { useEffect, useState } from 'react'; import { useIntl } from 'react-intl'; import useSWR from 'swr'; const messages = defineMessages('components.RequestList', { requests: 'Requests', showallrequests: 'Show All Requests', sortAdded: 'Most Recent', sortModified: 'Last Modified', sortDirection: 'Toggle Sort Direction', unableToConnect: 'Unable to connect to {services}. Some information may be unavailable.', }); enum Filter { ALL = 'all', PENDING = 'pending', APPROVED = 'approved', PROCESSING = 'processing', AVAILABLE = 'available', UNAVAILABLE = 'unavailable', FAILED = 'failed', DELETED = 'deleted', COMPLETED = 'completed', } type Sort = 'added' | 'modified'; type SortDirection = 'asc' | 'desc'; type MediaType = 'all' | 'movie' | 'tv'; const RequestList = () => { const router = useRouter(); const intl = useIntl(); const { user } = useUser({ id: Number(router.query.userId), }); const { user: currentUser, hasPermission } = useUser(); const [currentFilter, setCurrentFilter] = useState(Filter.PENDING); const [currentSort, setCurrentSort] = useState('added'); const [currentMediaType, setCurrentMediaType] = useState('all'); const [currentSortDirection, setCurrentSortDirection] = useState('desc'); const [currentPageSize, setCurrentPageSize] = useState(10); const page = router.query.page ? Number(router.query.page) : 1; const pageIndex = page - 1; const updateQueryParams = useUpdateQueryParams({ page: page.toString() }); const { data, error, mutate: revalidate, } = useSWR( `/api/v1/request?take=${currentPageSize}&skip=${ pageIndex * currentPageSize }&filter=${currentFilter}&mediaType=${currentMediaType}&sort=${currentSort}&sortDirection=${currentSortDirection}${ router.pathname.startsWith('/profile') ? `&requestedBy=${currentUser?.id}` : router.query.userId ? `&requestedBy=${router.query.userId}` : '' }` ); // Restore last set filter values on component mount useEffect(() => { const filterString = window.localStorage.getItem('rl-filter-settings'); if (filterString) { const filterSettings = JSON.parse(filterString); setCurrentFilter(filterSettings.currentFilter); setCurrentSort(filterSettings.currentSort); setCurrentPageSize(filterSettings.currentPageSize); if (['asc', 'desc'].includes(filterSettings.currentSortDirection)) { setCurrentSortDirection(filterSettings.currentSortDirection); } } // If filter value is provided in query, use that instead if (Object.values(Filter).includes(router.query.filter as Filter)) { setCurrentFilter(router.query.filter as Filter); } }, [router.query.filter]); // Set filter values to local storage any time they are changed useEffect(() => { window.localStorage.setItem( 'rl-filter-settings', JSON.stringify({ currentFilter, currentMediaType, currentSort, currentSortDirection, currentPageSize, }) ); }, [ currentFilter, currentMediaType, currentSort, currentSortDirection, currentPageSize, ]); if (!data && !error) { return ; } if (!data) { return ; } const hasNextPage = data.pageInfo.pages > pageIndex + 1; const hasPrevPage = pageIndex > 0; return ( <>
{currentUser?.displayName} ) : router.query.userId ? ( {user?.displayName} ) : ( '' ) } > {intl.formatMessage(messages.requests)}
{data.serviceErrors && (data.serviceErrors.radarr.length > 0 || data.serviceErrors.sonarr.length > 0) && (hasPermission(Permission.MANAGE_REQUESTS) || hasPermission(Permission.REQUEST_ADVANCED)) && (
{intl.formatMessage(messages.unableToConnect, { services: [ ...data.serviceErrors.radarr.map((s) => s.name), ...data.serviceErrors.sonarr.map((s) => s.name), ].join(', '), })}
)} {data.results.map((request) => { return (
revalidate()} />
); })} {data.results.length === 0 && (
{intl.formatMessage(globalMessages.noresults)} {(currentFilter !== Filter.ALL || currentMediaType !== Filter.ALL) && (
)}
)}
); }; export default RequestList;