feat: competitive intelligence & historical pattern matching layer
This commit is contained in:
@@ -5,6 +5,10 @@ import {
|
||||
usePendingApprovals,
|
||||
useReviewApproval,
|
||||
useActiveLockouts,
|
||||
useMacroStatus,
|
||||
useToggleMacro,
|
||||
useCompetitiveStatus,
|
||||
useToggleCompetitive,
|
||||
} from '../api/hooks';
|
||||
import { StatusBadge, LoadingSpinner, Card } from '../components/ui';
|
||||
|
||||
@@ -12,9 +16,15 @@ export function TradingPage() {
|
||||
const { data: config, isLoading: configLoading } = useTradingConfig();
|
||||
const { data: approvals } = usePendingApprovals();
|
||||
const { data: lockouts } = useActiveLockouts();
|
||||
const { data: macroStatus } = useMacroStatus();
|
||||
const { data: competitiveStatus } = useCompetitiveStatus();
|
||||
const setMode = useSetTradingMode();
|
||||
const reviewApproval = useReviewApproval();
|
||||
const toggleMacro = useToggleMacro();
|
||||
const toggleCompetitive = useToggleCompetitive();
|
||||
const [confirmMode, setConfirmMode] = useState<string | null>(null);
|
||||
const [confirmMacroToggle, setConfirmMacroToggle] = useState(false);
|
||||
const [confirmCompetitiveToggle, setConfirmCompetitiveToggle] = useState(false);
|
||||
|
||||
if (configLoading) return <LoadingSpinner />;
|
||||
|
||||
@@ -73,6 +83,126 @@ export function TradingPage() {
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* Macro Signal Layer Toggle */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">Macro Signal Layer</h2>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => setConfirmMacroToggle(true)}
|
||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 focus:ring-offset-surface-900 ${
|
||||
macroStatus?.enabled ? 'bg-brand-600' : 'bg-surface-700'
|
||||
}`}
|
||||
role="switch"
|
||||
aria-checked={macroStatus?.enabled ?? false}
|
||||
aria-label="Toggle macro signal layer"
|
||||
>
|
||||
<span
|
||||
className={`pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow ring-0 transition-transform ${
|
||||
macroStatus?.enabled ? 'translate-x-5' : 'translate-x-0'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
<span className="text-sm text-gray-300">
|
||||
{macroStatus?.enabled ? 'Enabled' : 'Disabled'}
|
||||
</span>
|
||||
{macroStatus?.toggled_at && (
|
||||
<span className="text-xs text-gray-500">
|
||||
Last changed: {new Date(macroStatus.toggled_at).toLocaleString()}
|
||||
{macroStatus.toggled_by && ` by ${macroStatus.toggled_by}`}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Confirmation dialog for macro toggle */}
|
||||
{confirmMacroToggle && (
|
||||
<div className="mt-4 rounded-lg border border-orange-700/50 bg-orange-900/20 p-4">
|
||||
<p className="text-sm text-orange-300">
|
||||
Are you sure you want to {macroStatus?.enabled ? 'disable' : 'enable'} the macro signal layer?
|
||||
{macroStatus?.enabled
|
||||
? ' Disabling will exclude macro signals from trend summaries and recommendations.'
|
||||
: ' Enabling will include global event macro signals in trend summaries and recommendations.'}
|
||||
</p>
|
||||
<div className="mt-3 flex gap-2">
|
||||
<button
|
||||
onClick={() => {
|
||||
toggleMacro.mutate(!macroStatus?.enabled);
|
||||
setConfirmMacroToggle(false);
|
||||
}}
|
||||
className="rounded-md bg-orange-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-orange-700"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setConfirmMacroToggle(false)}
|
||||
className="rounded-md border border-surface-700 px-3 py-1.5 text-sm text-gray-400 hover:bg-surface-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* Competitive Signal Layer Toggle */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">Competitive Signal Layer</h2>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={() => setConfirmCompetitiveToggle(true)}
|
||||
className={`relative inline-flex h-6 w-11 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 focus:ring-offset-surface-900 ${
|
||||
competitiveStatus?.enabled ? 'bg-brand-600' : 'bg-surface-700'
|
||||
}`}
|
||||
role="switch"
|
||||
aria-checked={competitiveStatus?.enabled ?? false}
|
||||
aria-label="Toggle competitive signal layer"
|
||||
>
|
||||
<span
|
||||
className={`pointer-events-none inline-block h-5 w-5 rounded-full bg-white shadow ring-0 transition-transform ${
|
||||
competitiveStatus?.enabled ? 'translate-x-5' : 'translate-x-0'
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
<span className="text-sm text-gray-300">
|
||||
{competitiveStatus?.enabled ? 'Enabled' : 'Disabled'}
|
||||
</span>
|
||||
{competitiveStatus?.toggled_at && (
|
||||
<span className="text-xs text-gray-500">
|
||||
Last changed: {new Date(competitiveStatus.toggled_at).toLocaleString()}
|
||||
{competitiveStatus.toggled_by && ` by ${competitiveStatus.toggled_by}`}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Confirmation dialog for competitive toggle */}
|
||||
{confirmCompetitiveToggle && (
|
||||
<div className="mt-4 rounded-lg border border-orange-700/50 bg-orange-900/20 p-4">
|
||||
<p className="text-sm text-orange-300">
|
||||
Are you sure you want to {competitiveStatus?.enabled ? 'disable' : 'enable'} the competitive signal layer?
|
||||
{competitiveStatus?.enabled
|
||||
? ' Disabling will exclude historical pattern and competitive signals from trend summaries and recommendations.'
|
||||
: ' Enabling will include historical pattern and competitive signals in trend summaries and recommendations.'}
|
||||
</p>
|
||||
<div className="mt-3 flex gap-2">
|
||||
<button
|
||||
onClick={() => {
|
||||
toggleCompetitive.mutate(!competitiveStatus?.enabled);
|
||||
setConfirmCompetitiveToggle(false);
|
||||
}}
|
||||
className="rounded-md bg-orange-600 px-3 py-1.5 text-sm font-medium text-white hover:bg-orange-700"
|
||||
>
|
||||
Confirm
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setConfirmCompetitiveToggle(false)}
|
||||
className="rounded-md border border-surface-700 px-3 py-1.5 text-sm text-gray-400 hover:bg-surface-800"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
|
||||
{/* Pending Approvals */}
|
||||
<Card>
|
||||
<h2 className="mb-3 text-sm font-medium text-gray-400">
|
||||
|
||||
Reference in New Issue
Block a user