import { Button, Card, Center, Grid, Group, Loader, Image as MantineImage, Modal, ScrollArea, Stack, Text, Title, } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; import { IconDownload, IconExternalLink, IconPlayerPlay } from '@tabler/icons-react'; import { Trans, useTranslation } from 'next-i18next'; import Image from 'next/image'; import { useRouter } from 'next/router'; import React, { useMemo } from 'react'; import { z } from 'zod'; import { availableIntegrations } from '~/components/Dashboard/Modals/EditAppModal/Tabs/IntegrationTab/Components/InputElements/IntegrationSelector'; import { useConfigContext } from '~/config/provider'; import { RequestModal } from '~/modules/overseerr/RequestModal'; import { RouterOutputs, api } from '~/utils/api'; type MovieModalProps = { opened: boolean; closeModal: () => void; }; const queryParamsSchema = z.object({ movie: z.literal('true'), search: z.string().nonempty(), type: z.enum(['jellyseerr', 'overseerr']), }); export const MovieModal = ({ opened, closeModal }: MovieModalProps) => { const query = useRouter().query; const queryParams = queryParamsSchema.safeParse(query); if (!queryParams.success) { return null; } const integration = useMemo(() => { return availableIntegrations.find((x) => x.value === queryParams.data.type)!; }, [queryParams.data.type]); return ( {`${integration.label} {integration.label} search } > ); }; type MovieResultsProps = Omit, 'movie'>; const MovieResults = ({ search, type }: MovieResultsProps) => { const { t } = useTranslation('layout/header'); const { name: configName } = useConfigContext(); const { data: movies, isLoading } = api.overseerr.search.useQuery( { query: search, configName: configName!, integration: type, limit: 12, }, { refetchOnWindowFocus: false, refetchOnMount: false, refetchInterval: false, } ); if (isLoading) return (
); return ( , }} /> {movies?.map((result, index: number) => ( ))} ); }; type MovieDisplayProps = { movie: RouterOutputs['overseerr']['search'][number]; type: 'jellyseerr' | 'overseerr'; }; const MovieDisplay = ({ movie, type }: MovieDisplayProps) => { const { t } = useTranslation('modules/common-media-cards'); const { config } = useConfigContext(); const [requestModalOpened, requestModal] = useDisclosure(false); if (!config) { return null; } const service = config.apps.find((service) => service.integration.type === type); const mediaUrl = movie.mediaInfo?.plexUrl ?? movie.mediaInfo?.mediaUrl; const serviceUrl = service?.behaviour.externalUrl ?? service?.url; const externalUrl = new URL( `${movie.mediaType}/${movie.id}`, serviceUrl ?? 'https://www.themoviedb.org' ); return ( {movie.title ?? movie.name ?? movie.originalName} {movie.overview} {!movie.mediaInfo?.mediaAddedAt && ( <> )} {mediaUrl && ( )} {externalUrl && ( )} ); };