refactor(web): normalize entry form theme surface

This commit is contained in:
Saravana Achu Mac 2026-05-05 22:20:58 -07:00
parent df00e977d4
commit 75a3ac4ecf
2 changed files with 44 additions and 33 deletions

View File

@ -99,7 +99,7 @@ Current public bundle:
- [x] Normalize `web/src/components/StrategyWizard.tsx` - [x] Normalize `web/src/components/StrategyWizard.tsx`
- [x] Normalize `web/src/tabs/ReconciliationAuditPanel.tsx` - [x] Normalize `web/src/tabs/ReconciliationAuditPanel.tsx`
- [x] Normalize `web/src/components/GlobalConfigManager.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 - [ ] Normalize remaining old admin/config surfaces
- [ ] Remove remaining dark-only bespoke surface systems - [ ] Remove remaining dark-only bespoke surface systems
- [ ] Replace remaining one-off controls with shared primitives where practical - [ ] Replace remaining one-off controls with shared primitives where practical

View File

@ -5,12 +5,18 @@ import { tradingRuntime } from '../lib/runtime';
import { createManualEntry, updateManualEntry } from '../lib/manualEntriesApi'; import { createManualEntry, updateManualEntry } from '../lib/manualEntriesApi';
import { getPlatformAccessToken } from '../lib/authSession'; import { getPlatformAccessToken } from '../lib/authSession';
import { createRequestId } from '../../../shared/request-id.js'; import { createRequestId } from '../../../shared/request-id.js';
import { Button } from './ui/button';
import { Input } from './ui/input';
interface EntryFormProps { interface EntryFormProps {
onSuccess: () => void; onSuccess: () => void;
initialData?: any; 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) { export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
const { user } = useAuth(); const { user } = useAuth();
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
@ -106,7 +112,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
// Remove temp fields from DB payload // Remove temp fields from DB payload
delete (payload as any).execute_order; delete (payload as any).execute_order;
// --- 🚀 REAL TRADE EXECUTION --- // --- REAL TRADE EXECUTION ---
if (formData.execute_order && !initialData) { if (formData.execute_order && !initialData) {
if (!Number.isFinite(payload.quantity) || !payload.symbol.trim()) { if (!Number.isFinite(payload.quantity) || !payload.symbol.trim()) {
alert('Symbol and a valid quantity are required to execute a trade.'); 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 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; if (!confirmTrade) return;
const apiUrl = tradingRuntime.tradingApiUrl; const apiUrl = tradingRuntime.tradingApiUrl;
@ -145,7 +151,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
throw new Error(`Execution Failed: ${resData.error}`); 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) { 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">Qty</th>
<th style={{ width: '10%' }} className="text-right">Stop Loss</th> <th style={{ width: '10%' }} className="text-right">Stop Loss</th>
<th style={{ width: '10%' }} className="text-right">Take Profit</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> <th style={{ width: '11%' }}>Actions</th>
</tr> </tr>
</thead> </thead>
@ -192,33 +200,33 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
<tr> <tr>
{/* Symbol */} {/* Symbol */}
<td> <td>
<input <Input
type="text" type="text"
name="symbol" name="symbol"
required required
value={formData.symbol} value={formData.symbol}
onChange={handleChange} onChange={handleChange}
placeholder="BTC/USD" 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> </td>
{/* Label */} {/* Label */}
<td> <td>
<input <Input
type="text" type="text"
name="label" name="label"
value={formData.label} value={formData.label}
onChange={handleChange} onChange={handleChange}
placeholder="Swing" 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> </td>
{/* Options (Real/Crypto) */} {/* Options (Real/Crypto) */}
<td> <td>
<div className="flex flex-col gap-1"> <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 <input
type="checkbox" type="checkbox"
name="execute_order" name="execute_order"
@ -226,10 +234,10 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
onChange={handleChange} onChange={handleChange}
className="mr-1.5 accent-yellow-500" className="mr-1.5 accent-yellow-500"
/> />
Execute Execute
</label> </label>
<div className="flex items-center space-x-2"> <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 <input
type="checkbox" type="checkbox"
name="is_real_trade" name="is_real_trade"
@ -239,7 +247,7 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
/> />
Trade Trade
</label> </label>
<label className="flex items-center cursor-pointer text-[10px] text-gray-500 hover:text-gray-300"> <label className={checkboxLabelClass}>
<input <input
type="checkbox" type="checkbox"
name="is_crypto" name="is_crypto"
@ -255,76 +263,76 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
{/* Buy Price */} {/* Buy Price */}
<td> <td>
<input <Input
type="number" type="number"
name="buy_price" name="buy_price"
step="any" step="any"
value={formData.buy_price} value={formData.buy_price}
onChange={handleChange} 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" placeholder="0.00"
/> />
</td> </td>
{/* Qty */} {/* Qty */}
<td> <td>
<input <Input
type="number" type="number"
name="quantity" name="quantity"
step="any" step="any"
value={formData.quantity} value={formData.quantity}
onChange={handleChange} 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" placeholder="0"
/> />
</td> </td>
{/* SL */} {/* SL */}
<td> <td>
<input <Input
type="number" type="number"
name="drop_threshold_for_buy" name="drop_threshold_for_buy"
step="any" step="any"
value={formData.drop_threshold_for_buy} value={formData.drop_threshold_for_buy}
onChange={handleChange} 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" placeholder="SL"
/> />
</td> </td>
{/* TP */} {/* TP */}
<td> <td>
<input <Input
type="number" type="number"
name="gain_threshold_for_sell" name="gain_threshold_for_sell"
step="any" step="any"
value={formData.gain_threshold_for_sell} value={formData.gain_threshold_for_sell}
onChange={handleChange} 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" placeholder="TP"
/> />
</td> </td>
{/* Time */} {/* Time */}
<td> <td>
<input <Input
type="datetime-local" type="datetime-local"
name="buy_time" name="buy_time"
value={formData.buy_time ? new Date(formData.buy_time).toISOString().slice(0, 16) : ''} 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() }))} 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> </td>
{/* Sell Price (Exit) */} {/* Sell Price (Exit) */}
<td className="relative"> <td className="relative">
<input <Input
type="number" type="number"
name="sell_price" name="sell_price"
step="any" step="any"
value={formData.sell_price} value={formData.sell_price}
onChange={handleChange} 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" placeholder="Exit"
/> />
{formData.sell_price && formData.buy_price && ( {formData.sell_price && formData.buy_price && (
@ -341,33 +349,36 @@ export function EntryForm({ onSuccess, initialData }: EntryFormProps) {
<td> <td>
<div className="flex items-center justify-end gap-2"> <div className="flex items-center justify-end gap-2">
{initialData && ( {initialData && (
<button <Button
type="button" type="button"
onClick={onSuccess} onClick={onSuccess}
className="text-xs text-gray-500 hover:text-white underline" variant="ghost"
size="sm"
className="h-8 text-xs underline"
> >
Cancel Cancel
</button> </Button>
)} )}
<button <Button
type="submit" 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'} {initialData ? 'Update' : 'Add'}
</button> </Button>
</div> </div>
</td> </td>
</tr> </tr>
{/* Notes Row */} {/* Notes Row */}
<tr> <tr>
<td colSpan={8} className="pt-2 border-t border-gray-800"> <td colSpan={10} className="border-t border-[var(--border)] pt-2">
<input <Input
type="text" type="text"
name="notes" name="notes"
value={formData.notes} value={formData.notes}
onChange={handleChange} onChange={handleChange}
placeholder="Add strategy notes here..." 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> </td>
</tr> </tr>