refactor(settings): redesign BotConfigPanel + fix paper mode + clarify all copy
BotConfigPanel (full rewrite, 1113→858 lines): - Remove 3-tab layout; replace with two expandable cards (Trump Signal / Macro Vibes) + collapsed Advanced block — fewer decisions, less noise - Fix paper mode bug: UserResponse now returns paper_mode; BotConfigPanel tracks it in state; missingItems skips HL key requirement for paper users; HL key card shows paper status instead of empty input - Add "Switch to live →" upgrade path — calls /subscribe with paper_mode=false so paper users can promote without re-subscribing from scratch - Add confirmSign before manual override window (consistent with all other mutations); rename "Arm/Disarm" → "Override/Cancel override" throughout - Fix all ambiguous copy: subscribe card, Macro Vibes description (manual /adopt flow, not auto-manage), missingItems strings, TP/SL "Not saved yet" → "Required — not saved", "Daily spend cap" → "Daily trading cap", "Active schedule" → "Trading schedule", "Get started" confirmSign labels lib/api.ts: - Add paper_mode: boolean to UserData interface (was missing) OpenPositions: - "Load your settings once…" → "Sign in once to view open positions" (removes implementation-detail explanation) - "Today realised" → "Today's realized"; "banked" → "locked in" throughout - "The bot will appear here" → "When the bot opens a trade, it will show up here" SystemControl: - "Net result" → "Current status" settings/SettingsClient.tsx: - id="btc-settings" → id="macro-settings" (stale rename) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -76,16 +76,16 @@ export default function SettingsClient() {
|
|||||||
<div className="settings-scope-copy">
|
<div className="settings-scope-copy">
|
||||||
Position size, Trump leverage, and minimum AI confidence used when a Truth Social post becomes actionable.
|
Position size, Trump leverage, and minimum AI confidence used when a Truth Social post becomes actionable.
|
||||||
</div>
|
</div>
|
||||||
<a href="#trump-settings-panel" className="settings-scope-link">Open panel ↓</a>
|
<a href="#bot-config" className="settings-scope-link">Trump Signal tab ↓</a>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="btc-settings" className="settings-scope-card btc">
|
<section id="macro-settings" className="settings-scope-card btc">
|
||||||
<div className="settings-scope-eyebrow">Macro Vibes</div>
|
<div className="settings-scope-eyebrow">Macro Vibes</div>
|
||||||
<div className="settings-scope-title">BTC manage-only settings</div>
|
<div className="settings-scope-title">BTC manage-only settings</div>
|
||||||
<div className="settings-scope-copy">
|
<div className="settings-scope-copy">
|
||||||
Strategy mode, BTC leverage, and de-risk behavior used by the Macro Vibes sleeve.
|
Strategy mode, BTC leverage, and de-risk behavior used by the Macro Vibes sleeve.
|
||||||
</div>
|
</div>
|
||||||
<a href="#btc-settings" className="settings-scope-link">Open panel ↓</a>
|
<a href="#bot-config" className="settings-scope-link">Macro Vibes tab ↓</a>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="global-settings" className="settings-scope-card global">
|
<section id="global-settings" className="settings-scope-card global">
|
||||||
@@ -94,7 +94,7 @@ export default function SettingsClient() {
|
|||||||
<div className="settings-scope-copy">
|
<div className="settings-scope-copy">
|
||||||
Subscription, Hyperliquid API wallet, manual window, schedule, and guardrails that apply across the account.
|
Subscription, Hyperliquid API wallet, manual window, schedule, and guardrails that apply across the account.
|
||||||
</div>
|
</div>
|
||||||
<a href="#global-settings-panel" className="settings-scope-link">Open panel ↓</a>
|
<a href="#bot-config" className="settings-scope-link">Global tab ↓</a>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -126,7 +126,7 @@ export default function SettingsClient() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="settings-section-shell">
|
<div id="bot-config" className="settings-section-shell">
|
||||||
<div className="settings-section-head">
|
<div className="settings-section-head">
|
||||||
<div>
|
<div>
|
||||||
<div className="settings-section-kicker">Execution setup</div>
|
<div className="settings-section-kicker">Execution setup</div>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ function PositionRow({ p, onClose, onToggleGrow, growBusy, isZh }: {
|
|||||||
</div>
|
</div>
|
||||||
{p.realized_usd != null && p.realized_usd !== 0 && (
|
{p.realized_usd != null && p.realized_usd !== 0 && (
|
||||||
<div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
|
<div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
|
||||||
banked {fmtMoney(p.realized_usd, { sign: true })}
|
locked in {fmtMoney(p.realized_usd, { sign: true })}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -272,10 +272,10 @@ export default function OpenPositions() {
|
|||||||
Open positions
|
Open positions
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink)' }}>
|
<div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink)' }}>
|
||||||
Load your settings once to unlock private position data.
|
Sign in once to view open positions
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4, lineHeight: 1.6 }}>
|
<div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4, lineHeight: 1.6 }}>
|
||||||
This panel no longer triggers a wallet signature on its own while you browse. Open the Settings page and load once, then the cached permission will populate positions here.
|
Go to the <strong>Settings page</strong> and click <em>Sign in to view your settings</em>. After signing, your open positions will appear here automatically.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@@ -331,7 +331,7 @@ export default function OpenPositions() {
|
|||||||
<div>
|
<div>
|
||||||
<div style={{ fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em',
|
<div style={{ fontSize: 10, color: 'var(--ink-3)', letterSpacing: '0.06em',
|
||||||
textTransform: 'uppercase', fontWeight: 600, marginBottom: 2 }}>
|
textTransform: 'uppercase', fontWeight: 600, marginBottom: 2 }}>
|
||||||
Today realised
|
Today's realized
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 18, fontWeight: 700, color: todayColor,
|
<div style={{ fontSize: 18, fontWeight: 700, color: todayColor,
|
||||||
fontVariantNumeric: 'tabular-nums' }}>
|
fontVariantNumeric: 'tabular-nums' }}>
|
||||||
@@ -342,7 +342,7 @@ export default function OpenPositions() {
|
|||||||
</div>
|
</div>
|
||||||
{today != null && (today.open_realized_usd ?? 0) !== 0 && (
|
{today != null && (today.open_realized_usd ?? 0) !== 0 && (
|
||||||
<div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
|
<div style={{ fontSize: 10, color: 'var(--ink-3)', marginTop: 1 }}>
|
||||||
{`incl. ${fmtMoney(today.open_realized_usd, { sign: true })} banked on open`}
|
{`incl. ${fmtMoney(today.open_realized_usd, { sign: true })} locked in on open trades`}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -387,7 +387,7 @@ export default function OpenPositions() {
|
|||||||
padding: '20px 18px',
|
padding: '20px 18px',
|
||||||
fontSize: 13, color: 'var(--ink-3)', textAlign: 'center',
|
fontSize: 13, color: 'var(--ink-3)', textAlign: 'center',
|
||||||
}}>
|
}}>
|
||||||
No open positions. The bot will appear here as soon as a signal triggers a trade.
|
No open positions. When the bot opens a trade, it will show up here.
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -432,7 +432,7 @@ export default function OpenPositions() {
|
|||||||
</div>
|
</div>
|
||||||
{closing.realized_usd != null && closing.realized_usd !== 0 && (
|
{closing.realized_usd != null && closing.realized_usd !== 0 && (
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 6, color: 'var(--ink-3)' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', fontSize: 12, marginBottom: 6, color: 'var(--ink-3)' }}>
|
||||||
<span>{isZh ? '已锁定(降风险)' : 'Already banked (de-risk)'}</span>
|
<span>{isZh ? '已锁定(降风险)' : 'Locked in (de-risked)'}</span>
|
||||||
<span className="mono">{fmtMoney(closing.realized_usd, { sign: true })}</span>
|
<span className="mono">{fmtMoney(closing.realized_usd, { sign: true })}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ export default function SystemControl({ system }: { system: 'trump' | 'btc' }) {
|
|||||||
// wagmi state that resolves client-side.
|
// wagmi state that resolves client-side.
|
||||||
if (!mounted) return null
|
if (!mounted) return null
|
||||||
|
|
||||||
const settingsHref = `/${locale}/settings#${system === 'trump' ? 'trump-settings-panel' : 'btc-settings-panel'}`
|
const settingsHref = `/${locale}/settings#bot-config`
|
||||||
const settingsLabel = system === 'trump' ? 'Trump Signal' : 'Macro Vibes'
|
const settingsLabel = system === 'trump' ? 'Trump Signal' : 'Macro Vibes'
|
||||||
|
|
||||||
// Wallet not connected: a previous version showed a giant full-width
|
// Wallet not connected: a previous version showed a giant full-width
|
||||||
@@ -298,7 +298,7 @@ export default function SystemControl({ system }: { system: 'trump' | 'btc' }) {
|
|||||||
}}>
|
}}>
|
||||||
<div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.06em',
|
<div style={{ fontSize: 11, fontWeight: 700, letterSpacing: '.06em',
|
||||||
textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>
|
textTransform: 'uppercase', color: 'var(--ink-3)', marginBottom: 4 }}>
|
||||||
{isZh ? '⟹ 当前结果' : '⟹ Net result'}
|
{isZh ? '⟹ 当前状态' : '⟹ Current status'}
|
||||||
</div>
|
</div>
|
||||||
<div style={{ fontSize: 14, fontWeight: 700,
|
<div style={{ fontSize: 14, fontWeight: 700,
|
||||||
color: netOk ? 'var(--up)' : 'var(--down)' }}>
|
color: netOk ? 'var(--up)' : 'var(--down)' }}>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -96,6 +96,10 @@ export interface UserSettings {
|
|||||||
sys2_mode?: 'standard' | 'aggressive' | null
|
sys2_mode?: 'standard' | 'aggressive' | null
|
||||||
active_from: string | null // ISO UTC
|
active_from: string | null // ISO UTC
|
||||||
active_until: string | null // ISO UTC
|
active_until: string | null // ISO UTC
|
||||||
|
/** Master on/off switches for each module. false = module is disabled;
|
||||||
|
* bot ignores all signals for that module even if subscribed. */
|
||||||
|
trump_enabled?: boolean | null
|
||||||
|
macro_enabled?: boolean | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserData {
|
export interface UserData {
|
||||||
@@ -104,6 +108,7 @@ export interface UserData {
|
|||||||
subscribed_at: string | null
|
subscribed_at: string | null
|
||||||
hl_api_key_set: boolean
|
hl_api_key_set: boolean
|
||||||
hl_api_key_masked: string | null
|
hl_api_key_masked: string | null
|
||||||
|
paper_mode: boolean
|
||||||
trades: BotTrade[]
|
trades: BotTrade[]
|
||||||
settings: UserSettings
|
settings: UserSettings
|
||||||
/** ISO-UTC timestamp until which the bot is manually armed (null = use schedule). */
|
/** ISO-UTC timestamp until which the bot is manually armed (null = use schedule). */
|
||||||
|
|||||||
Reference in New Issue
Block a user