refactor(ui): redesign trade plans workflow shell
This commit is contained in:
parent
0743c16b71
commit
0144124d0d
@ -971,12 +971,14 @@ export function SimpleView() {
|
|||||||
description="Create and manage short-term trade plans, then convert filled positions into long-term holds when you want to stop automated exits."
|
description="Create and manage short-term trade plans, then convert filled positions into long-term holds when you want to stop automated exits."
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="grid gap-8 xl:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)]">
|
<div className="grid gap-8 xl:grid-cols-[minmax(0,1.05fr)_minmax(380px,0.95fr)]">
|
||||||
<Card>
|
<Card className="overflow-hidden">
|
||||||
<CardHeader>
|
<CardHeader className="border-b border-[var(--border)] bg-[var(--card-elevated)]/80 p-6">
|
||||||
<div>
|
<div>
|
||||||
<CardTitle className="uppercase">{editingSetupId ? 'Edit setup' : 'New setup'}</CardTitle>
|
<CardTitle>{editingSetupId ? 'Edit trade plan' : 'Create trade plan'}</CardTitle>
|
||||||
<CardDescription>Build a short-term buy plan or attach a managed profit exit to an existing holding.</CardDescription>
|
<CardDescription className="mt-2 max-w-2xl leading-6">
|
||||||
|
Build a guided plan with clear setup, instrument, price, sizing, trigger, and review steps before automation is armed.
|
||||||
|
</CardDescription>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@ -989,14 +991,20 @@ export function SimpleView() {
|
|||||||
}}
|
}}
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
className="uppercase tracking-[0.2em]"
|
|
||||||
>
|
>
|
||||||
Reset
|
Reset
|
||||||
</Button>
|
</Button>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
|
|
||||||
<CardContent>
|
<CardContent className="p-6">
|
||||||
<form className="space-y-6" onSubmit={handleSubmit}>
|
<form className="space-y-5" onSubmit={handleSubmit}>
|
||||||
|
<section className="rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card-elevated)] p-5">
|
||||||
|
<div className="mb-4">
|
||||||
|
<div className="text-sm font-bold text-[var(--foreground)]">1. Setup type</div>
|
||||||
|
<p className="mt-1 text-sm leading-6 text-[var(--muted-foreground)]">
|
||||||
|
Choose whether this plan opens a new position or manages profit-taking for an existing holding.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@ -1006,15 +1014,16 @@ export function SimpleView() {
|
|||||||
updateDraft('side', 'buy');
|
updateDraft('side', 'buy');
|
||||||
}}
|
}}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className={`rounded-[1.25rem] border px-4 py-4 text-left transition ${
|
className={`h-auto justify-start rounded-[1.25rem] border px-5 py-5 text-left transition ${
|
||||||
draft.side === 'buy'
|
draft.side === 'buy'
|
||||||
? 'border-[var(--primary)] bg-[var(--accent-soft)]'
|
? 'border-[var(--primary)] bg-[var(--accent-soft)]'
|
||||||
: 'border-[var(--border)] bg-[var(--card-elevated)]'
|
: 'border-[var(--border)] bg-[var(--card-elevated)]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="text-[11px] font-black uppercase tracking-[0.24em] text-[var(--muted-foreground)]">Create plan</div>
|
<div>
|
||||||
<div className="mt-1 text-sm font-semibold text-[var(--foreground)]">New short-term buy plan</div>
|
<div className="text-sm font-bold text-[var(--foreground)]">New short-term buy plan</div>
|
||||||
<div className="mt-1 text-sm text-[var(--muted-foreground)]">Arm a dip-buy trigger and let the app manage the profit exit after fill.</div>
|
<div className="mt-2 text-sm font-normal leading-6 text-[var(--muted-foreground)]">Arm a dip-buy trigger and let the app manage the profit exit after fill.</div>
|
||||||
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
@ -1027,21 +1036,23 @@ export function SimpleView() {
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
className={`rounded-[1.25rem] border px-4 py-4 text-left transition ${
|
className={`h-auto justify-start rounded-[1.25rem] border px-5 py-5 text-left transition ${
|
||||||
draft.side === 'sell'
|
draft.side === 'sell'
|
||||||
? 'border-[var(--primary)] bg-[var(--accent-soft)]'
|
? 'border-[var(--primary)] bg-[var(--accent-soft)]'
|
||||||
: 'border-[var(--border)] bg-[var(--card-elevated)]'
|
: 'border-[var(--border)] bg-[var(--card-elevated)]'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<div className="text-[11px] font-black uppercase tracking-[0.24em] text-[var(--muted-foreground)]">Manage holding</div>
|
<div>
|
||||||
<div className="mt-1 text-sm font-semibold text-[var(--foreground)]">Attach an exit plan</div>
|
<div className="text-sm font-bold text-[var(--foreground)]">Manage an existing holding</div>
|
||||||
<div className="mt-1 text-sm text-[var(--muted-foreground)]">Choose an existing holding and place it back under managed profit-taking.</div>
|
<div className="mt-2 text-sm font-normal leading-6 text-[var(--muted-foreground)]">Choose a filled holding and place it back under managed profit-taking.</div>
|
||||||
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
{draft.side === 'sell' && (
|
{draft.side === 'sell' && (
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card-elevated)] p-5">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Existing holding</span>
|
<span className="ux-field-label">Existing holding</span>
|
||||||
<Select
|
<Select
|
||||||
value={selectedHoldingTradeId || ''}
|
value={selectedHoldingTradeId || ''}
|
||||||
onChange={(e: ChangeEvent<HTMLSelectElement>) => {
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => {
|
||||||
@ -1056,15 +1067,22 @@ export function SimpleView() {
|
|||||||
label: `${holding.symbol} · ${holding.size} @ ${holding.entryPrice.toFixed(4)}`,
|
label: `${holding.symbol} · ${holding.size} @ ${holding.entryPrice.toFixed(4)}`,
|
||||||
}))}
|
}))}
|
||||||
/>
|
/>
|
||||||
<span className="block text-[11px] text-[var(--muted-foreground)]">
|
<span className="ux-helper-text">
|
||||||
Trade Plans can manage an existing filled holding by attaching a profit exit target to it.
|
Trade Plans can manage an existing filled holding by attaching a profit exit target to it.
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<section className="rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card-elevated)] p-5">
|
||||||
|
<div className="mb-4">
|
||||||
|
<div className="text-sm font-bold text-[var(--foreground)]">2. Instrument and market price</div>
|
||||||
|
<p className="mt-1 text-sm leading-6 text-[var(--muted-foreground)]">
|
||||||
|
Select the symbol and confirm the reference price that automation will use for trigger calculations.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Symbol</span>
|
<span className="ux-field-label">Symbol</span>
|
||||||
<Input
|
<Input
|
||||||
value={draft.symbol}
|
value={draft.symbol}
|
||||||
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
||||||
@ -1089,11 +1107,11 @@ export function SimpleView() {
|
|||||||
<option key={symbol} value={symbol} />
|
<option key={symbol} value={symbol} />
|
||||||
))}
|
))}
|
||||||
</datalist>
|
</datalist>
|
||||||
<span className="block text-[11px] text-[var(--muted-foreground)]">
|
<span className="ux-helper-text">
|
||||||
Start typing to pick a supported symbol. Suggestions come from live market symbols plus common supported assets.
|
Start typing to pick a supported symbol. Suggestions come from live market symbols plus common supported assets.
|
||||||
</span>
|
</span>
|
||||||
{normalizedSymbol && !isSuggestedSymbol ? (
|
{normalizedSymbol && !isSuggestedSymbol ? (
|
||||||
<span className="block text-[11px] text-amber-700 dark:text-amber-300">
|
<span className="block text-sm text-[var(--bl-warning)]">
|
||||||
This symbol is not in the current supported suggestions. Double-check it before saving.
|
This symbol is not in the current supported suggestions. Double-check it before saving.
|
||||||
</span>
|
</span>
|
||||||
) : null}
|
) : null}
|
||||||
@ -1132,32 +1150,19 @@ export function SimpleView() {
|
|||||||
) : null}
|
) : null}
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label className="space-y-2">
|
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Setup type</span>
|
|
||||||
<Select
|
|
||||||
value={draft.side}
|
|
||||||
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('side', e.target.value as SimpleSide)}
|
|
||||||
options={[
|
|
||||||
{ value: 'buy', label: 'Buy the dip + profit exit' },
|
|
||||||
{ value: 'sell', label: 'Manage existing holding at profit' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-4 md:grid-cols-[minmax(0,1fr)_auto]">
|
<div className="grid gap-4 md:grid-cols-[minmax(0,1fr)_auto]">
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Market price (auto-fetched)</span>
|
<span className="ux-field-label">Market price</span>
|
||||||
<Input
|
<Input
|
||||||
value={draft.currentMarketPrice}
|
value={draft.currentMarketPrice}
|
||||||
readOnly
|
readOnly
|
||||||
className="bg-[var(--muted)] text-[var(--foreground)]"
|
className="bg-[var(--muted)] text-[var(--foreground)]"
|
||||||
/>
|
/>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<span className="block text-[11px] text-[var(--muted-foreground)]">
|
<span className="ux-helper-text">
|
||||||
Uses live market price when available. Outside market hours, it falls back to the latest close.
|
Uses live market price when available. Outside market hours, it falls back to the latest close.
|
||||||
</span>
|
</span>
|
||||||
<span className="block text-[11px] text-[var(--muted-foreground)]">
|
<span className="block text-sm text-[var(--muted-foreground)]">
|
||||||
Price source:{' '}
|
Price source:{' '}
|
||||||
<span className="font-semibold text-[var(--foreground)]">
|
<span className="font-semibold text-[var(--foreground)]">
|
||||||
{marketPriceSource === 'live'
|
{marketPriceSource === 'live'
|
||||||
@ -1174,7 +1179,7 @@ export function SimpleView() {
|
|||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => void handleLoadMarketPrice()}
|
onClick={() => void handleLoadMarketPrice()}
|
||||||
className="self-end uppercase tracking-[0.2em]"
|
className="self-start md:self-end"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
disabled={loadingPrice || !normalizedSymbol}
|
disabled={loadingPrice || !normalizedSymbol}
|
||||||
>
|
>
|
||||||
@ -1184,12 +1189,21 @@ export function SimpleView() {
|
|||||||
</span>
|
</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card-elevated)] p-5">
|
||||||
|
<div className="mb-4">
|
||||||
|
<div className="text-sm font-bold text-[var(--foreground)]">3. Sizing and notes</div>
|
||||||
|
<p className="mt-1 text-sm leading-6 text-[var(--muted-foreground)]">
|
||||||
|
Define the planned exposure and add context for why the plan should run.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<div className="grid gap-4 md:grid-cols-2">
|
<div className="grid gap-4 md:grid-cols-2">
|
||||||
{draft.side === 'buy' ? (
|
{draft.side === 'buy' ? (
|
||||||
<>
|
<>
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Sizing method</span>
|
<span className="ux-field-label">Sizing method</span>
|
||||||
<Select
|
<Select
|
||||||
value={draft.sizingMode}
|
value={draft.sizingMode}
|
||||||
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('sizingMode', e.target.value as 'quantity' | 'amount')}
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('sizingMode', e.target.value as 'quantity' | 'amount')}
|
||||||
@ -1200,8 +1214,8 @@ export function SimpleView() {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-500">
|
<span className="ux-field-label">
|
||||||
{draft.sizingMode === 'amount' ? 'Spend amount (USD)' : 'Planned quantity'}
|
{draft.sizingMode === 'amount' ? 'Spend amount (USD)' : 'Planned quantity'}
|
||||||
</span>
|
</span>
|
||||||
<Input
|
<Input
|
||||||
@ -1215,17 +1229,17 @@ export function SimpleView() {
|
|||||||
}}
|
}}
|
||||||
placeholder={draft.sizingMode === 'amount' ? '250' : '10'}
|
placeholder={draft.sizingMode === 'amount' ? '250' : '10'}
|
||||||
/>
|
/>
|
||||||
<span className="block text-[11px] text-[var(--muted-foreground)]">
|
<span className="ux-helper-text">
|
||||||
Quantity supports fractional shares/coins. Amount spends an approximate USD budget at trigger time.
|
Quantity supports fractional shares/coins. Amount spends an approximate USD budget at trigger time.
|
||||||
</span>
|
</span>
|
||||||
<span className="block text-[11px] text-[var(--muted-foreground)]">
|
<span className="ux-helper-text">
|
||||||
Use quantity when you know the units you want. Use amount to budget dollars and let the app derive fractional size at entry.
|
Use quantity when you know the units you want. Use amount to budget dollars and let the app derive fractional size at entry.
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-500">
|
<span className="ux-field-label">
|
||||||
Holding size
|
Holding size
|
||||||
</span>
|
</span>
|
||||||
<Input
|
<Input
|
||||||
@ -1238,8 +1252,8 @@ export function SimpleView() {
|
|||||||
</label>
|
</label>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<label className="space-y-2">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Notes</span>
|
<span className="ux-field-label">Notes</span>
|
||||||
<Input
|
<Input
|
||||||
value={draft.notes}
|
value={draft.notes}
|
||||||
onChange={(e: ChangeEvent<HTMLInputElement>) => updateDraft('notes', e.target.value)}
|
onChange={(e: ChangeEvent<HTMLInputElement>) => updateDraft('notes', e.target.value)}
|
||||||
@ -1247,11 +1261,13 @@ export function SimpleView() {
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
{draft.side === 'buy' && (
|
{draft.side === 'buy' && (
|
||||||
<div className="grid gap-4 rounded-[1.5rem] border border-[var(--border)] bg-[var(--card-elevated)] p-5 md:grid-cols-[0.55fr_0.45fr]">
|
<section className="grid gap-4 rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card-elevated)] p-5 md:grid-cols-[0.55fr_0.45fr]">
|
||||||
<div className="space-y-3">
|
<div className="ux-field-stack">
|
||||||
<p className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Drop trigger</p>
|
<p className="text-sm font-bold text-[var(--foreground)]">4. Drop trigger</p>
|
||||||
|
<p className="ux-helper-text">Set the dip condition that should arm the buy entry.</p>
|
||||||
<Select
|
<Select
|
||||||
value={draft.dropMode}
|
value={draft.dropMode}
|
||||||
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('dropMode', e.target.value as TriggerMode)}
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('dropMode', e.target.value as TriggerMode)}
|
||||||
@ -1261,8 +1277,8 @@ export function SimpleView() {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<label className="space-y-3">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">
|
<span className="ux-field-label">
|
||||||
{draft.dropMode === 'dollar' ? 'Drop amount ($)' : 'Drop amount (%)'}
|
{draft.dropMode === 'dollar' ? 'Drop amount ($)' : 'Drop amount (%)'}
|
||||||
</span>
|
</span>
|
||||||
<Input
|
<Input
|
||||||
@ -1271,12 +1287,13 @@ export function SimpleView() {
|
|||||||
placeholder={draft.dropMode === 'dollar' ? '0.00' : '0'}
|
placeholder={draft.dropMode === 'dollar' ? '0.00' : '0'}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="grid gap-4 rounded-[1.5rem] border border-[var(--border)] bg-[var(--card-elevated)] p-5 md:grid-cols-[0.55fr_0.45fr]">
|
<section className="grid gap-4 rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card-elevated)] p-5 md:grid-cols-[0.55fr_0.45fr]">
|
||||||
<div className="space-y-3">
|
<div className="ux-field-stack">
|
||||||
<p className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">Profit exit</p>
|
<p className="text-sm font-bold text-[var(--foreground)]">{draft.side === 'buy' ? '5. Profit exit' : '4. Profit exit'}</p>
|
||||||
|
<p className="ux-helper-text">Define when automation should take profit and close or reduce risk.</p>
|
||||||
<Select
|
<Select
|
||||||
value={draft.profitMode}
|
value={draft.profitMode}
|
||||||
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('profitMode', e.target.value as TriggerMode)}
|
onChange={(e: ChangeEvent<HTMLSelectElement>) => updateDraft('profitMode', e.target.value as TriggerMode)}
|
||||||
@ -1286,8 +1303,8 @@ export function SimpleView() {
|
|||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<label className="space-y-3">
|
<label className="ux-field-stack">
|
||||||
<span className="text-[11px] font-black uppercase tracking-[0.24em] text-zinc-700">
|
<span className="ux-field-label">
|
||||||
{draft.profitMode === 'dollar' ? 'Profit target ($)' : 'Profit target (%)'}
|
{draft.profitMode === 'dollar' ? 'Profit target ($)' : 'Profit target (%)'}
|
||||||
</span>
|
</span>
|
||||||
<Input
|
<Input
|
||||||
@ -1296,13 +1313,13 @@ export function SimpleView() {
|
|||||||
placeholder={draft.profitMode === 'dollar' ? '7.50' : '10'}
|
placeholder={draft.profitMode === 'dollar' ? '7.50' : '10'}
|
||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</section>
|
||||||
|
|
||||||
{draft.side === 'sell' && (
|
{draft.side === 'sell' && (
|
||||||
<div className={`rounded-[1.5rem] border px-4 py-4 text-sm ${
|
<div className={`rounded-[1.5rem] border px-4 py-4 text-sm ${
|
||||||
selectedSellHolding
|
selectedSellHolding
|
||||||
? 'border-emerald-500/20 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300'
|
? 'border-[var(--bl-success)]/20 bg-[var(--bl-success-muted)] text-[var(--bl-success)]'
|
||||||
: 'border-red-500/20 bg-red-500/10 text-red-700 dark:text-red-300'
|
: 'border-[var(--bl-danger)]/20 bg-[var(--bl-danger-muted)] text-[var(--bl-danger)]'
|
||||||
}`}>
|
}`}>
|
||||||
{selectedSellHolding
|
{selectedSellHolding
|
||||||
? `Holding ready: ${selectedSellHolding.symbol} · ${selectedSellHolding.size} units at ${selectedSellHolding.entryPrice.toFixed(4)}. Executed buys also appear in Portfolio as live positions.`
|
? `Holding ready: ${selectedSellHolding.symbol} · ${selectedSellHolding.size} units at ${selectedSellHolding.entryPrice.toFixed(4)}. Executed buys also appear in Portfolio as live positions.`
|
||||||
@ -1311,31 +1328,44 @@ export function SimpleView() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{previewText && (
|
{previewText && (
|
||||||
<div className="rounded-[1.5rem] border border-[var(--border)] bg-[var(--accent-soft)] px-5 py-4 text-sm text-[var(--foreground)]">
|
<section className="rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--accent-soft)] p-5 text-sm leading-6 text-[var(--foreground)]">
|
||||||
{previewText}
|
<div className="mb-1 font-bold">{draft.side === 'buy' ? '6. Review and create' : '5. Review and create'}</div>
|
||||||
|
<div>{previewText}</div>
|
||||||
|
<div className="mt-3 text-[var(--muted-foreground)]">
|
||||||
|
Review the symbol, price source, sizing, and exit target before creating the plan.
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{message && (
|
{message && (
|
||||||
<div className="rounded-2xl border border-emerald-500/20 bg-emerald-500/10 px-4 py-3 text-sm text-emerald-700 dark:text-emerald-300">
|
<div className="rounded-2xl border border-[var(--bl-success)]/20 bg-[var(--bl-success-muted)] px-4 py-3 text-sm text-[var(--bl-success)]">
|
||||||
{message}
|
{message}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{error && (
|
{error && (
|
||||||
<div className="rounded-2xl border border-red-500/20 bg-red-500/10 px-4 py-3 text-sm text-red-700 dark:text-red-300">
|
<div className="rounded-2xl border border-[var(--bl-danger)]/20 bg-[var(--bl-danger-muted)] px-4 py-3 text-sm text-[var(--bl-danger)]">
|
||||||
{error}
|
{error}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
<div className="sticky bottom-4 z-[var(--bl-z-sticky)] rounded-[var(--bl-radius-card)] border border-[var(--border)] bg-[var(--card)]/95 p-4 shadow-[var(--bl-shadow-card)] backdrop-blur">
|
||||||
|
<div className="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||||
|
<div className="text-sm leading-6 text-[var(--muted-foreground)]">
|
||||||
|
{saveButtonDisabled
|
||||||
|
? 'Complete the required setup details before creating the plan.'
|
||||||
|
: 'Ready to save this plan and arm the next automation step.'}
|
||||||
|
</div>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={saveButtonDisabled}
|
disabled={saveButtonDisabled}
|
||||||
className="w-full uppercase tracking-[0.24em]"
|
className="w-full md:w-auto"
|
||||||
size="lg"
|
size="lg"
|
||||||
>
|
>
|
||||||
{submitting ? 'Saving...' : saveButtonLabel}
|
{submitting ? 'Saving...' : saveButtonLabel}
|
||||||
</Button>
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user