import { PondArchivePreview } from '@dorfteich/shared'; import { useQuery } from '@tanstack/react-query'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { apiGet } from '../lib/api'; /** * The last full archive, offered INSIDE the deletion flow (issue #305). * * The gap this closes is not a missing prompt — the type-to-confirm field * next to it is stricter than a dialog. It is that the person who deletes the * pond loses access the moment they do: the pond disappears from their view, * only a Site Admin can bring it back, and the export is no longer reachable * for them. So the offer has to be here, before the button, not afterwards. * * Not downloading is allowed. A pond full of test pages should not require a * download, and the server cannot tell whether a file actually arrived — so * the finality is stated in text instead of enforced. */ export function PondArchiveOffer({ pondId }: { pondId: string }): React.JSX.Element { const { t } = useTranslation(); const [started, setStarted] = useState(false); const preview = useQuery({ queryKey: ['pond', pondId, 'archive-preview'], queryFn: () => apiGet(`/ponds/${pondId}/archive/preview`), }); return (

{t('pond.archive.intro')}

{/* An archive silently missing content is worse than no archive: it ends the search. So the omission is named BEFORE the download, with its number, not implied afterwards. */} {preview.data && !preview.data.complete && (

{t('pond.archive.omitted', { count: preview.data.omittedPages })}

)}

{t('pond.archive.noImport')}

{/* A plain link, not fetch-into-a-blob: the api streams the ZIP, and buffering a whole pond in the tab to show a progress bar would trade memory for cosmetics. The browser's own download UI reports progress and completion; what it cannot say is that the archive is being BUILT, so the live region below says that. */} setStarted(true)} > {t('pond.archive.download')}

{started ? t('pond.archive.started') : ''}

{t('pond.archive.finality')}

); }