({
openOrders,
cancellingOrderId,
onCancel,
onTradePosition,
onClose,
}: {
openOrders: OpenOrder[];
cancellingOrderId: string | null;
onCancel: (id: string) => void;
onTradePosition?: (title: string, outcome: string) => void;
onClose: () => void;
})
| 83 | } |
| 84 | |
| 85 | function OpenOrdersTab({ |
| 86 | openOrders, |
| 87 | cancellingOrderId, |
| 88 | onCancel, |
| 89 | onTradePosition, |
| 90 | onClose, |
| 91 | }: { |
| 92 | openOrders: OpenOrder[]; |
| 93 | cancellingOrderId: string | null; |
| 94 | onCancel: (id: string) => void; |
| 95 | onTradePosition?: (title: string, outcome: string) => void; |
| 96 | onClose: () => void; |
| 97 | }) { |
| 98 | const { t } = useI18n(); |
| 99 | const mapped = useMarketStore((s) => s.mapped); |
| 100 | const unmapped = useMarketStore((s) => s.unmapped); |
| 101 | const tokenIndex = useMemo(() => buildTokenIndex([...mapped, ...unmapped]), [mapped, unmapped]); |
| 102 | const resolved = useMemo( |
| 103 | () => openOrders.map((o) => ({ order: o, market: tokenIndex.get(String(o.asset_id)) ?? null })), |
| 104 | [openOrders, tokenIndex], |
| 105 | ); |
| 106 | |
| 107 | if (openOrders.length === 0) { |
| 108 | return <div className="px-3 py-4 text-[11px] text-[var(--text-ghost)] text-center">{t("openOrders.noOpenOrders")}</div>; |
| 109 | } |
| 110 | |
| 111 | return ( |
| 112 | <> |
| 113 | {resolved.map(({ order, market }) => { |
| 114 | const price = parseFloat(order.price) || 0; |
| 115 | const total = parseFloat(order.original_size) || 0; |
| 116 | const matched = parseFloat(order.size_matched) || 0; |
| 117 | const isBuy = order.side === "BUY"; |
| 118 | const title = market?.title || `${order.asset_id.slice(0, 12)}…`; |
| 119 | const image = market?.image; |
| 120 | |
| 121 | return ( |
| 122 | <div |
| 123 | key={order.id} |
| 124 | className="w-full px-3 py-2.5 text-left border-b border-[var(--border-subtle)] hover:bg-[var(--border-subtle)]/30 transition-colors group" |
| 125 | > |
| 126 | <div className="flex items-start gap-2.5"> |
| 127 | {image ? ( |
| 128 | // eslint-disable-next-line @next/next/no-img-element |
| 129 | <img src={image} alt="" width={28} height={28} className="rounded shrink-0 mt-0.5 object-cover" /> |
| 130 | ) : ( |
| 131 | <div className="w-7 h-7 rounded shrink-0 mt-0.5 bg-[var(--border-subtle)] flex items-center justify-center text-[10px] text-[var(--text-ghost)]"> |
| 132 | {title.slice(0, 1).toUpperCase()} |
| 133 | </div> |
| 134 | )} |
| 135 | <div className="flex-1 min-w-0"> |
| 136 | {market ? ( |
| 137 | <button |
| 138 | onClick={() => { |
| 139 | onTradePosition?.(market.title, market.outcome); |
| 140 | onClose(); |
| 141 | }} |
| 142 | className="text-[12px] text-[var(--text-muted)] group-hover:text-[var(--text)] truncate leading-snug transition-colors block text-left w-full" |
nothing calls this directly
no test coverage detected