Spaces:
Running
Running
File size: 2,952 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 | 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>
);
}
|