/** * QuickActionBoard — reusable card grid for feature dashboards. * * Renders a set of Quick Action cards grouped by category. * Each card dispatches via the onDispatch callback; the parent * decides what happens (navigate to workspace, trigger workflow, etc.). */ import React from 'react'; import styles from './QuickActionBoard.module.css'; import { useLanguage } from '../../providers/language/LanguageContext'; // ============================================================================ // TYPES // ============================================================================ export interface QuickAction { id: string; label: string; description: string; icon: string; color: string; category: string; actionType: 'agentPrompt' | 'workflow' | 'link'; config: Record; sortOrder: number; } export interface QuickActionCategory { id: string; label: string; sortOrder: number; } export interface QuickActionBoardProps { actions: QuickAction[]; categories?: QuickActionCategory[]; onDispatch: (action: QuickAction) => void; loading?: boolean; grouped?: boolean; } // ============================================================================ // ICON MAP (mdi name → unicode/emoji fallback) // ============================================================================ const _ICON_MAP: Record = { 'mdi-file-document-check-outline': '\uD83D\uDCCB', 'mdi-sync': '\uD83D\uDD04', 'mdi-chart-bar': '\uD83D\uDCCA', 'mdi-view-dashboard-outline': '\uD83D\uDCF0', 'mdi-cash-multiple': '\uD83D\uDCB0', 'mdi-clipboard-check-outline': '\u2705', 'mdi-chart-timeline-variant': '\uD83D\uDCC8', 'mdi-camera-document-outline': '\uD83D\uDCF7', }; function _renderIcon(icon: string, color: string): React.ReactNode { const fallback = _ICON_MAP[icon] || '\u26A1'; return ( {fallback} ); } // ============================================================================ // COMPONENT // ============================================================================ export const QuickActionBoard: React.FC = ({ actions, categories, onDispatch, loading = false, grouped = true, }) => { const { t } = useLanguage(); if (loading) { return (

{t('Schnellaktionen')}

{[1, 2, 3, 4].map((i) => (
))}
); } if (!actions || actions.length === 0) { return null; } const _handleClick = (action: QuickAction) => (e: React.MouseEvent) => { e.preventDefault(); onDispatch(action); }; if (!grouped || !categories || categories.length === 0) { return (

{t('Schnellaktionen')}

{actions.map((action) => ( ))}
); } const sortedCategories = [...categories].sort((a, b) => a.sortOrder - b.sortOrder); const actionsByCategory = new Map(); for (const action of actions) { const cat = action.category || '_uncategorized'; if (!actionsByCategory.has(cat)) actionsByCategory.set(cat, []); actionsByCategory.get(cat)!.push(action); } return (

{t('Schnellaktionen')}

{sortedCategories.map((cat) => { const catActions = actionsByCategory.get(cat.id); if (!catActions || catActions.length === 0) return null; return (

{cat.label}

{catActions.map((action) => ( ))}
); })}
); }; export default QuickActionBoard;