Files
triqura-ecd/components/cortex/shared/block-footer.tsx
colinislit b095b1e492 feat(cortex): add Intake Blocks MVP for voice/text commands
Adds 4 new intents for intake workflow:
- intake_status: shows completion percentage and section checklist
- intake_navigeer: navigation to specific intake tabs
- risico_query: displays risk assessments with severity indicators
- diagnose_query: shows primary/secondary diagnoses

New components:
- IntakeStatusBlock, RisicoBlock, DiagnoseBlock
- Shared block components (BlockLoading, BlockError, BlockEmpty, BlockSection, BlockItem, BlockFooter)
- useBlockData and useIntakeContext hooks

New API routes:
- GET /api/cortex/intake/status
- GET /api/cortex/intake/risico
- GET /api/cortex/intake/diagnose

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 23:21:18 +01:00

104 lines
2.6 KiB
TypeScript

'use client';
/**
* BlockFooter Component
*
* Footer with action buttons for Cortex blocks.
* Secondary action on left, primary action on right.
*
* Epic: E1.S3 - Block Layout
*/
import type { LucideIcon } from 'lucide-react';
import { Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { cn } from '@/lib/utils';
// ============================================================================
// Types
// ============================================================================
interface ActionConfig {
/** Knop label */
label: string;
/** Optioneel icoon */
icon?: LucideIcon;
/** Click handler */
onClick: () => void;
/** Loading state (alleen voor primary) */
loading?: boolean;
/** Disabled state */
disabled?: boolean;
}
interface BlockFooterProps {
/** Linker actie (ghost button) */
secondaryAction?: ActionConfig;
/** Rechter actie (solid button) */
primaryAction?: ActionConfig;
/** Extra CSS classes */
className?: string;
}
// ============================================================================
// Component
// ============================================================================
/**
* Footer for Cortex blocks with action buttons.
* Returns null if no actions provided.
*/
export function BlockFooter({
secondaryAction,
primaryAction,
className,
}: BlockFooterProps) {
// Don't render if no actions
if (!secondaryAction && !primaryAction) {
return null;
}
return (
<div
className={cn(
'flex items-center justify-between',
'pt-4 mt-4 border-t border-slate-200',
className
)}
>
{/* Secondary Action (left) */}
{secondaryAction ? (
<Button
variant="ghost"
size="sm"
onClick={secondaryAction.onClick}
disabled={secondaryAction.disabled}
>
{secondaryAction.icon && (
<secondaryAction.icon className="h-4 w-4 mr-1.5" />
)}
{secondaryAction.label}
</Button>
) : (
<div /> // Spacer
)}
{/* Primary Action (right) */}
{primaryAction && (
<Button
size="sm"
onClick={primaryAction.onClick}
disabled={primaryAction.loading || primaryAction.disabled}
>
{primaryAction.loading ? (
<Loader2 className="h-4 w-4 mr-1.5 animate-spin" />
) : primaryAction.icon ? (
<primaryAction.icon className="h-4 w-4 mr-1.5" />
) : null}
{primaryAction.label}
</Button>
)}
</div>
);
}