1
mirror of https://github.com/jakejarvis/hoot.git synced 2025-10-18 22:34:25 -04:00
Files
hoot/components/domain/screenshot.tsx

90 lines
2.2 KiB
TypeScript

"use client";
import { useQuery } from "@tanstack/react-query";
import { CircleX } from "lucide-react";
import Image from "next/image";
import { useState } from "react";
import { Spinner } from "@/components/ui/spinner";
import { useTRPC } from "@/lib/trpc/client";
import { cn } from "@/lib/utils";
export function Screenshot({
domain,
enabled = true,
className,
width = 1200,
height = 630,
imageClassName,
aspectClassName = "aspect-[1200/630]",
}: {
domain: string;
enabled?: boolean;
className?: string;
width?: number;
height?: number;
imageClassName?: string;
aspectClassName?: string;
}) {
const trpc = useTRPC();
const [failedUrl, setFailedUrl] = useState<string | null>(null);
const { data, isLoading, isFetching } = useQuery(
trpc.domain.screenshot.queryOptions(
{ domain },
{
enabled,
retry: 5,
},
),
);
const url = data?.url ?? null;
const loading = isLoading || isFetching;
return (
<div className={className}>
{url && failedUrl !== url ? (
<a href={`https://${domain}`} target="_blank" rel="noopener">
<Image
key={url}
src={url}
alt={`Homepage preview of ${domain}`}
width={width}
height={height}
className={cn(
"h-auto w-full object-cover",
aspectClassName,
imageClassName,
)}
unoptimized
priority={false}
draggable={false}
onError={() => setFailedUrl(url)}
/>
</a>
) : (
<div
className={`h-auto w-full ${aspectClassName} flex items-center justify-center bg-muted/50`}
>
<div
className="flex items-center gap-2 text-muted-foreground text-xs"
aria-live="polite"
>
{loading ? (
<>
<Spinner />
<span>Taking screenshot...</span>
</>
) : (
<>
<CircleX className="h-4 w-4" />
<span>Unable to take a screenshot.</span>
</>
)}
</div>
</div>
)}
</div>
);
}