Files
triqura-ecd/components/behandelplan/editable-section.tsx
colinislit 9e4e16035b feat(behandelplan): E3 UI componenten en documentatie updates
Behandelplan UI (E3):
- page-client.tsx: Client-side behandelplan pagina
- actions.ts: Server actions voor CRUD operaties
- behandelplan-view.tsx: Volledige behandelplan weergave
- behandelplan-list.tsx: Lijst van behandelplannen
- editable-section.tsx: Herbruikbare edit sectie component
- sections/: Goal, intervention en behandelstructuur forms

UI Componenten:
- components/ui/checkbox.tsx (shadcn)
- components/ui/input.tsx (shadcn)
- components/ui/select.tsx (shadcn)

Documentatie:
- agenda-systeem.mdx toegevoegd
- _index.json en metadata.json bijgewerkt

Dependencies:
- @radix-ui/react-checkbox toegevoegd

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-06 00:35:00 +01:00

163 lines
4.1 KiB
TypeScript

'use client';
import { useState, ReactNode } from 'react';
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from '@/components/ui/card';
import { Button } from '@/components/ui/button';
import { Pencil, X, Check, Loader2 } from 'lucide-react';
interface EditableSectionProps {
title: string;
description?: string;
icon?: ReactNode;
children: ReactNode;
editForm?: ReactNode;
onSave?: () => Promise<void>;
onCancel?: () => void;
isEditing?: boolean;
onEditChange?: (isEditing: boolean) => void;
canEdit?: boolean;
className?: string;
}
export function EditableSection({
title,
description,
icon,
children,
editForm,
onSave,
onCancel,
isEditing: externalIsEditing,
onEditChange,
canEdit = true,
className = '',
}: EditableSectionProps) {
const [internalIsEditing, setInternalIsEditing] = useState(false);
const [isSaving, setIsSaving] = useState(false);
// Use external or internal state
const isEditing = externalIsEditing ?? internalIsEditing;
const setIsEditing = onEditChange ?? setInternalIsEditing;
const handleSave = async () => {
if (!onSave) return;
setIsSaving(true);
try {
await onSave();
setIsEditing(false);
} catch (error) {
console.error('Error saving:', error);
} finally {
setIsSaving(false);
}
};
const handleCancel = () => {
onCancel?.();
setIsEditing(false);
};
return (
<Card className={className}>
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<div>
<CardTitle className="text-base flex items-center gap-2">
{icon}
{title}
</CardTitle>
{description && <CardDescription>{description}</CardDescription>}
</div>
{canEdit && !isEditing && (
<Button
variant="ghost"
size="sm"
className="h-8 w-8 p-0"
onClick={() => setIsEditing(true)}
>
<Pencil className="h-4 w-4" />
</Button>
)}
</div>
</CardHeader>
<CardContent>
{isEditing && editForm ? (
<div className="space-y-4">
{editForm}
<div className="flex justify-end gap-2 pt-2 border-t">
<Button
variant="outline"
size="sm"
onClick={handleCancel}
disabled={isSaving}
>
<X className="h-4 w-4 mr-1" />
Annuleren
</Button>
<Button
size="sm"
onClick={handleSave}
disabled={isSaving}
>
{isSaving ? (
<Loader2 className="h-4 w-4 mr-1 animate-spin" />
) : (
<Check className="h-4 w-4 mr-1" />
)}
Opslaan
</Button>
</div>
</div>
) : (
children
)}
</CardContent>
</Card>
);
}
// Simple inline edit buttons for list items
interface ItemActionsProps {
onEdit?: () => void;
onDelete?: () => void;
isDeleting?: boolean;
}
export function ItemActions({ onEdit, onDelete, isDeleting }: ItemActionsProps) {
return (
<div className="flex items-center gap-1">
{onEdit && (
<Button
variant="ghost"
size="sm"
className="h-7 w-7 p-0"
onClick={(e) => {
e.stopPropagation();
onEdit();
}}
>
<Pencil className="h-3.5 w-3.5" />
</Button>
)}
{onDelete && (
<Button
variant="ghost"
size="sm"
className="h-7 w-7 p-0 text-red-500 hover:text-red-700 hover:bg-red-50"
onClick={(e) => {
e.stopPropagation();
onDelete();
}}
disabled={isDeleting}
>
{isDeleting ? (
<Loader2 className="h-3.5 w-3.5 animate-spin" />
) : (
<X className="h-3.5 w-3.5" />
)}
</Button>
)}
</div>
);
}