import { ActionIcon, Badge, Card, Center, Flex, Group, Image, Stack, Text, Tooltip, } from '@mantine/core'; import { useTranslation } from 'next-i18next'; import { IconCheck, IconGitPullRequest, IconThumbDown, IconThumbUp } from '@tabler/icons-react'; import { useMutation } from '@tanstack/react-query'; import axios from 'axios'; import { notifications } from '@mantine/notifications'; import { defineWidget } from '../helper'; import { WidgetLoading } from '../loading'; import { IWidget } from '../widgets'; import { useMediaRequestQuery } from './media-request-query'; import { MediaRequest, MediaRequestStatus } from './media-request-types'; const definition = defineWidget({ id: 'media-requests-list', icon: IconGitPullRequest, options: { replaceLinksWithExternalHost: { type: 'switch', defaultValue: true, }, }, component: MediaRequestListTile, gridstack: { minWidth: 3, minHeight: 2, maxWidth: 12, maxHeight: 12, }, }); export type MediaRequestListWidget = IWidget<(typeof definition)['id'], typeof definition>; interface MediaRequestListWidgetProps { widget: MediaRequestListWidget; } function MediaRequestListTile({ widget }: MediaRequestListWidgetProps) { const { t } = useTranslation('modules/media-requests-list'); const { data, refetch, isLoading } = useMediaRequestQuery(); // Use mutation to approve or deny a pending request const mutate = useMutation({ mutationFn: async (e: { request: MediaRequest; action: string }) => { const data = await axios.put(`/api/modules/overseerr/${e.request.id}?action=${e.action}`); notifications.show({ title: t('requestUpdated'), message: t('requestUpdatedMessage', { title: e.request.name }), color: 'blue', }); refetch(); }, }); if (!data || isLoading) { return ; } if (data.length === 0) { return (
{t('noRequests')}
); } const countPendingApproval = data.filter( (x) => x.status === MediaRequestStatus.PendingApproval ).length; // Return a sorted data by status to show pending first, then the default order const sortedData = data.sort((a: MediaRequest, b: MediaRequest) => { if (a.status === MediaRequestStatus.PendingApproval) { return -1; } if (b.status === MediaRequestStatus.PendingApproval) { return 1; } return 0; }); return ( {countPendingApproval > 0 ? ( {t('pending', { countPendingApproval })} ) : ( {t('nonePending')} )} {sortedData.map((item) => ( poster {item.airDate && {item.airDate.split('-')[0]}} {item.name} requester avatar {item.userName} {item.status === MediaRequestStatus.PendingApproval && ( { notifications.show({ id: `approve ${item.id}`, color: 'yellow', title: 'Approving request...', message: undefined, loading: true, }); await mutate.mutateAsync({ request: item, action: 'approve' }).then(() => notifications.update({ id: `approve ${item.id}`, color: 'teal', title: 'Request was approved!', message: undefined, icon: , autoClose: 2000, }) ); await refetch(); }} > { await mutate.mutateAsync({ request: item, action: 'decline' }); await refetch(); }} > )} ))} ); } const MediaRequestStatusBadge = ({ status }: { status: MediaRequestStatus }) => { const { t } = useTranslation('modules/media-requests-list'); switch (status) { case MediaRequestStatus.Approved: return {t('state.approved')}; case MediaRequestStatus.Declined: return {t('state.declined')}; case MediaRequestStatus.PendingApproval: return {t('state.pendingApproval')}; default: return <>; } }; export default definition;