Add whatsapp feature

This commit is contained in:
Urtzi Alfaro
2025-11-13 16:01:08 +01:00
parent d7df2b0853
commit 9bc048d360
74 changed files with 9765 additions and 533 deletions

View File

@@ -80,7 +80,9 @@ export function HealthStatusCard({ healthStatus, loading }: HealthStatusCardProp
</div>
<div className="flex-1 min-w-0">
<h2 className="text-xl md:text-2xl font-bold mb-2" style={{ color: config.textColor }}>
{healthStatus.headline || t(`jtbd.health_status.${status}`)}
{typeof healthStatus.headline === 'object' && healthStatus.headline?.key
? t(healthStatus.headline.key.replace('.', ':'), healthStatus.headline.params || {})
: healthStatus.headline || t(`jtbd.health_status.${status}`)}
</h2>
{/* Last Update */}
@@ -117,6 +119,11 @@ export function HealthStatusCard({ healthStatus, loading }: HealthStatusCardProp
const iconColor = item.actionRequired ? 'var(--color-warning-600)' : 'var(--color-success-600)';
const bgColor = item.actionRequired ? 'var(--bg-primary)' : 'rgba(255, 255, 255, 0.5)';
// Translate using textKey if available, otherwise use text
const displayText = item.textKey
? t(item.textKey.replace('.', ':'), item.textParams || {})
: item.text || '';
return (
<div
key={index}
@@ -128,7 +135,7 @@ export function HealthStatusCard({ healthStatus, loading }: HealthStatusCardProp
className={`text-sm md:text-base ${item.actionRequired ? 'font-semibold' : ''}`}
style={{ color: 'var(--text-primary)' }}
>
{item.text || ''}
{displayText}
</span>
</div>
);

View File

@@ -20,19 +20,53 @@ import {
Brain,
ChevronDown,
ChevronUp,
Loader2,
} from 'lucide-react';
import { OrchestrationSummary } from '../../api/hooks/newDashboard';
import { runDailyWorkflow } from '../../api/services/orchestrator';
import { formatDistanceToNow } from 'date-fns';
import { useTranslation } from 'react-i18next';
import { useTenant } from '../../stores/tenant.store';
import toast from 'react-hot-toast';
interface OrchestrationSummaryCardProps {
summary: OrchestrationSummary;
loading?: boolean;
onWorkflowComplete?: () => void;
}
export function OrchestrationSummaryCard({ summary, loading }: OrchestrationSummaryCardProps) {
export function OrchestrationSummaryCard({ summary, loading, onWorkflowComplete }: OrchestrationSummaryCardProps) {
const [expanded, setExpanded] = useState(false);
const [isRunning, setIsRunning] = useState(false);
const { t } = useTranslation('reasoning');
const { currentTenant } = useTenant();
const handleRunPlanning = async () => {
if (!currentTenant?.id) {
toast.error(t('jtbd.orchestration_summary.no_tenant_error') || 'No tenant ID found');
return;
}
setIsRunning(true);
try {
const result = await runDailyWorkflow(currentTenant.id);
if (result.success) {
toast.success(t('jtbd.orchestration_summary.planning_started') || 'Planning started successfully');
// Call callback to refresh the orchestration summary
if (onWorkflowComplete) {
onWorkflowComplete();
}
} else {
toast.error(result.message || t('jtbd.orchestration_summary.planning_failed') || 'Failed to start planning');
}
} catch (error) {
console.error('Error running daily workflow:', error);
toast.error(t('jtbd.orchestration_summary.planning_error') || 'An error occurred while starting planning');
} finally {
setIsRunning(false);
}
};
if (loading || !summary) {
return (
@@ -57,24 +91,27 @@ export function OrchestrationSummaryCard({ summary, loading }: OrchestrationSumm
<div
className="border-2 rounded-xl p-6"
style={{
backgroundColor: 'var(--color-info-50)',
borderColor: 'var(--color-info-200)',
backgroundColor: 'var(--surface-secondary)',
borderColor: 'var(--color-info-300)',
}}
>
<div className="flex items-start gap-4">
<Bot className="w-10 h-10 flex-shrink-0" style={{ color: 'var(--color-info-600)' }} />
<Bot className="w-10 h-10 flex-shrink-0" style={{ color: 'var(--color-info)' }} />
<div>
<h3 className="text-lg font-bold mb-2" style={{ color: 'var(--color-info-900)' }}>
<h3 className="text-lg font-bold mb-2" style={{ color: 'var(--text-primary)' }}>
{t('jtbd.orchestration_summary.ready_to_plan')}
</h3>
<p className="mb-4" style={{ color: 'var(--color-info-700)' }}>{summary.message || ''}</p>
<p className="mb-4" style={{ color: 'var(--text-secondary)' }}>{summary.message || ''}</p>
<button
className="px-4 py-2 rounded-lg font-semibold transition-colors duration-200"
onClick={handleRunPlanning}
disabled={isRunning}
className="px-4 py-2 rounded-lg font-semibold transition-colors duration-200 flex items-center gap-2 disabled:opacity-50 disabled:cursor-not-allowed hover:opacity-90"
style={{
backgroundColor: 'var(--color-info-600)',
color: 'var(--text-inverse)',
backgroundColor: 'var(--color-info)',
color: 'var(--bg-primary)',
}}
>
{isRunning && <Loader2 className="w-4 h-4 animate-spin" />}
{t('jtbd.orchestration_summary.run_planning')}
</button>
</div>
@@ -91,14 +128,14 @@ export function OrchestrationSummaryCard({ summary, loading }: OrchestrationSumm
<div
className="rounded-xl shadow-md p-6 border"
style={{
background: 'linear-gradient(to bottom right, var(--color-primary-50), var(--color-info-50))',
borderColor: 'var(--color-primary-100)',
background: 'linear-gradient(135deg, var(--bg-secondary) 0%, var(--bg-tertiary) 100%)',
borderColor: 'var(--border-primary)',
}}
>
{/* Header */}
<div className="flex items-start gap-4 mb-6">
<div className="p-3 rounded-full" style={{ backgroundColor: 'var(--color-primary-100)' }}>
<Bot className="w-8 h-8" style={{ color: 'var(--color-primary-600)' }} />
<div className="p-3 rounded-full" style={{ backgroundColor: 'var(--bg-tertiary)' }}>
<Bot className="w-8 h-8" style={{ color: 'var(--color-primary)' }} />
</div>
<div className="flex-1">
<h2 className="text-2xl font-bold mb-1" style={{ color: 'var(--text-primary)' }}>
@@ -210,9 +247,9 @@ export function OrchestrationSummaryCard({ summary, loading }: OrchestrationSumm
)}
{/* Reasoning Inputs (How decisions were made) */}
<div className="rounded-lg p-4" style={{ backgroundColor: 'rgba(255, 255, 255, 0.6)' }}>
<div className="rounded-lg p-4" style={{ backgroundColor: 'var(--surface-secondary)', border: '1px solid var(--border-primary)' }}>
<div className="flex items-center gap-2 mb-3">
<Brain className="w-5 h-5" style={{ color: 'var(--color-primary-600)' }} />
<Brain className="w-5 h-5" style={{ color: 'var(--color-primary)' }} />
<h3 className="font-bold" style={{ color: 'var(--text-primary)' }}>{t('jtbd.orchestration_summary.based_on')}</h3>
</div>
@@ -260,13 +297,13 @@ export function OrchestrationSummaryCard({ summary, loading }: OrchestrationSumm
<div
className="mt-4 p-4 border rounded-lg"
style={{
backgroundColor: 'var(--color-warning-50)',
borderColor: 'var(--color-warning-200)',
backgroundColor: 'var(--bg-tertiary)',
borderColor: 'var(--color-warning)',
}}
>
<div className="flex items-center gap-2">
<FileText className="w-5 h-5" style={{ color: 'var(--color-warning-600)' }} />
<p className="text-sm font-medium" style={{ color: 'var(--color-warning-900)' }}>
<FileText className="w-5 h-5" style={{ color: 'var(--color-warning)' }} />
<p className="text-sm font-medium" style={{ color: 'var(--text-primary)' }}>
{t('jtbd.orchestration_summary.actions_required', {
count: summary.userActionsRequired,
})}