"use client"; import { useCallback, type ReactNode } from "react"; import { FileText, ImageOff } from "lucide-react"; import { certificationsAPI, CertificationFileInfo, CertificationSide, } from "@/lib/api/certifications"; import { useAuthedBlobUrl } from "@/hooks/useAuthedBlobUrl"; import { getApiErrorMessage } from "@/lib/api/error"; import { shrinkPicture } from "@/lib/shrink-picture"; import { CERTIFICATION_CARD_ASPECT_CLASS, certificationFileVersion, } from "@/lib/certification"; import { cn } from "@/lib/utils"; import { ButtonSpinner } from "@/components/ui/button-spinner"; interface CertificationCardFrameProps { /** * Draws the frame at a thumbnail's width instead of filling its column. It * changes the *width* only: the shape is the same everywhere, which is the * whole point of the frame existing. */ compact?: boolean; /** Dashed, for a slot with nothing in it. */ empty?: boolean; className?: string; /** Announces what the frame stands for when it holds no picture to describe. */ "aria-label"?: string; title?: string; children?: ReactNode; } /** * The box a c-card is drawn in, wherever one is drawn: the standard card shape, * the app's own corner radius, and `overflow-hidden` so a picture filling it is * clipped to those corners rather than sitting square inside them. * * Exported because a card is not always a picture - a stored PDF, a slot the diver * has not filled, a fetch that failed and the check-in sheet's own PDF note all * occupy the same footprint, and one box is what keeps them to one size. */ export function CertificationCardFrame({ compact = false, empty = false, className, children, ...rest }: CertificationCardFrameProps) { return (