a11oy / web /src /components /DefenseDataState.tsx
betterwithage's picture
sync(space): complete build context — fix BUILD_ERROR (CTO)
518343a verified
Raw
History Blame Contribute Delete
2.95 kB
import type { ReactNode } from 'react';
const T = {
surface: 'rgba(255,255,255,0.025)',
border: 'rgba(255,255,255,0.08)',
text: '#f5f5f5',
dim: '#8a8a8a',
muted: '#5e5e5e',
accent: '#c9b787',
};
interface RefreshBarProps {
loading: boolean;
error: string | null;
lastUpdated: string | null;
onRefresh: () => void;
}
export function RefreshBar({ loading, error, lastUpdated, onRefresh }: RefreshBarProps) {
return (
<div className="flex items-center justify-end gap-3 mb-4">
{error ? (
<span className="text-[10px] font-mono" style={{ color: '#ef4444' }}>
ERROR — {error}
</span>
) : lastUpdated ? (
<span className="text-[10px] font-mono" style={{ color: T.muted }}>
Updated {new Date(lastUpdated).toLocaleTimeString()}
</span>
) : null}
<button
onClick={onRefresh}
disabled={loading}
className="px-3 py-1.5 rounded-md text-[10px] font-mono uppercase tracking-widest transition-all"
style={{
background: loading ? 'transparent' : 'rgba(201,183,135,0.08)',
border: `1px solid ${loading ? T.border : 'rgba(201,183,135,0.25)'}`,
color: loading ? T.muted : T.accent,
cursor: loading ? 'wait' : 'pointer',
}}
>
{loading ? 'Refreshing…' : '↻ Refresh'}
</button>
</div>
);
}
interface LoadingStateProps {
label?: string;
}
export function LoadingState({ label = 'Loading defense data…' }: LoadingStateProps) {
return (
<div
className="rounded-lg px-6 py-12 text-center"
style={{ background: T.surface, border: `1px solid ${T.border}` }}
>
<div className="inline-flex items-center gap-3">
<span
className="w-2 h-2 rounded-full animate-pulse"
style={{ background: T.accent }}
/>
<span className="text-xs font-mono" style={{ color: T.dim }}>
{label}
</span>
</div>
</div>
);
}
interface ErrorStateProps {
error: string;
onRetry: () => void;
children?: ReactNode;
}
export function ErrorState({ error, onRetry, children }: ErrorStateProps) {
return (
<div
className="rounded-lg px-6 py-8 text-center"
style={{ background: 'rgba(239,68,68,0.04)', border: '1px solid rgba(239,68,68,0.2)' }}
>
<div className="text-xs font-mono mb-2" style={{ color: '#ef4444' }}>
DEFENSE FEED UNAVAILABLE
</div>
<div className="text-[10px] font-mono mb-4" style={{ color: T.dim }}>
{error}
</div>
{children}
<button
onClick={onRetry}
className="px-3 py-1.5 rounded-md text-[10px] font-mono uppercase tracking-widest"
style={{
background: 'rgba(201,183,135,0.08)',
border: '1px solid rgba(201,183,135,0.25)',
color: T.accent,
cursor: 'pointer',
}}
>
Retry
</button>
</div>
);
}