dorfteich/apps/web/src/ponds/DeletePondSection.tsx
Claude Fable 5 627f128ab8
Some checks failed
CD / Build and push images (push) Successful in 3m54s
CD / Deploy to Test (push) Successful in 11s
CI / Lint, typecheck, test (push) Successful in 4m8s
CI / Build container images (push) Has been skipped
CD / Smoke tests against Test (push) Failing after 11s
CD / Promote to Int (push) Has been skipped
CI / Auth e2e pack (push) Successful in 5m40s
CI / Import/export fidelity gate (push) Successful in 54s
Pond lifecycle in the UI: create shared ponds, delete from settings
The pond switcher grows a "+ New pond" entry with an inline form
(name + optional description, quota errors surfaced translated); the
pond settings of shared ponds end in a danger section that moves the
pond to the site-level trash after typing its name to confirm.
Personal ponds keep hiding the section. .button--danger is now a
solid red button (also fixes the admin restore button, which showed
red text on the accent-green background). Manuals no longer call
these actions API-only; covered by a members-pack e2e test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwZ4jR4KFAPvpjWevfUGX1
2026-07-12 19:15:34 +02:00

70 lines
2.1 KiB
TypeScript

import { useQueryClient } from '@tanstack/react-query';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { FormError } from '../components/forms';
import { apiDelete } from '../lib/api';
/**
* The pond's danger zone: move a shared pond to the site-level trash
* (`DELETE /ponds/:id`, Pond-Admin-gated in the api; a site admin can
* restore it). Type-to-confirm with the pond name — the same backstop
* pattern as the backup restore. Personal ponds never render this
* section: they are the account's home and the api refuses anyway.
*/
export function DeletePondSection({
pondId,
pondName,
}: {
pondId: string;
pondName: string;
}): React.JSX.Element {
const { t } = useTranslation();
const navigate = useNavigate();
const queryClient = useQueryClient();
const [confirm, setConfirm] = useState('');
const [error, setError] = useState<unknown>(null);
const [busy, setBusy] = useState(false);
const remove = async (event: React.FormEvent): Promise<void> => {
event.preventDefault();
setError(null);
setBusy(true);
try {
await apiDelete(`/ponds/${pondId}`);
await queryClient.invalidateQueries({ queryKey: ['ponds'] });
navigate('/');
} catch (err) {
setError(err);
setBusy(false);
}
};
return (
<section className="pond-delete">
<h2>{t('pond.delete.title')}</h2>
<p className="pond-delete__hint">{t('pond.delete.hint')}</p>
<form onSubmit={(e) => void remove(e)}>
<FormError error={error} />
<label>
{t('pond.delete.confirmLabel', { name: pondName })}
<input
type="text"
value={confirm}
autoComplete="off"
onChange={(e) => setConfirm(e.target.value)}
/>
</label>
<button
type="submit"
className="button button--danger pond-delete__submit"
disabled={busy || confirm !== pondName}
>
{t('pond.delete.submit')}
</button>
</form>
</section>
);
}