Spaces:
Running
Running
File size: 5,985 Bytes
518343a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | import { useQuery } from '@tanstack/react-query';
import { ArrowRight, Sparkles, TrendingUp } from 'lucide-react';
interface CapabilityProposal {
id: string;
title: string;
description: string;
targetAgent: string;
priority: string;
status: string;
impactArea?: string;
estimatedEffort?: string;
}
interface ProposalsResponse {
proposals: CapabilityProposal[];
total: number;
}
const PRIORITY_COLOR: Record<string, string> = {
P0: '#ef4444',
P1: '#f59e0b',
P2: '#3b82f6',
P3: '#6b7280',
};
const STATUS_LABEL: Record<string, string> = {
new: 'New',
in_progress: 'In Review',
approved: 'Approved',
deployed: 'Live',
rejected: 'Rejected',
};
async function fetchProposals(): Promise<CapabilityProposal[]> {
const res = await fetch('/api/helios/proposals?status=new,in_progress&limit=4');
if (!res.ok) return [];
const data: ProposalsResponse = await res.json();
return data.proposals ?? [];
}
export function HeliosProposalsInbox() {
const { data: proposals = [], isLoading } = useQuery({
queryKey: ['helios-proposals-inbox'],
queryFn: fetchProposals,
staleTime: 60_000,
retry: false,
});
return (
<div
className="rounded-xl overflow-hidden"
style={{
backgroundColor: 'var(--color-bg-elevated)',
border: '1px solid var(--color-surface-border)',
padding: '24px',
}}
>
<div className="flex items-center justify-between mb-4 flex-wrap gap-2">
<div className="flex items-center gap-2">
<Sparkles className="w-4 h-4" style={{ color: '#f59e0b' }} />
<span
className="text-xs font-bold uppercase tracking-widest"
style={{ color: 'var(--color-fg-muted)' }}
>
HELIOS Capability Proposals
</span>
</div>
<a
href="/helios/"
target="_blank"
rel="noopener noreferrer"
className="flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider px-2 py-1 rounded"
style={{
color: '#f59e0b',
backgroundColor: 'color-mix(in srgb, #f59e0b 10%, transparent)',
border: '1px solid color-mix(in srgb, #f59e0b 25%, transparent)',
textDecoration: 'none',
}}
>
Open HELIOS <ArrowRight className="w-2.5 h-2.5" />
</a>
</div>
{isLoading ? (
<div className="flex flex-col gap-2">
{[0, 1, 2].map((i) => (
<div
key={i}
className="h-16 rounded-lg animate-pulse"
style={{ backgroundColor: 'var(--color-surface-border)' }}
/>
))}
</div>
) : proposals.length === 0 ? (
<p className="text-xs text-center py-8" style={{ color: 'var(--color-fg-muted)' }}>
No pending proposals from HELIOS
</p>
) : (
<div className="flex flex-col gap-2">
{proposals.map((p) => {
const color = PRIORITY_COLOR[p.priority] ?? '#6b7280';
return (
<div
key={p.id}
className="rounded-lg p-3 flex items-start gap-3"
style={{
backgroundColor: 'var(--color-bg-base)',
border: '1px solid var(--color-surface-border)',
borderLeftWidth: '3px',
borderLeftColor: color,
}}
>
<TrendingUp
className="w-4 h-4 mt-0.5 shrink-0"
style={{ color }}
/>
<div className="flex-1 min-w-0">
<div className="flex items-start justify-between gap-2">
<p
className="text-xs font-semibold leading-snug truncate"
style={{ color: 'var(--color-fg-primary)' }}
>
{p.title}
</p>
<span
className="text-[10px] font-bold px-1.5 py-0.5 rounded shrink-0"
style={{
color,
backgroundColor: `color-mix(in srgb, ${color} 12%, transparent)`,
}}
>
{STATUS_LABEL[p.status] ?? p.status}
</span>
</div>
<div className="flex items-center gap-2 mt-0.5">
<span
className="text-[10px]"
style={{ color: 'var(--color-fg-muted)' }}
>
{p.targetAgent}
</span>
{p.impactArea && (
<>
<span className="text-[10px]" style={{ color: 'var(--color-fg-muted)' }}>
·
</span>
<span className="text-[10px]" style={{ color: 'var(--color-fg-muted)' }}>
{p.impactArea}
</span>
</>
)}
{p.estimatedEffort && (
<>
<span className="text-[10px]" style={{ color: 'var(--color-fg-muted)' }}>
·
</span>
<span
className="text-[10px] font-mono"
style={{ color: 'var(--color-fg-muted)' }}
>
{p.estimatedEffort}
</span>
</>
)}
</div>
</div>
<span
className="text-[11px] font-bold font-mono shrink-0"
style={{ color }}
>
{p.priority}
</span>
</div>
);
})}
</div>
)}
</div>
);
}
|