refactor(web): normalize entry form theme surface
This commit is contained in:
parent
df00e977d4
commit
75a3ac4ecf
@ -99,7 +99,7 @@ Current public bundle:
|
||||
- [x] Normalize `web/src/components/StrategyWizard.tsx`
|
||||
- [x] Normalize `web/src/tabs/ReconciliationAuditPanel.tsx`
|
||||
- [x] Normalize `web/src/components/GlobalConfigManager.tsx`
|
||||
- [ ] Normalize `web/src/components/EntryForm.tsx`
|
||||
- [x] Normalize `web/src/components/EntryForm.tsx`
|
||||
- [ ] Normalize remaining old admin/config surfaces
|
||||
- [ ] Remove remaining dark-only bespoke surface systems
|
||||
- [ ] Replace remaining one-off controls with shared primitives where practical
|
||||
|
||||
@ -5,12 +5,18 @@ import { tradingRuntime } from '../lib/runtime';
|
||||
import { createManualEntry, updateManualEntry } from '../lib/manualEntriesApi';
|
||||
import { getPlatformAccessToken } from '../lib/authSession';
|
||||
import { createRequestId } from '../../../shared/request-id.js';
|
||||
import { Button } from './ui/button';
|
||||
import { Input } from './ui/input';
|
||||
|
||||
interface EntryFormProps {
|
||||
onSuccess: () => void;
|
||||
initialData?: any;
|
||||
}
|
||||
|
||||
const tableInputClass = 'h-9 rounded border-[var(--border)] bg-[var(--input)] px-2 py-1 text-sm';
|
||||
const numericInputClass = `${tableInputClass} font-mono text-right`;
|
||||
const checkboxLabelClass = 'flex cursor-pointer items-center text-[10px] text-[var(--muted-foreground)] hover:text-[var(--foreground)]';
|
||||
|
||||
export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
const { user } = useAuth();
|
||||
const [formData, setFormData] = useState({
|
||||
@ -106,7 +112,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
// Remove temp fields from DB payload
|
||||
delete (payload as any).execute_order;
|
||||
|
||||
// --- 🚀 REAL TRADE EXECUTION ---
|
||||
// --- REAL TRADE EXECUTION ---
|
||||
if (formData.execute_order && !initialData) {
|
||||
if (!Number.isFinite(payload.quantity) || !payload.symbol.trim()) {
|
||||
alert('Symbol and a valid quantity are required to execute a trade.');
|
||||
@ -125,7 +131,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
tp: payload.gain_threshold_for_sell
|
||||
};
|
||||
|
||||
const confirmTrade = window.confirm(`🚀 EXECUTE LIVE TRADE (via Bot)?\n(Note: Uses currently configured Bot account)\n\nSymbol: ${payload.symbol}\nSide: BUY\nQty: ${payload.quantity}`);
|
||||
const confirmTrade = window.confirm(`EXECUTE LIVE TRADE (via Bot)?\n(Note: Uses currently configured Bot account)\n\nSymbol: ${payload.symbol}\nSide: BUY\nQty: ${payload.quantity}`);
|
||||
if (!confirmTrade) return;
|
||||
|
||||
const apiUrl = tradingRuntime.tradingApiUrl;
|
||||
@ -145,7 +151,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
throw new Error(`Execution Failed: ${resData.error}`);
|
||||
}
|
||||
|
||||
alert(`✅ Trade Executed! Order ID: ${resData.orderId}`);
|
||||
alert(`Trade Executed! Order ID: ${resData.orderId}`);
|
||||
}
|
||||
|
||||
if (initialData?.stock_instance_id) {
|
||||
@ -185,6 +191,8 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
<th style={{ width: '10%' }} className="text-right">Qty</th>
|
||||
<th style={{ width: '10%' }} className="text-right">Stop Loss</th>
|
||||
<th style={{ width: '10%' }} className="text-right">Take Profit</th>
|
||||
<th style={{ width: '12%' }}>Buy Time</th>
|
||||
<th style={{ width: '10%' }} className="text-right">Exit Price</th>
|
||||
<th style={{ width: '11%' }}>Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@ -192,33 +200,33 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
<tr>
|
||||
{/* Symbol */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="text"
|
||||
name="symbol"
|
||||
required
|
||||
value={formData.symbol}
|
||||
onChange={handleChange}
|
||||
placeholder="BTC/USD"
|
||||
className="bg-transparent border-b border-gray-600 focus:border-blue-500 outline-none w-full py-1 text-sm text-gray-200 placeholder-gray-600"
|
||||
className={tableInputClass}
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* Label */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="text"
|
||||
name="label"
|
||||
value={formData.label}
|
||||
onChange={handleChange}
|
||||
placeholder="Swing"
|
||||
className="bg-transparent border-b border-gray-600 focus:border-blue-500 outline-none w-full py-1 text-sm text-gray-200 placeholder-gray-600"
|
||||
className={tableInputClass}
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* Options (Real/Crypto) */}
|
||||
<td>
|
||||
<div className="flex flex-col gap-1">
|
||||
<label className="flex items-center cursor-pointer text-xs text-yellow-400 hover:text-yellow-300" title="Places actual order on Bot">
|
||||
<label className="flex cursor-pointer items-center text-xs text-amber-600 hover:text-amber-500 dark:text-amber-400 dark:hover:text-amber-300" title="Places actual order on Bot">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="execute_order"
|
||||
@ -226,10 +234,10 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
onChange={handleChange}
|
||||
className="mr-1.5 accent-yellow-500"
|
||||
/>
|
||||
⚡ Execute
|
||||
Execute
|
||||
</label>
|
||||
<div className="flex items-center space-x-2">
|
||||
<label className="flex items-center cursor-pointer text-[10px] text-gray-500 hover:text-gray-300" title="Marks as Active Trade in Journal">
|
||||
<label className={checkboxLabelClass} title="Marks as Active Trade in Journal">
|
||||
<input
|
||||
type="checkbox"
|
||||
name="is_real_trade"
|
||||
@ -239,7 +247,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
/>
|
||||
Trade
|
||||
</label>
|
||||
<label className="flex items-center cursor-pointer text-[10px] text-gray-500 hover:text-gray-300">
|
||||
<label className={checkboxLabelClass}>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="is_crypto"
|
||||
@ -255,76 +263,76 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
|
||||
{/* Buy Price */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="number"
|
||||
name="buy_price"
|
||||
step="any"
|
||||
value={formData.buy_price}
|
||||
onChange={handleChange}
|
||||
className="bg-transparent border-b border-gray-600 focus:border-green-500 outline-none w-full py-1 text-sm text-right text-green-400 placeholder-gray-700 font-mono"
|
||||
className={`${numericInputClass} text-emerald-600 dark:text-emerald-400`}
|
||||
placeholder="0.00"
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* Qty */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="number"
|
||||
name="quantity"
|
||||
step="any"
|
||||
value={formData.quantity}
|
||||
onChange={handleChange}
|
||||
className="bg-transparent border-b border-gray-600 focus:border-blue-500 outline-none w-full py-1 text-sm text-right text-gray-200 placeholder-gray-700 font-mono"
|
||||
className={numericInputClass}
|
||||
placeholder="0"
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* SL */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="number"
|
||||
name="drop_threshold_for_buy"
|
||||
step="any"
|
||||
value={formData.drop_threshold_for_buy}
|
||||
onChange={handleChange}
|
||||
className="bg-transparent border-b border-gray-600 focus:border-red-500 outline-none w-full py-1 text-sm text-right text-red-400 placeholder-gray-700 font-mono"
|
||||
className={`${numericInputClass} text-red-600 dark:text-red-400`}
|
||||
placeholder="SL"
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* TP */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="number"
|
||||
name="gain_threshold_for_sell"
|
||||
step="any"
|
||||
value={formData.gain_threshold_for_sell}
|
||||
onChange={handleChange}
|
||||
className="bg-transparent border-b border-gray-600 focus:border-blue-500 outline-none w-full py-1 text-sm text-right text-blue-400 placeholder-gray-700 font-mono"
|
||||
className={`${numericInputClass} text-blue-600 dark:text-blue-400`}
|
||||
placeholder="TP"
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* Time */}
|
||||
<td>
|
||||
<input
|
||||
<Input
|
||||
type="datetime-local"
|
||||
name="buy_time"
|
||||
value={formData.buy_time ? new Date(formData.buy_time).toISOString().slice(0, 16) : ''}
|
||||
onChange={(e) => setFormData(prev => ({ ...prev, buy_time: new Date(e.target.value).toISOString() }))}
|
||||
className="bg-transparent border-b border-gray-600 focus:border-blue-500 outline-none w-full py-1 text-xs text-gray-400 font-mono"
|
||||
className="h-9 rounded border-[var(--border)] bg-[var(--input)] px-2 py-1 font-mono text-xs"
|
||||
/>
|
||||
</td>
|
||||
|
||||
{/* Sell Price (Exit) */}
|
||||
<td className="relative">
|
||||
<input
|
||||
<Input
|
||||
type="number"
|
||||
name="sell_price"
|
||||
step="any"
|
||||
value={formData.sell_price}
|
||||
onChange={handleChange}
|
||||
className="bg-transparent border-b border-gray-600 focus:border-purple-500 outline-none w-full py-1 text-sm text-right text-purple-400 placeholder-gray-700 font-mono"
|
||||
className={`${numericInputClass} text-purple-600 dark:text-purple-400`}
|
||||
placeholder="Exit"
|
||||
/>
|
||||
{formData.sell_price && formData.buy_price && (
|
||||
@ -341,33 +349,36 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
|
||||
<td>
|
||||
<div className="flex items-center justify-end gap-2">
|
||||
{initialData && (
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
onClick={onSuccess}
|
||||
className="text-xs text-gray-500 hover:text-white underline"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="h-8 text-xs underline"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</Button>
|
||||
)}
|
||||
<button
|
||||
<Button
|
||||
type="submit"
|
||||
className="bg-blue-600 hover:bg-blue-500 text-white text-xs px-3 py-1.5 rounded font-medium transition-colors"
|
||||
size="sm"
|
||||
className="h-8 text-xs"
|
||||
>
|
||||
{initialData ? 'Update' : 'Add'}
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
{/* Notes Row */}
|
||||
<tr>
|
||||
<td colSpan={8} className="pt-2 border-t border-gray-800">
|
||||
<input
|
||||
<td colSpan={10} className="border-t border-[var(--border)] pt-2">
|
||||
<Input
|
||||
type="text"
|
||||
name="notes"
|
||||
value={formData.notes}
|
||||
onChange={handleChange}
|
||||
placeholder="Add strategy notes here..."
|
||||
className="bg-transparent w-full text-xs text-gray-400 italic outline-none placeholder-gray-700"
|
||||
className="h-9 border-transparent bg-transparent px-0 text-xs italic shadow-none focus:border-transparent focus:ring-0"
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user