exec-ops-env / frontend /src /components /InboxPanel.js
saaheerpurav's picture
first commit
1bb18a0
Raw
History Blame Contribute Delete
4.5 kB
import React from 'react';
const PRIORITY_CONFIG = {
5: { color: '#ef4444', bg: 'rgba(239,68,68,0.12)', label: 'CRITICAL', textColor: '#fca5a5' },
4: { color: '#f59e0b', bg: 'rgba(245,158,11,0.12)', label: 'HIGH', textColor: '#fcd34d' },
3: { color: '#eab308', bg: 'rgba(234,179,8,0.10)', label: 'MEDIUM', textColor: '#fde047' },
2: { color: '#22c55e', bg: 'rgba(34,197,94,0.10)', label: 'LOW', textColor: '#86efac' },
1: { color: '#94a3b8', bg: 'rgba(148,163,184,0.08)', label: 'MINIMAL', textColor: '#cbd5e1' },
};
const ACTION_ICONS = {
reply: '↩',
schedule: '📅',
delegate: '→',
ignore: '✕',
};
function UrgencyRing({ urgency, priority }) {
const pct = Math.max(0, Math.min(1, urgency));
const size = 36;
const stroke = 3;
const r = (size - stroke * 2) / 2;
const circ = 2 * Math.PI * r;
const dash = circ * pct;
const color = PRIORITY_CONFIG[priority]?.color || '#94a3b8';
return (
<div className="urgency-ring-wrapper" title={`Urgency: ${(urgency * 100).toFixed(0)}%`}>
<svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
<circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="rgba(255,255,255,0.08)" strokeWidth={stroke} />
<circle
cx={size / 2} cy={size / 2} r={r}
fill="none"
stroke={color}
strokeWidth={stroke}
strokeDasharray={`${dash} ${circ}`}
strokeLinecap="round"
style={{ transition: 'stroke-dasharray 0.6s ease, stroke 0.3s' }}
opacity={0.3 + pct * 0.7}
/>
</svg>
<span className="urgency-pct" style={{ color }}>{(urgency * 100).toFixed(0)}</span>
</div>
);
}
export default function InboxPanel({ emails, selectedEmailId, onSelect, isAutoRunning }) {
const sorted = [...emails].sort((a, b) => {
if (a.handled !== b.handled) return a.handled ? 1 : -1;
if (b.priority !== a.priority) return b.priority - a.priority;
return b.urgency - a.urgency;
});
return (
<div className="panel inbox-panel">
<div className="panel-header">
<span className="panel-title">📥 Inbox</span>
<span className="panel-badge">{emails.filter(e => !e.handled).length} unhandled</span>
</div>
<div className="email-list">
{sorted.map(email => {
const cfg = PRIORITY_CONFIG[email.priority] || PRIORITY_CONFIG[1];
const isSelected = email.id === selectedEmailId;
const isHandled = email.handled;
const isAiFocus = isSelected && isAutoRunning;
return (
<div
key={email.id}
className={`email-card ${isSelected ? 'selected' : ''} ${isHandled ? 'handled' : ''} ${isAiFocus ? 'ai-focus' : ''}`}
style={{
borderLeft: `3px solid ${isHandled ? 'rgba(148,163,184,0.3)' : cfg.color}`,
background: isSelected ? `${cfg.bg}` : isHandled ? 'rgba(15,23,42,0.4)' : cfg.bg,
cursor: isHandled || isAutoRunning ? 'default' : 'pointer',
}}
onClick={() => !isHandled && !isAutoRunning && onSelect && onSelect(email)}
>
<div className="email-header">
<div className="email-meta">
<span
className="priority-badge"
style={{ background: isHandled ? 'rgba(148,163,184,0.15)' : cfg.color, color: isHandled ? '#64748b' : '#fff' }}
>
P{email.priority} {cfg.label}
</span>
{isHandled && (
<span className="action-taken-badge">
{ACTION_ICONS[email.action_taken]} {email.action_taken}
</span>
)}
</div>
{!isHandled && <UrgencyRing urgency={email.urgency} priority={email.priority} />}
{isHandled && <span className="handled-check"></span>}
</div>
<div className="email-sender" style={{ color: isHandled ? '#475569' : cfg.textColor }}>
{email.sender.split('<')[0].trim()}
</div>
<div className="email-subject" style={{ color: isHandled ? '#475569' : '#f1f5f9' }}>
{email.subject}
</div>
{isSelected && !isHandled && (
<div className="email-body">{email.body}</div>
)}
</div>
);
})}
</div>
</div>
);
}