import { useCallback, useMemo } from "react"; import { useRouter } from "next/router"; import { Chip } from "./Chip"; import { Ico, Icon } from "./Ico"; import { Img } from "./Img"; import { Link } from "./Inputs/Link"; import { DatePickerFragment, PricePickerFragment, UploadImageFragment } from "graphql/generated"; import { cIf, cJoin } from "helpers/className"; import { prettyDate, prettyDuration, prettyPrice, prettyShortenNumber } from "helpers/formatters"; import { ImageQuality } from "helpers/img"; import { useDeviceSupportsHover } from "hooks/useMediaQuery"; import { useSmartLanguage } from "hooks/useSmartLanguage"; import { TranslatedProps } from "types/TranslatedProps"; import { useUserSettings } from "contexts/UserSettingsContext"; import { useLocalData } from "contexts/LocalDataContext"; /* * ╭─────────────╮ * ───────────────────────────────────────╯ COMPONENT ╰─────────────────────────────────────────── */ interface Props { thumbnail?: UploadImageFragment | string | null | undefined; thumbnailAspectRatio?: string; thumbnailForceAspectRatio?: boolean; thumbnailRounded?: boolean; href: string; pre_title?: string | null | undefined; title: string | null | undefined; subtitle?: string | null | undefined; description?: string | null | undefined; topChips?: string[]; bottomChips?: string[]; keepInfoVisible?: boolean; stackNumber?: number; metadata?: { releaseDate?: DatePickerFragment | null; releaseDateFormat?: Intl.DateTimeFormatOptions["dateStyle"]; price?: PricePickerFragment | null; views?: number; author?: string; position: "Bottom" | "Top"; }; infoAppend?: React.ReactNode; hoverlay?: | { __typename: "Video"; duration: number; } | { __typename: "anotherHoverlayName" }; } // ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ export const PreviewCard = ({ href, thumbnail, thumbnailAspectRatio = "4/3", thumbnailForceAspectRatio = false, thumbnailRounded = true, pre_title, title, subtitle, description, stackNumber = 0, topChips, bottomChips, keepInfoVisible, metadata, hoverlay, infoAppend, }: Props): JSX.Element => { const { currency } = useUserSettings(); const { currencies } = useLocalData(); const isHoverable = useDeviceSupportsHover(); const router = useRouter(); const metadataJSX = useMemo( () => ( <> {metadata && (metadata.releaseDate || metadata.price) && (
{metadata.releaseDate && (

{prettyDate(metadata.releaseDate, router.locale)}

)} {metadata.price && (

{prettyPrice(metadata.price, currencies, currency)}

)} {metadata.views && (

{prettyShortenNumber(metadata.views)}

)} {metadata.author && (

{metadata.author}

)}
)} ), [currencies, currency, metadata, router.locale] ); return ( {stackNumber > 0 && ( <>
{thumbnail && ( )}
{thumbnail && ( )}
)} {thumbnail ? (
{stackNumber > 0 && (
{stackNumber}
)} {hoverlay && hoverlay.__typename === "Video" && ( <>
{prettyDuration(hoverlay.duration)}
)}
) : (
{stackNumber > 0 && (
{stackNumber}
)}
)}
{metadata?.position === "Top" && metadataJSX} {topChips && topChips.length > 0 && (
{topChips.map((text, index) => ( ))}
)}
{pre_title &&

{pre_title}

} {title && (

{title}

)} {subtitle &&

{subtitle}

}
{description &&

{description}

} {bottomChips && bottomChips.length > 0 && (
{bottomChips.map((text, index) => ( ))}
)} {metadata?.position === "Bottom" && metadataJSX} {infoAppend}
); }; /* * ╭──────────────────────╮ * ───────────────────────────────────╯ TRANSLATED VARIANT ╰────────────────────────────────────── */ export const TranslatedPreviewCard = ({ translations, fallback, ...otherProps }: TranslatedProps): JSX.Element => { const [selectedTranslation] = useSmartLanguage({ items: translations, languageExtractor: useCallback((item: { language: string }): string => item.language, []), }); return ( ); };