Scrum4Me/components/product-docs/delete-product-doc-button.tsx
Madhura68 bb4a71eafa feat(PBI-96/T-1069): doc viewer/editor + delete-button
- app/(app)/products/[id]/docs/[folder]/[slug]/page.tsx: server-route
  die doc laadt (scope-checked via productAccessFilter), frontmatter
  parseert, en op basis van ?edit=1 viewer of editor toont. Fallback
  voor unparseable frontmatter toont errors + raw content in <pre>.
- product-doc-viewer.tsx: server-component met frontmatter-kop
  (title + status-badge + audience/applies_to/last_updated meta) en
  body via <Markdown> (XSS-safe).
- product-doc-editor.tsx: client-wrapper rond MarkdownDocEditor met
  parseProductDocMd validator + updateProductDocAction + cancelHref.
- delete-product-doc-button.tsx: AlertDialog confirm + delete-action
  + DemoTooltip + redirect-na-success. Disabled in demo.
- Edit-knop conditioneel verborgen bij disabled folder (T-1071 voegt
  banner toe); delete blijft altijd zichtbaar voor cleanup.
- Button met `render={<Link/>}` ipv asChild (CLAUDE.md hardstop
  base-ui pattern).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 14:30:13 +02:00

104 lines
2.9 KiB
TypeScript

'use client'
// Confirm-dialog + delete-action voor een Product Doc. DemoTooltip-wrapped
// (laag 3 van de drie-laagse demo-policy). Na succesvolle delete: redirect
// naar de folder-page.
import { useState, useTransition } from 'react'
import { useRouter } from 'next/navigation'
import { Trash2 } from 'lucide-react'
import { toast } from 'sonner'
import { Button } from '@/components/ui/button'
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from '@/components/ui/alert-dialog'
import { DemoTooltip } from '@/components/shared/demo-tooltip'
import { debugProps } from '@/lib/debug'
import { deleteProductDocAction } from '@/actions/product-docs'
interface Props {
docId: string
docTitle: string
/** URL waar we naar redirecten na succes. */
redirectHref: string
isDemo: boolean
}
export function DeleteProductDocButton({
docId,
docTitle,
redirectHref,
isDemo,
}: Props) {
const router = useRouter()
const [open, setOpen] = useState(false)
const [submitting, startSubmit] = useTransition()
function confirmDelete() {
startSubmit(async () => {
const r = await deleteProductDocAction(docId)
if ('error' in r) {
toast.error(r.error)
return
}
toast.success('Doc verwijderd')
setOpen(false)
router.push(redirectHref)
router.refresh()
})
}
return (
<AlertDialog open={open} onOpenChange={setOpen}>
<DemoTooltip show={isDemo}>
<AlertDialogTrigger
render={
<Button
variant="outline"
size="sm"
disabled={isDemo}
{...debugProps(
'delete-product-doc-button',
'DeleteProductDocButton',
'components/product-docs/delete-product-doc-button.tsx',
)}
>
<Trash2 className="size-3.5 mr-1" />
Verwijderen
</Button>
}
/>
</DemoTooltip>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Doc verwijderen?</AlertDialogTitle>
<AlertDialogDescription>
&ldquo;{docTitle}&rdquo; wordt permanent verwijderd. Een audit-log-rij
blijft bewaard, maar de inhoud is daarna niet meer leesbaar.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel disabled={submitting}>Annuleer</AlertDialogCancel>
<AlertDialogAction
onClick={confirmDelete}
disabled={submitting}
variant="destructive"
data-debug-id="delete-product-doc-button__confirm"
>
Ja, verwijder
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}