// ================================================================ // frontend/src/components/dashboard/ActionQueueCard.tsx // ================================================================ /** * Action Queue Card - What needs your attention right now * * Prioritized list of actions the user needs to take, with context * about why each action is needed and what happens if they don't do it. */ import React, { useState } from 'react'; import { FileText, AlertCircle, CheckCircle2, Eye, Edit, Clock, Euro, ChevronDown, ChevronUp, } from 'lucide-react'; import { ActionItem, ActionQueue } from '../../api/hooks/newDashboard'; import { useReasoningFormatter } from '../../hooks/useReasoningTranslation'; import { useTranslation } from 'react-i18next'; interface ActionQueueCardProps { actionQueue: ActionQueue; loading?: boolean; onApprove?: (actionId: string) => void; onViewDetails?: (actionId: string) => void; onModify?: (actionId: string) => void; } const urgencyConfig = { critical: { bg: 'bg-red-50', border: 'border-red-300', badge: 'bg-red-100 text-red-800', icon: AlertCircle, }, important: { bg: 'bg-amber-50', border: 'border-amber-300', badge: 'bg-amber-100 text-amber-800', icon: AlertCircle, }, normal: { bg: 'bg-blue-50', border: 'border-blue-300', badge: 'bg-blue-100 text-blue-800', icon: FileText, }, }; function ActionItemCard({ action, onApprove, onViewDetails, onModify, }: { action: ActionItem; onApprove?: (id: string) => void; onViewDetails?: (id: string) => void; onModify?: (id: string) => void; }) { const [expanded, setExpanded] = useState(false); const config = urgencyConfig[action.urgency as keyof typeof urgencyConfig] || urgencyConfig.normal; const UrgencyIcon = config.icon; const { formatPOAction } = useReasoningFormatter(); const { t } = useTranslation('reasoning'); // Translate reasoning_data (or fallback to deprecated text fields) const { reasoning, consequence, severity } = action.reasoning_data ? formatPOAction(action.reasoning_data) : { reasoning: action.reasoning || '', consequence: action.consequence || '', severity: '' }; return (
{/* Header */}

{action.title || 'Action Required'}

{action.urgency || 'normal'}

{action.subtitle || ''}

{/* Amount (for POs) */} {action.amount && (
{action.amount.toFixed(2)} {action.currency}
)} {/* Reasoning (always visible) */}

{t('jtbd.action_queue.why_needed')}

{reasoning}

{/* Consequence (expandable) */} {consequence && ( <> {expanded && (

{consequence}

{severity && ( {severity} )}
)} )} {/* Time Estimate */}
{t('jtbd.action_queue.estimated_time')}: {action.estimatedTimeMinutes || 5} min
{/* Action Buttons */}
{(action.actions || []).map((button, index) => { const buttonStyles = { primary: 'bg-blue-600 hover:bg-blue-700 text-white', secondary: 'bg-gray-200 hover:bg-gray-300 text-gray-800', tertiary: 'bg-white hover:bg-gray-50 text-gray-700 border border-gray-300', }; const handleClick = () => { if (button.action === 'approve' && onApprove) { onApprove(action.id); } else if (button.action === 'view_details' && onViewDetails) { onViewDetails(action.id); } else if (button.action === 'modify' && onModify) { onModify(action.id); } }; return ( ); })}
); } export function ActionQueueCard({ actionQueue, loading, onApprove, onViewDetails, onModify, }: ActionQueueCardProps) { const [showAll, setShowAll] = useState(false); const { t } = useTranslation('reasoning'); if (loading || !actionQueue) { return (
); } if (!actionQueue.actions || actionQueue.actions.length === 0) { return (

{t('jtbd.action_queue.all_caught_up')}

{t('jtbd.action_queue.no_actions')}

); } const displayedActions = showAll ? actionQueue.actions : actionQueue.actions.slice(0, 3); return (
{/* Header */}

{t('jtbd.action_queue.title')}

{(actionQueue.totalActions || 0) > 3 && ( {actionQueue.totalActions || 0} {t('jtbd.action_queue.total')} )}
{/* Summary Badges */} {((actionQueue.criticalCount || 0) > 0 || (actionQueue.importantCount || 0) > 0) && (
{(actionQueue.criticalCount || 0) > 0 && ( {actionQueue.criticalCount || 0} {t('jtbd.action_queue.critical')} )} {(actionQueue.importantCount || 0) > 0 && ( {actionQueue.importantCount || 0} {t('jtbd.action_queue.important')} )}
)} {/* Action Items */}
{displayedActions.map((action) => ( ))}
{/* Show More/Less */} {(actionQueue.totalActions || 0) > 3 && ( )}
); }