import { X, Pencil, Trash2, Star, StarOff } from 'lucide-react'; import type { LucideIcon } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { useConfirmAction } from '@/hooks/useConfirmAction'; import { formatUpdatedAt } from './utils'; import CopyableField from './CopyableField'; export interface PanelField { label: string; key: string; copyable?: boolean; icon?: LucideIcon; multiline?: boolean; fullWidth?: boolean; } interface EntityDetailPanelProps { item: T | null; fields: PanelField[]; onEdit: () => void; onDelete: () => void; deleteLoading?: boolean; onClose: () => void; renderHeader: (item: T) => React.ReactNode; getUpdatedAt: (item: T) => string; getValue: (item: T, key: string) => string | undefined; isFavourite?: boolean; onToggleFavourite?: () => void; favouriteLabel?: string; extraActions?: (item: T) => React.ReactNode; } export function EntityDetailPanel({ item, fields, onEdit, onDelete, deleteLoading = false, onClose, renderHeader, getUpdatedAt, getValue, isFavourite, onToggleFavourite, favouriteLabel = 'favourite', extraActions, }: EntityDetailPanelProps) { const { confirming, handleClick: handleDelete } = useConfirmAction(onDelete); if (!item) return null; return (
{/* Header */}
{renderHeader(item)}
{onToggleFavourite && ( )}
{/* Body */}
{(() => { const gridFields = fields.filter((f) => !f.fullWidth && getValue(item, f.key)); const fullWidthFields = fields.filter((f) => f.fullWidth && getValue(item, f.key)); return ( <> {gridFields.length > 0 && (
{gridFields.map((field) => { const value = getValue(item, field.key)!; return (
{field.icon && } {field.label}
{field.copyable ? ( ) : (

{value}

)}
); })}
)} {fullWidthFields.map((field) => { const value = getValue(item, field.key)!; return (
{field.icon && } {field.label}
{field.copyable ? ( ) : (

{value}

)}
); })} ); })()}
{/* Footer */}
{formatUpdatedAt(getUpdatedAt(item))} {extraActions?.(item)}
{confirming ? ( ) : ( )}
); }