+
+
+ My Trades
+
+
+ Confirmations, requests, and the reputation they build. Payment is arranged
+ with the other skater — the app only records the deal.
+
+
+
+
+
+ {/* Action needed */}
+
+
+ Action needed {actionNeeded > 0 && `· ${actionNeeded}`}
+
+
+ {(loadingIncoming || loadingPending) && (
+
+
+
+
+ )}
+
+ {/* Incoming: someone asked you (seller) to record a sale */}
+ {incoming?.map((r) => (
+
+
+
+
+
+ asked you to confirm a sale
+
+
+ View listing
+
+
+
+
+
+ ))}
+
+ {/* Pending: a seller recorded a sale you haven't confirmed */}
+ {pending?.map((t) => (
+
+
+
+
+
+ recorded a sale — confirm your side
+
+
+ View listing
+
+
+
+
+
+ ))}
+
+ {!loadingIncoming && !loadingPending && actionNeeded === 0 && (
+ Nothing waiting on you right now. 🛹
+ )}
+
+
+ {/* Your trade records */}
+
+
+ Your trade records
+
+
+ {loadingRep && }
+
+ {!loadingRep && authored.length === 0 && (
+
+
+
+
+ No trades yet. Close a deal and confirm it to start building reputation.
+
+
+
+
+ )}
+
+ {authored.map((ev) => {
+ const coord = ev.tags.find(([t]) => t === 'a')?.[1];
+ const parsed = parseListingCoord(coord);
+ const d = ev.tags.find(([t]) => t === 'd')?.[1] ?? '';
+ const role = d.includes(':trade:sold:') ? 'Sold' : d.includes(':trade:bought:') ? 'Bought' : 'Trade';
+ const state = ev.tags.find(([t]) => t === 's')?.[1] ?? 'valid';
+ const counterparty = ev.tags.find(([t]) => t === 'p')?.[1];
+ return (
+
+
+
+ {role}
+
+
+
+ {counterparty ? <>with > : 'trade'}
+
+
+ {new Date(ev.created_at * 1000).toLocaleDateString()}
+ {state !== 'valid' && ` · ${state}`}
+
+
+ {parsed && (
+
+ View listing
+
+ )}
+
+
+ );
+ })}
+
+
+