@agg-build/ui 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunk-R6DETAZ6.mjs → chunk-34L7ZKJW.mjs} +804 -776
  3. package/dist/{chunk-JDYZJKTE.mjs → chunk-5FXMHTVR.mjs} +1 -1
  4. package/dist/{chunk-IT2Y62MG.mjs → chunk-CDQZJPHQ.mjs} +589 -340
  5. package/dist/{chunk-7JEJIGG4.mjs → chunk-EGCVA2AQ.mjs} +23 -8
  6. package/dist/{chunk-OHEZGKFM.mjs → chunk-FDTLV74F.mjs} +89 -5
  7. package/dist/{chunk-F3SU7BRE.mjs → chunk-Q2BRDVBU.mjs} +1 -1
  8. package/dist/{chunk-KDMNFHPL.mjs → chunk-TBKDLNOE.mjs} +27 -16
  9. package/dist/events.js +956 -906
  10. package/dist/events.mjs +3 -3
  11. package/dist/index.js +2936 -2550
  12. package/dist/index.mjs +17 -15
  13. package/dist/modals.js +816 -792
  14. package/dist/modals.mjs +3 -3
  15. package/dist/pages.js +2214 -1830
  16. package/dist/pages.mjs +6 -6
  17. package/dist/primitives.js +799 -773
  18. package/dist/primitives.mjs +3 -1
  19. package/dist/styles.css +1 -1
  20. package/dist/tailwind.css +1 -1
  21. package/dist/trading.js +868 -639
  22. package/dist/trading.mjs +4 -4
  23. package/dist/types/events/market-details/index.d.mts +1 -1
  24. package/dist/types/events/market-details/index.d.ts +1 -1
  25. package/dist/types/events/market-details/market-details.types.d.mts +11 -0
  26. package/dist/types/events/market-details/market-details.types.d.ts +11 -0
  27. package/dist/types/pages/user-profile/position-view-model.d.mts +54 -0
  28. package/dist/types/pages/user-profile/position-view-model.d.ts +54 -0
  29. package/dist/types/pages/user-profile/user-profile.types.d.mts +22 -0
  30. package/dist/types/pages/user-profile/user-profile.types.d.ts +22 -0
  31. package/dist/types/primitives/icon/index.d.mts +2 -1
  32. package/dist/types/primitives/icon/index.d.ts +2 -1
  33. package/dist/types/primitives/icon/registry.d.mts +4 -0
  34. package/dist/types/primitives/icon/registry.d.ts +4 -0
  35. package/dist/types/primitives/icon/svg/hourglass-start.d.mts +5 -0
  36. package/dist/types/primitives/icon/svg/hourglass-start.d.ts +5 -0
  37. package/dist/types/shared/utils.d.mts +5 -1
  38. package/dist/types/shared/utils.d.ts +5 -1
  39. package/package.json +3 -3
@@ -9,13 +9,13 @@ import {
9
9
  isErrorWithStatus,
10
10
  useEventListTabs,
11
11
  useEventListTabsHeaderOverflow
12
- } from "./chunk-7JEJIGG4.mjs";
12
+ } from "./chunk-EGCVA2AQ.mjs";
13
13
  import {
14
14
  DEPOSIT_MODAL_OPEN_EVENT,
15
15
  PlaceOrder,
16
16
  SettlementDetails,
17
17
  WITHDRAW_MODAL_OPEN_EVENT
18
- } from "./chunk-OHEZGKFM.mjs";
18
+ } from "./chunk-FDTLV74F.mjs";
19
19
  import {
20
20
  AggErrorBoundary,
21
21
  Button,
@@ -44,7 +44,7 @@ import {
44
44
  filterOpenEvents,
45
45
  resolveTabVenus,
46
46
  shortenAddress
47
- } from "./chunk-R6DETAZ6.mjs";
47
+ } from "./chunk-34L7ZKJW.mjs";
48
48
 
49
49
  // src/pages/home/index.tsx
50
50
  import {
@@ -158,11 +158,12 @@ var EventMarketPageMobileTrade = ({
158
158
  classNames,
159
159
  eventTradingState,
160
160
  showPlaceOrder = true,
161
- resolvedClaim
161
+ resolvedClaim,
162
+ isOpen,
163
+ onOpenChange
162
164
  }) => {
163
165
  var _a;
164
166
  const labels = useLabels();
165
- const [isOpen, setIsOpen] = useState(false);
166
167
  const tradingContext = useEventTradingContext();
167
168
  const selectedMarketState = resolveMarketTradingState((_a = tradingContext == null ? void 0 : tradingContext.selectedMarket) != null ? _a : null);
168
169
  if (!showPlaceOrder) {
@@ -179,80 +180,51 @@ var EventMarketPageMobileTrade = ({
179
180
  }
180
181
  ) });
181
182
  }
182
- const handleOpen = () => {
183
- setIsOpen(true);
184
- };
185
183
  const handleOpenChange = (nextOpen) => {
186
- setIsOpen(nextOpen);
184
+ onOpenChange(nextOpen);
187
185
  };
188
186
  const handleClose = () => {
189
- setIsOpen(false);
187
+ onOpenChange(false);
190
188
  };
191
- return /* @__PURE__ */ jsxs(Fragment, { children: [
192
- /* @__PURE__ */ jsx(
193
- "div",
194
- {
195
- className: cn(
196
- "agg-mobile-trade-cta",
197
- "fixed inset-x-0 bottom-0 z-100 flex justify-end p-4 lg:hidden",
198
- classNames == null ? void 0 : classNames.mobileTradeCta
199
- ),
200
- children: /* @__PURE__ */ jsx(
201
- Button,
189
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Modal, { open: isOpen, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(
190
+ Modal.Container,
191
+ {
192
+ classNames: {
193
+ content: "items-end p-0 sm:items-center sm:p-4",
194
+ container: cn(
195
+ "agg-mobile-trade-modal",
196
+ "w-full border-0 bg-transparent shadow-none",
197
+ classNames == null ? void 0 : classNames.mobileTradeModal
198
+ )
199
+ },
200
+ children: [
201
+ /* @__PURE__ */ jsx(Dialog.Title, { className: "sr-only", children: labels.trading.confirmOrder }),
202
+ /* @__PURE__ */ jsx(Dialog.Description, { className: "sr-only", children: labels.trading.disclaimer }),
203
+ /* @__PURE__ */ jsx("div", { className: "agg-mobile-trade-handle relative flex w-full flex-col items-center sm:hidden", children: /* @__PURE__ */ jsx(
204
+ "button",
202
205
  {
203
- size: "large",
204
- className: "agg-mobile-trade-trigger min-w-[168px] shadow-agg-modal",
205
- "aria-label": labels.trading.confirmOrder,
206
- onClick: (e) => {
207
- e.stopPropagation();
208
- e.preventDefault();
209
- handleOpen();
210
- },
211
- children: labels.trading.confirmOrder
206
+ type: "button",
207
+ className: "absolute right-3 top-4 z-100 flex cursor-pointer items-center justify-center rounded-full p-1 text-agg-muted-foreground hover:text-agg-foreground",
208
+ "aria-label": labels.common.close,
209
+ onClick: handleClose,
210
+ children: /* @__PURE__ */ jsx(CloseIcon, { className: "h-5 w-5" })
211
+ }
212
+ ) }),
213
+ /* @__PURE__ */ jsx(
214
+ PlaceOrder,
215
+ {
216
+ eventTradingState,
217
+ className: cn(
218
+ "agg-mobile-trade-panel w-full overflow-hidden rounded-t-agg-2xl sm:rounded-agg-xl",
219
+ classNames == null ? void 0 : classNames.mobileTrade
220
+ ),
221
+ classNames: resolveMobileTradePlaceOrderClassNames(classNames),
222
+ onClose: handleClose
212
223
  }
213
224
  )
214
- }
215
- ),
216
- /* @__PURE__ */ jsx(Modal, { open: isOpen, onOpenChange: handleOpenChange, children: /* @__PURE__ */ jsxs(
217
- Modal.Container,
218
- {
219
- classNames: {
220
- content: "items-end p-0 sm:items-center sm:p-4",
221
- container: cn(
222
- "agg-mobile-trade-modal",
223
- "w-full border-0 bg-transparent shadow-none",
224
- classNames == null ? void 0 : classNames.mobileTradeModal
225
- )
226
- },
227
- children: [
228
- /* @__PURE__ */ jsx(Dialog.Title, { className: "sr-only", children: labels.trading.confirmOrder }),
229
- /* @__PURE__ */ jsx(Dialog.Description, { className: "sr-only", children: labels.trading.disclaimer }),
230
- /* @__PURE__ */ jsx("div", { className: "agg-mobile-trade-handle relative flex w-full flex-col items-center sm:hidden", children: /* @__PURE__ */ jsx(
231
- "button",
232
- {
233
- type: "button",
234
- className: "absolute right-3 top-4 z-100 flex cursor-pointer items-center justify-center rounded-full p-1 text-agg-muted-foreground hover:text-agg-foreground",
235
- "aria-label": labels.common.close,
236
- onClick: handleClose,
237
- children: /* @__PURE__ */ jsx(CloseIcon, { className: "h-5 w-5" })
238
- }
239
- ) }),
240
- /* @__PURE__ */ jsx(
241
- PlaceOrder,
242
- {
243
- eventTradingState,
244
- className: cn(
245
- "agg-mobile-trade-panel w-full overflow-hidden rounded-t-agg-2xl sm:rounded-agg-xl",
246
- classNames == null ? void 0 : classNames.mobileTrade
247
- ),
248
- classNames: resolveMobileTradePlaceOrderClassNames(classNames),
249
- onClose: handleClose
250
- }
251
- )
252
- ]
253
- }
254
- ) })
255
- ] });
225
+ ]
226
+ }
227
+ ) }) });
256
228
  };
257
229
  var EventMarketPageUnavailableState = ({
258
230
  ariaLabel: _ariaLabel
@@ -375,6 +347,7 @@ var EventMarketPageContent = ({
375
347
  const stickyOrderPanelState = resolveEventMarketPageStickyState({
376
348
  stickyOrderPanel
377
349
  });
350
+ const [isMobileTradeOpen, setIsMobileTradeOpen] = useState(false);
378
351
  if (!event || !event.venueMarkets.length) {
379
352
  return /* @__PURE__ */ jsx(EventMarketPageUnavailableState, { ariaLabel });
380
353
  }
@@ -427,6 +400,12 @@ var EventMarketPageContent = ({
427
400
  markets: eventTradingState.displayMarkets,
428
401
  eventTradingState,
429
402
  live: true,
403
+ onOutcomeSelect: () => {
404
+ if (typeof window === "undefined") return;
405
+ if (typeof window.matchMedia !== "function") return;
406
+ if (!window.matchMedia("(max-width: 1023px)").matches) return;
407
+ setIsMobileTradeOpen(true);
408
+ },
430
409
  classNames: { root: "agg-market-list", item: "agg-market-list-item" }
431
410
  }
432
411
  ),
@@ -474,7 +453,9 @@ var EventMarketPageContent = ({
474
453
  classNames,
475
454
  eventTradingState,
476
455
  showPlaceOrder,
477
- resolvedClaim
456
+ resolvedClaim,
457
+ isOpen: isMobileTradeOpen,
458
+ onOpenChange: setIsMobileTradeOpen
478
459
  }
479
460
  ) : null
480
461
  ]
@@ -1095,6 +1076,7 @@ import {
1095
1076
  useGeoBlock,
1096
1077
  useLabels as useLabels6,
1097
1078
  useQueryClient,
1079
+ useRedeem,
1098
1080
  useUserActivity
1099
1081
  } from "@agg-build/hooks";
1100
1082
  import { Venue } from "@agg-build/sdk";
@@ -1209,7 +1191,7 @@ var AvailableBalanceCard = ({
1209
1191
  "div",
1210
1192
  {
1211
1193
  role: "listitem",
1212
- className: "agg-balance-row flex items-center justify-between gap-3 w-full",
1194
+ className: "agg-balance-row flex items-center justify-between self-stretch gap-3 w-full",
1213
1195
  children: [
1214
1196
  /* @__PURE__ */ jsxs3("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [
1215
1197
  icon ? /* @__PURE__ */ jsx3("span", { className: "flex h-4 w-4 items-center justify-center rounded-[4px]", children: /* @__PURE__ */ jsx3(Icon, { name: icon, size: "small", className: "text-agg-foreground" }) }) : /* @__PURE__ */ jsx3("span", { className: "flex h-4 w-4 items-center justify-center rounded-[4px] border border-agg-separator text-[10px] leading-3 text-agg-muted-foreground", children: row.label.slice(0, 2).toUpperCase() }),
@@ -1221,7 +1203,7 @@ var AvailableBalanceCard = ({
1221
1203
  minimumFractionDigits: Number.isInteger(row.balance) ? 0 : 1,
1222
1204
  maximumFractionDigits: 2
1223
1205
  }) }),
1224
- /* @__PURE__ */ jsx3("div", { className: "flex w-12 shrink-0 items-center justify-end gap-1 empty:hidden", children: ((_a = CHAIN_VENUE_MAP[row.key]) != null ? _a : []).slice(0, 2).map((venue, venueIndex) => /* @__PURE__ */ jsx3(
1206
+ /* @__PURE__ */ jsx3("div", { className: "flex w-12 shrink-0 items-center justify-end gap-1", children: ((_a = CHAIN_VENUE_MAP[row.key]) != null ? _a : []).slice(0, 2).map((venue, venueIndex) => /* @__PURE__ */ jsx3(
1225
1207
  VenueLogo,
1226
1208
  {
1227
1209
  venue,
@@ -1291,6 +1273,188 @@ var USER_PROFILE_POSITION_FILTERS = [
1291
1273
  { value: "closed", label: "Closed" }
1292
1274
  ];
1293
1275
 
1276
+ // src/pages/user-profile/position-view-model.ts
1277
+ var defaultLabels = {
1278
+ avgPrefix: "avg",
1279
+ nowPrefix: "now",
1280
+ finalPrefix: "final"
1281
+ };
1282
+ var missingLabel = "\u2014";
1283
+ var usdFormatter = new Intl.NumberFormat("en-US", {
1284
+ style: "currency",
1285
+ currency: "USD",
1286
+ minimumFractionDigits: 2,
1287
+ maximumFractionDigits: 2
1288
+ });
1289
+ var percentFormatter = new Intl.NumberFormat("en-US", {
1290
+ minimumFractionDigits: 0,
1291
+ maximumFractionDigits: 1
1292
+ });
1293
+ var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
1294
+ var parseCurrencyLabel = (label) => {
1295
+ if (!label) return null;
1296
+ const normalized = label.replace(/[$,\s]/g, "");
1297
+ const parsed = Number(normalized);
1298
+ return Number.isFinite(parsed) ? parsed : null;
1299
+ };
1300
+ var parsePriceLabel = (label) => {
1301
+ if (!label) return null;
1302
+ const match = label.match(/-?\d+(?:\.\d+)?/);
1303
+ if (!match) return null;
1304
+ const parsed = Number(match[0]);
1305
+ return Number.isFinite(parsed) ? parsed / 100 : null;
1306
+ };
1307
+ var parsePercentLabel = (label) => {
1308
+ if (!label) return null;
1309
+ const match = label.match(/([+-]?\d+(?:,\d{3})*(?:\.\d+)?)%/);
1310
+ if (!(match == null ? void 0 : match[1])) return null;
1311
+ const parsed = Number(match[1].replace(/,/g, ""));
1312
+ return Number.isFinite(parsed) ? parsed : null;
1313
+ };
1314
+ var formatCurrency = (value) => {
1315
+ if (!isFiniteNumber(value)) return missingLabel;
1316
+ return usdFormatter.format(value);
1317
+ };
1318
+ var formatSignedCurrency = (value) => {
1319
+ if (!isFiniteNumber(value)) return missingLabel;
1320
+ if (value === 0) return usdFormatter.format(0);
1321
+ return `${value > 0 ? "+" : "-"}${usdFormatter.format(Math.abs(value))}`;
1322
+ };
1323
+ var formatPriceCents = (value) => {
1324
+ if (!isFiniteNumber(value)) return missingLabel;
1325
+ return `${Math.round(value * 100)}\xA2`;
1326
+ };
1327
+ var formatSignedPercent = (value) => {
1328
+ if (!isFiniteNumber(value)) return missingLabel;
1329
+ if (value === 0) return "0%";
1330
+ return `${value > 0 ? "+" : "-"}${percentFormatter.format(Math.abs(value))}%`;
1331
+ };
1332
+ var resolvePositionStatus = (position) => {
1333
+ if (position.marketStatus === "open") return "open";
1334
+ if (position.winner === false) return "lost";
1335
+ if (position.winner === true) {
1336
+ return position.closedClaimStatus === "redeemed" ? "won_claimed" : "won_unclaimed";
1337
+ }
1338
+ if (position.status === "closed") return "sold";
1339
+ return "open";
1340
+ };
1341
+ var resolvePositionBucket = (position) => {
1342
+ const status = resolvePositionStatus(position);
1343
+ if (status === "won_unclaimed") return "active";
1344
+ if (status === "open") return "active";
1345
+ return "closed";
1346
+ };
1347
+ var getTotalTradedValue = (position) => {
1348
+ if (isFiniteNumber(position.totalTradedValue)) return position.totalTradedValue;
1349
+ const closedValue = parseCurrencyLabel(position.closedTotalTradedLabel);
1350
+ if (closedValue != null) return closedValue;
1351
+ const avgPrice = getAveragePrice(position);
1352
+ const totalShares = position.venueShareBreakdown.reduce((sum, row) => {
1353
+ var _a, _b;
1354
+ const shares = Number((_b = (_a = row.sharesLabel.match(/-?\d+(?:\.\d+)?/)) == null ? void 0 : _a[0]) != null ? _b : Number.NaN);
1355
+ return Number.isFinite(shares) ? sum + shares : sum;
1356
+ }, 0);
1357
+ return avgPrice != null && totalShares > 0 ? avgPrice * totalShares : parseCurrencyLabel(position.valueLabel);
1358
+ };
1359
+ var getAveragePrice = (position) => {
1360
+ if (isFiniteNumber(position.averagePrice)) return position.averagePrice;
1361
+ return parsePriceLabel(position.averageLabel);
1362
+ };
1363
+ var getCurrentPrice = (position) => {
1364
+ if (isFiniteNumber(position.currentPrice)) return position.currentPrice;
1365
+ return parsePriceLabel(position.currentLabel);
1366
+ };
1367
+ var getCurrentValue = (position) => {
1368
+ if (isFiniteNumber(position.currentValue)) return position.currentValue;
1369
+ return parseCurrencyLabel(position.valueLabel);
1370
+ };
1371
+ var getFinalPayoutValue = (position) => {
1372
+ if (isFiniteNumber(position.finalPayoutValue)) return position.finalPayoutValue;
1373
+ if (position.closedAmountWonLabel) return parseCurrencyLabel(position.closedAmountWonLabel);
1374
+ if (position.winner === false) return 0;
1375
+ return getCurrentValue(position);
1376
+ };
1377
+ var getFinalPrice = (position) => {
1378
+ if (isFiniteNumber(position.finalPrice)) return position.finalPrice;
1379
+ if (position.marketStatus === "resolved" && position.winner === true) return 1;
1380
+ if (position.marketStatus === "resolved" && position.winner === false) return 0;
1381
+ return getCurrentPrice(position);
1382
+ };
1383
+ var getPnlValue = (position, value) => {
1384
+ if (isFiniteNumber(position.pnlValue)) return position.pnlValue;
1385
+ const totalTraded = getTotalTradedValue(position);
1386
+ if (value != null && totalTraded != null) return value - totalTraded;
1387
+ return parseCurrencyLabel(position.pnlLabel);
1388
+ };
1389
+ var getPnlPercent = (position, pnlValue) => {
1390
+ var _a;
1391
+ if (isFiniteNumber(position.pnlPercent)) return position.pnlPercent;
1392
+ const parsed = parsePercentLabel((_a = position.closedReturnLabel) != null ? _a : position.pnlLabel);
1393
+ if (parsed != null) return parsed;
1394
+ const totalTraded = getTotalTradedValue(position);
1395
+ if (pnlValue != null && totalTraded && totalTraded !== 0)
1396
+ return pnlValue / Math.abs(totalTraded) * 100;
1397
+ return null;
1398
+ };
1399
+ var getFinalPnlValue = (position, value) => {
1400
+ if (isFiniteNumber(position.finalPnlValue)) return position.finalPnlValue;
1401
+ const totalTraded = getTotalTradedValue(position);
1402
+ if (value != null && totalTraded != null) return value - totalTraded;
1403
+ return null;
1404
+ };
1405
+ var getFinalPnlPercent = (position, pnlValue) => {
1406
+ if (isFiniteNumber(position.finalPnlPercent)) return position.finalPnlPercent;
1407
+ const parsed = parsePercentLabel(position.closedReturnLabel);
1408
+ if (parsed != null) return parsed;
1409
+ const totalTraded = getTotalTradedValue(position);
1410
+ if (pnlValue != null && totalTraded && totalTraded !== 0) {
1411
+ return pnlValue / Math.abs(totalTraded) * 100;
1412
+ }
1413
+ return null;
1414
+ };
1415
+ var getPositionTone = (value) => {
1416
+ if (!isFiniteNumber(value) || value === 0) return "neutral";
1417
+ return value > 0 ? "positive" : "negative";
1418
+ };
1419
+ var toPositionRowViewModel = (position, labels = defaultLabels) => {
1420
+ const positionStatus = resolvePositionStatus(position);
1421
+ const currentValue = getCurrentValue(position);
1422
+ const currentPnl = getPnlValue(position, currentValue);
1423
+ const currentPercent = getPnlPercent(position, currentPnl);
1424
+ const finalPayout = getFinalPayoutValue(position);
1425
+ const payoutPnl = getFinalPnlValue(position, finalPayout);
1426
+ const payoutPercent = getFinalPnlPercent(position, payoutPnl);
1427
+ return {
1428
+ position,
1429
+ positionStatus,
1430
+ bucket: resolvePositionBucket(position),
1431
+ title: position.title || missingLabel,
1432
+ thumbnailSrc: position.thumbnailSrc,
1433
+ selectedOutcomeLabel: position.outcomeLabel || missingLabel,
1434
+ resolutionLabel: position.outcomeLabel || missingLabel,
1435
+ venueShareBreakdown: position.venueShareBreakdown,
1436
+ totalTraded: {
1437
+ primaryLabel: formatCurrency(getTotalTradedValue(position)),
1438
+ averageLabel: `${labels.avgPrefix} ${formatPriceCents(getAveragePrice(position))}`
1439
+ },
1440
+ currentValue: {
1441
+ primaryLabel: formatCurrency(currentValue),
1442
+ deltaLabel: formatSignedCurrency(currentPnl),
1443
+ priceLabel: `${labels.nowPrefix} ${formatPriceCents(getCurrentPrice(position))}`,
1444
+ percentLabel: formatSignedPercent(currentPercent),
1445
+ tone: getPositionTone(currentPnl)
1446
+ },
1447
+ payout: {
1448
+ primaryLabel: formatCurrency(finalPayout),
1449
+ deltaLabel: formatSignedCurrency(payoutPnl),
1450
+ priceLabel: `${labels.finalPrefix} ${formatPriceCents(getFinalPrice(position))}`,
1451
+ percentLabel: formatSignedPercent(payoutPercent),
1452
+ tone: getPositionTone(payoutPnl)
1453
+ },
1454
+ canClaim: positionStatus === "won_unclaimed" && position.closedClaimStatus !== "pending"
1455
+ };
1456
+ };
1457
+
1294
1458
  // src/pages/user-profile/components/activity-row.tsx
1295
1459
  import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
1296
1460
  var shouldUseNativeLinkNavigation = (event) => {
@@ -1635,131 +1799,121 @@ EmptyState.displayName = "EmptyState";
1635
1799
  // src/pages/user-profile/components/position-row.tsx
1636
1800
  import { optimizedImageUrl, useLabels as useLabels3 } from "@agg-build/hooks";
1637
1801
  import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1638
- var resolveBadge = (position, labels) => {
1639
- if (position.marketStatus === "resolved") {
1640
- if (position.winner === true) return { label: labels.won, tone: "won" };
1641
- if (position.winner === false) return { label: labels.lost, tone: "lost" };
1642
- return { label: labels.resolved, tone: "resolved" };
1643
- }
1644
- if (position.marketStatus === "closed") {
1645
- return { label: labels.marketClosed, tone: "market-closed" };
1646
- }
1647
- if (position.status === "closed") {
1648
- return { label: labels.closed, tone: "closed" };
1649
- }
1650
- return null;
1651
- };
1652
- var isMarketResolved = (position) => position.marketStatus === "resolved";
1653
- var badgeToneClass = (tone) => {
1654
- switch (tone) {
1655
- case "won":
1656
- return "bg-agg-success/10 text-agg-success";
1657
- case "lost":
1658
- return "bg-agg-error/10 text-agg-error";
1659
- case "resolved":
1660
- case "market-closed":
1661
- case "closed":
1662
- return "bg-agg-secondary-hover text-agg-muted-foreground";
1663
- }
1802
+ var shouldUseNativeLinkNavigation2 = (event) => {
1803
+ return event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button === 1;
1664
1804
  };
1665
- var resolveClosedReturnToneClass = (position) => {
1666
- var _a;
1667
- if (!isMarketResolved(position)) return "text-agg-muted-foreground";
1668
- if (position.winner === true) return "text-agg-success";
1669
- if (position.winner === false) return "text-agg-error";
1670
- const returnLabel = ((_a = position.closedReturnLabel) != null ? _a : "").trim();
1671
- if (returnLabel.startsWith("+")) return "text-agg-success";
1672
- if (returnLabel.startsWith("-")) return "text-agg-error";
1805
+ var toneTextClassName = (tone) => {
1806
+ if (tone === "positive") return "text-agg-success";
1807
+ if (tone === "negative") return "text-agg-error";
1673
1808
  return "text-agg-muted-foreground";
1674
1809
  };
1675
- var shouldUseNativeLinkNavigation2 = (event) => {
1676
- return event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button === 1;
1810
+ var OutcomePill = ({ label }) => /* @__PURE__ */ jsx6("span", { className: "agg-position-outcome inline-flex items-center justify-center rounded-full bg-agg-secondary-hover px-4 py-[6px]", children: /* @__PURE__ */ jsx6("span", { className: "whitespace-nowrap font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground", children: label }) });
1811
+ var VenueShares = ({
1812
+ model,
1813
+ className,
1814
+ keyPrefix
1815
+ }) => {
1816
+ if (model.venueShareBreakdown.length === 0) return null;
1817
+ return /* @__PURE__ */ jsx6("div", { className, children: model.venueShareBreakdown.map((row, index) => /* @__PURE__ */ jsxs6(
1818
+ "div",
1819
+ {
1820
+ className: "flex items-center gap-1",
1821
+ children: [
1822
+ /* @__PURE__ */ jsx6(VenueLogo, { venue: row.venue, size: "small", className: "size-4 shrink-0" }),
1823
+ /* @__PURE__ */ jsx6("span", { className: "whitespace-nowrap font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground", children: row.sharesLabel })
1824
+ ]
1825
+ },
1826
+ `${keyPrefix}-${row.venue}-${row.sharesLabel}-${String(index)}`
1827
+ )) });
1677
1828
  };
1678
- var OutcomePill = ({ label }) => /* @__PURE__ */ jsx6("span", { className: "agg-position-outcome inline-flex items-center justify-center rounded-full bg-agg-secondary-hover px-4 py-[6px]", children: /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground whitespace-nowrap", children: label }) });
1679
- var PositionBadgeNode = ({ badge }) => {
1680
- if (!badge) return null;
1681
- return /* @__PURE__ */ jsx6(
1829
+ var StatusBadge = ({
1830
+ status,
1831
+ labels
1832
+ }) => {
1833
+ if (status === "lost" || status === "won_claimed") return null;
1834
+ const isWon = status === "won_unclaimed";
1835
+ return /* @__PURE__ */ jsxs6(
1682
1836
  "span",
1683
1837
  {
1684
1838
  className: cn(
1685
- "agg-position-badge inline-flex items-center rounded-full px-3 py-[4px]",
1686
- "font-agg-sans text-agg-xs leading-agg-4 font-agg-normal whitespace-nowrap",
1687
- badgeToneClass(badge.tone)
1839
+ "agg-position-status-badge inline-flex items-center justify-center gap-1 rounded-[4px] border px-2 py-[2px]",
1840
+ "font-agg-sans text-[10px] leading-agg-14 font-agg-bold uppercase whitespace-nowrap",
1841
+ isWon ? "border-agg-success/50 bg-agg-success/10 text-agg-success" : "border-agg-muted-foreground/30 bg-agg-secondary-hover text-agg-foreground"
1688
1842
  ),
1689
- children: badge.label
1843
+ children: [
1844
+ /* @__PURE__ */ jsx6(Icon, { name: isWon ? "check-circle" : "hourglass-start", size: "small", className: "size-2.5" }),
1845
+ isWon ? labels.won : labels.open
1846
+ ]
1690
1847
  }
1691
1848
  );
1692
1849
  };
1693
- var VenueShares = ({
1694
- position,
1695
- className,
1696
- keyPrefix
1697
- }) => /* @__PURE__ */ jsx6("div", { className, children: position.venueShareBreakdown.map((row, index) => /* @__PURE__ */ jsxs6(
1698
- "div",
1699
- {
1700
- className: "flex items-center gap-1",
1701
- children: [
1702
- /* @__PURE__ */ jsx6(VenueLogo, { venue: row.venue, size: "small", className: "size-4 shrink-0" }),
1703
- /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground whitespace-nowrap", children: row.sharesLabel })
1704
- ]
1705
- },
1706
- `${keyPrefix}-${row.venue}-${row.sharesLabel}-${String(index)}`
1707
- )) });
1708
- var ClosedResultBadge = ({
1709
- position,
1850
+ var ResultBadge = ({
1851
+ status,
1710
1852
  labels
1711
1853
  }) => {
1712
- if (!isMarketResolved(position)) return null;
1713
- if (position.winner == null) return null;
1714
- const isWon = position.winner === true;
1854
+ if (status !== "won_claimed" && status !== "lost" && status !== "sold") return null;
1855
+ const isWon = status === "won_claimed";
1856
+ const isSold = status === "sold";
1715
1857
  return /* @__PURE__ */ jsxs6(
1716
1858
  "span",
1717
1859
  {
1718
1860
  className: cn(
1719
- "inline-flex items-center gap-1 rounded-[4px] border px-2 py-[2px]",
1720
- isWon ? "border-agg-success/50 bg-agg-success/10 text-agg-success" : "border-agg-error/50 bg-agg-error/10 text-agg-error"
1861
+ "agg-position-result-badge inline-flex items-center justify-center gap-1 rounded-[4px] border px-2 py-[2px]",
1862
+ "font-agg-sans text-[10px] leading-agg-14 font-agg-bold uppercase whitespace-nowrap",
1863
+ isWon ? "border-agg-success/50 bg-agg-success/10 text-agg-success" : isSold ? "border-agg-muted-foreground/30 bg-agg-secondary-hover text-agg-muted-foreground" : "border-agg-error/50 bg-agg-error/10 text-agg-error"
1721
1864
  ),
1722
1865
  children: [
1723
- /* @__PURE__ */ jsx6(Icon, { name: isWon ? "check-circle" : "cross-circle", size: "small", className: "size-2.5" }),
1724
- /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-[10px] leading-agg-14 font-agg-bold uppercase", children: isWon ? labels.won : labels.lost })
1866
+ /* @__PURE__ */ jsx6(
1867
+ Icon,
1868
+ {
1869
+ name: isWon ? "check-circle" : isSold ? "hourglass-start" : "cross-circle",
1870
+ size: "small",
1871
+ className: "size-2.5!"
1872
+ }
1873
+ ),
1874
+ isWon ? labels.won : isSold ? labels.sold : labels.lost
1725
1875
  ]
1726
1876
  }
1727
1877
  );
1728
1878
  };
1729
- var ClosedClaimState = ({
1730
- claimStatus,
1731
- onClaim,
1732
- isClaiming,
1733
- labels
1734
- }) => {
1735
- if (claimStatus === "eligible") {
1736
- return /* @__PURE__ */ jsxs6(
1737
- "button",
1879
+ var TotalTradedCell = ({
1880
+ model,
1881
+ className
1882
+ }) => /* @__PURE__ */ jsxs6("div", { className: cn("flex flex-col gap-[2px] whitespace-nowrap", className), children: [
1883
+ /* @__PURE__ */ jsx6("p", { className: "font-agg-sans text-agg-base leading-agg-6 font-agg-bold text-agg-foreground", children: model.totalTraded.primaryLabel }),
1884
+ /* @__PURE__ */ jsx6("p", { className: "font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-muted-foreground", children: model.totalTraded.averageLabel })
1885
+ ] });
1886
+ var PositionValueCell = ({
1887
+ value,
1888
+ className
1889
+ }) => /* @__PURE__ */ jsxs6("div", { className: cn("flex flex-col gap-[2px] whitespace-nowrap", className), children: [
1890
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-baseline gap-1.5", children: [
1891
+ /* @__PURE__ */ jsx6("p", { className: "font-agg-sans text-agg-base leading-agg-6 font-agg-bold text-agg-foreground", children: value.primaryLabel }),
1892
+ /* @__PURE__ */ jsx6(
1893
+ "p",
1738
1894
  {
1739
- type: "button",
1740
- className: "inline-flex h-8 items-center justify-center gap-1 rounded-agg-full bg-agg-primary px-4 font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-white cursor-pointer disabled:cursor-not-allowed disabled:opacity-80",
1741
- onClick: (event) => {
1742
- event.preventDefault();
1743
- event.stopPropagation();
1744
- onClaim == null ? void 0 : onClaim();
1745
- },
1746
- disabled: isClaiming,
1747
- "aria-busy": isClaiming || void 0,
1748
- children: [
1749
- isClaiming ? /* @__PURE__ */ jsx6(LoadingIcon, { size: "small", className: "text-white" }) : null,
1750
- /* @__PURE__ */ jsx6("span", { children: labels.claim })
1751
- ]
1895
+ className: cn(
1896
+ "font-agg-sans text-agg-sm leading-agg-5 font-agg-normal",
1897
+ toneTextClassName(value.tone)
1898
+ ),
1899
+ children: value.deltaLabel
1752
1900
  }
1753
- );
1754
- }
1755
- if (claimStatus === "pending") {
1756
- return /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-xs leading-agg-4 font-agg-bold uppercase text-agg-muted-foreground", children: labels.pending });
1757
- }
1758
- if (claimStatus === "redeemed") {
1759
- return /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-xs leading-agg-4 font-agg-bold uppercase text-agg-muted-foreground", children: labels.claimed });
1760
- }
1761
- return null;
1762
- };
1901
+ )
1902
+ ] }),
1903
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-baseline gap-1.5", children: [
1904
+ /* @__PURE__ */ jsx6("p", { className: "font-agg-sans text-agg-sm leading-agg-5 font-agg-normal text-agg-foreground", children: value.priceLabel }),
1905
+ /* @__PURE__ */ jsx6(
1906
+ "p",
1907
+ {
1908
+ className: cn(
1909
+ "font-agg-sans text-agg-xs leading-agg-4 font-agg-normal",
1910
+ toneTextClassName(value.tone)
1911
+ ),
1912
+ children: value.percentLabel
1913
+ }
1914
+ )
1915
+ ] })
1916
+ ] });
1763
1917
  var PositionRow = ({
1764
1918
  position,
1765
1919
  variant,
@@ -1768,39 +1922,37 @@ var PositionRow = ({
1768
1922
  onClaim,
1769
1923
  isClaiming = false
1770
1924
  }) => {
1771
- var _a, _b, _c, _d, _e, _f, _g;
1772
1925
  const labels = useLabels3().userProfile.positions;
1773
- const resolvedVariant = variant != null ? variant : position.status === "closed" ? "closed" : "active";
1774
- const isClosed = resolvedVariant === "closed";
1775
- const badge = resolveBadge(position, labels);
1776
- const mobileValueLabel = isClosed ? (_a = position.closedAmountWonLabel) != null ? _a : position.valueLabel : position.valueLabel;
1777
- const mobileSecondaryLabel = isClosed ? (_b = position.closedReturnLabel) != null ? _b : position.pnlLabel : position.pnlLabel;
1778
- const closedReturnToneClass = resolveClosedReturnToneClass(position);
1779
- const mobileSecondaryToneClass = isClosed ? closedReturnToneClass : position.isPnlPositive ? "text-agg-success" : "text-agg-error";
1926
+ const model = toPositionRowViewModel(position, {
1927
+ avgPrefix: labels.avgPrefix,
1928
+ nowPrefix: labels.nowPrefix,
1929
+ finalPrefix: labels.finalPrefix
1930
+ });
1931
+ const isClosed = (variant != null ? variant : model.bucket) === "closed";
1932
+ const handleClaim = (event) => {
1933
+ event.preventDefault();
1934
+ event.stopPropagation();
1935
+ if (!model.canClaim || isClaiming) return;
1936
+ void (onClaim == null ? void 0 : onClaim(position));
1937
+ };
1780
1938
  const handleAnchorClick = (event) => {
1781
1939
  if (shouldUseNativeLinkNavigation2(event)) return;
1782
1940
  if (!onClick) return;
1783
1941
  event.preventDefault();
1784
1942
  onClick(position);
1785
1943
  };
1786
- const handleAnchorAuxClick = (event) => {
1787
- if (event.button !== 1) return;
1788
- };
1789
1944
  const handleDivClick = () => {
1790
1945
  onClick == null ? void 0 : onClick(position);
1791
1946
  };
1792
1947
  const sharedClassName = cn(
1793
- "agg-position-row",
1794
- "relative cursor-pointer block",
1948
+ "agg-position-row relative block cursor-pointer",
1795
1949
  "before:absolute before:-top-2 before:-left-2 before:-bottom-2 before:-right-2 before:z-0",
1796
- "before:transition-all before:duration-300 before:opacity-0 hover:before:opacity-100",
1797
- "before:bg-agg-secondary-hover before:rounded-agg-xl"
1950
+ "before:rounded-agg-xl before:bg-agg-secondary-hover before:opacity-0 before:transition-all before:duration-300 hover:before:opacity-100"
1798
1951
  );
1799
1952
  const Wrapper = href ? "a" : "div";
1800
1953
  const wrapperProps = href ? {
1801
1954
  href,
1802
- onClick: handleAnchorClick,
1803
- onAuxClick: handleAnchorAuxClick
1955
+ onClick: handleAnchorClick
1804
1956
  } : {
1805
1957
  role: "button",
1806
1958
  tabIndex: 0,
@@ -1815,29 +1967,28 @@ var PositionRow = ({
1815
1967
  "div",
1816
1968
  {
1817
1969
  className: cn(
1818
- "flex w-full flex-col gap-3 text-left transition-colors md:min-h-16 md:flex-row md:items-center",
1819
- isClosed ? "md:gap-10" : "md:gap-6",
1820
- "relative z-10"
1970
+ "relative z-10 flex w-full flex-col gap-3 text-left transition-colors md:min-h-16 md:flex-row md:items-center",
1971
+ isClosed ? "md:gap-8" : "md:gap-6"
1821
1972
  ),
1822
1973
  children: [
1823
- /* @__PURE__ */ jsxs6("div", { className: "flex w-full items-center justify-between gap-3 md:w-auto md:flex-1 md:min-w-0 md:justify-start md:gap-4", children: [
1974
+ /* @__PURE__ */ jsxs6("div", { className: "flex w-full items-center justify-between gap-3 md:w-auto md:min-w-0 md:flex-1 md:justify-start md:gap-4", children: [
1824
1975
  /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 flex-1 items-center gap-3 md:gap-4", children: [
1825
1976
  /* @__PURE__ */ jsx6("div", { className: "agg-position-image flex h-10 w-10 shrink-0 items-center justify-center md:h-15 md:w-15", children: /* @__PURE__ */ jsx6(
1826
1977
  RemoteImage,
1827
1978
  {
1828
- src: optimizedImageUrl(position.thumbnailSrc, 60),
1979
+ src: optimizedImageUrl(model.thumbnailSrc, 60),
1829
1980
  alt: "",
1830
1981
  className: "h-full w-full rounded-agg-sm object-cover"
1831
1982
  }
1832
1983
  ) }),
1833
- /* @__PURE__ */ jsxs6("div", { className: "min-w-0 flex flex-1 flex-col", children: [
1834
- /* @__PURE__ */ jsx6("p", { className: "agg-position-market min-w-0 overflow-hidden font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-agg-foreground [display:-webkit-box] [-webkit-line-clamp:2] [-webkit-box-orient:vertical] md:text-agg-base md:leading-agg-6 md:whitespace-nowrap md:text-ellipsis md:[-webkit-line-clamp:1] md:[display:block]", children: position.title }),
1984
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 flex-1 flex-col", children: [
1985
+ /* @__PURE__ */ jsx6("p", { className: "agg-position-market min-w-0 overflow-hidden font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-agg-foreground [display:-webkit-box] [-webkit-line-clamp:2] [-webkit-box-orient:vertical] md:block md:truncate md:text-agg-base md:leading-agg-6", children: model.title }),
1835
1986
  /* @__PURE__ */ jsxs6("div", { className: "hidden min-w-0 flex-1 flex-wrap items-center gap-x-3 gap-y-2 pt-1 md:flex", children: [
1836
- /* @__PURE__ */ jsx6(OutcomePill, { label: position.outcomeLabel }),
1987
+ /* @__PURE__ */ jsx6(OutcomePill, { label: model.selectedOutcomeLabel }),
1837
1988
  /* @__PURE__ */ jsx6(
1838
1989
  VenueShares,
1839
1990
  {
1840
- position,
1991
+ model,
1841
1992
  keyPrefix: "desktop",
1842
1993
  className: "agg-position-venues flex min-w-0 flex-1 flex-wrap content-center items-center gap-x-3 gap-y-2"
1843
1994
  }
@@ -1846,112 +1997,85 @@ var PositionRow = ({
1846
1997
  ] })
1847
1998
  ] }),
1848
1999
  /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-end justify-center gap-1 whitespace-nowrap md:hidden", children: [
1849
- /* @__PURE__ */ jsx6("p", { className: "agg-position-value font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-agg-foreground", children: mobileValueLabel }),
2000
+ /* @__PURE__ */ jsx6("p", { className: "agg-position-value font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-agg-foreground", children: isClosed ? model.payout.primaryLabel : model.currentValue.primaryLabel }),
1850
2001
  /* @__PURE__ */ jsx6(
1851
2002
  "p",
1852
2003
  {
1853
2004
  className: cn(
1854
2005
  "agg-position-pnl font-agg-sans text-agg-xs leading-agg-4 font-agg-normal",
1855
- mobileSecondaryToneClass
2006
+ toneTextClassName(isClosed ? model.payout.tone : model.currentValue.tone)
1856
2007
  ),
1857
- children: mobileSecondaryLabel
2008
+ children: isClosed ? model.payout.deltaLabel : model.currentValue.deltaLabel
1858
2009
  }
1859
2010
  )
1860
2011
  ] })
1861
2012
  ] }),
1862
- isClosed ? /* @__PURE__ */ jsxs6("div", { className: "flex w-full items-center gap-3 md:hidden", children: [
1863
- /* @__PURE__ */ jsx6(OutcomePill, { label: position.outcomeLabel }),
1864
- /* @__PURE__ */ jsx6(PositionBadgeNode, { badge }),
1865
- /* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-baseline gap-3", children: [
1866
- /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-lg leading-agg-7 font-agg-normal text-agg-foreground", children: (_c = position.closedTotalTradedLabel) != null ? _c : position.valueLabel }),
1867
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1.5", children: [
1868
- /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-lg leading-agg-7 font-agg-normal text-agg-foreground", children: (_d = position.closedAmountWonLabel) != null ? _d : position.valueLabel }),
1869
- /* @__PURE__ */ jsx6(ClosedResultBadge, { position, labels })
1870
- ] })
1871
- ] })
1872
- ] }) : /* @__PURE__ */ jsxs6("div", { className: "flex w-full items-baseline gap-3 md:hidden", children: [
1873
- /* @__PURE__ */ jsx6(OutcomePill, { label: position.outcomeLabel }),
1874
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-3", children: [
1875
- /* @__PURE__ */ jsxs6("div", { className: "flex items-baseline gap-1.5", children: [
1876
- /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-lg leading-agg-7 font-agg-normal text-agg-foreground", children: position.averageLabel }),
1877
- /* @__PURE__ */ jsx6("span", { className: "inline-flex md:hidden font-agg-sans text-agg-2xs leading-agg-14 font-agg-bold uppercase text-agg-muted-foreground", children: "AVG." }),
1878
- /* @__PURE__ */ jsx6("span", { className: "hidden md:inline-flex font-agg-sans text-agg-2xs leading-agg-14 font-agg-bold uppercase text-agg-muted-foreground", children: "Average" })
1879
- ] }),
1880
- /* @__PURE__ */ jsxs6("div", { className: "flex items-baseline gap-1.5", children: [
1881
- /* @__PURE__ */ jsx6("span", { className: "font-agg-sans text-agg-lg leading-agg-7 font-agg-normal text-agg-foreground", children: position.currentLabel }),
1882
- /* @__PURE__ */ jsx6("span", { className: "inline-flex md:hidden font-agg-sans text-agg-2xs leading-agg-14 font-agg-bold uppercase text-agg-muted-foreground", children: "CUR." }),
1883
- /* @__PURE__ */ jsx6("span", { className: "hidden md:inline-flex font-agg-sans text-agg-2xs leading-agg-14 font-agg-bold uppercase text-agg-muted-foreground", children: "Current" })
1884
- ] })
1885
- ] })
2013
+ /* @__PURE__ */ jsxs6("div", { className: "flex w-full flex-wrap items-center gap-3 md:hidden", children: [
2014
+ /* @__PURE__ */ jsx6(OutcomePill, { label: model.selectedOutcomeLabel }),
2015
+ isClosed ? /* @__PURE__ */ jsx6(ResultBadge, { status: model.positionStatus, labels }) : /* @__PURE__ */ jsx6(StatusBadge, { status: model.positionStatus, labels }),
2016
+ !isClosed && model.canClaim ? /* @__PURE__ */ jsxs6(
2017
+ "button",
2018
+ {
2019
+ type: "button",
2020
+ className: "ml-auto inline-flex h-8 items-center justify-center gap-1 rounded-agg-full px-2 font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-agg-accent disabled:cursor-not-allowed disabled:opacity-60",
2021
+ onClick: handleClaim,
2022
+ disabled: isClaiming,
2023
+ "aria-busy": isClaiming || void 0,
2024
+ children: [
2025
+ isClaiming ? /* @__PURE__ */ jsx6(LoadingIcon, { size: "small", className: "text-agg-accent" }) : null,
2026
+ labels.claim
2027
+ ]
2028
+ }
2029
+ ) : null
1886
2030
  ] }),
1887
2031
  /* @__PURE__ */ jsx6(
1888
2032
  VenueShares,
1889
2033
  {
1890
- position,
2034
+ model,
1891
2035
  keyPrefix: "mobile",
1892
2036
  className: "agg-position-venues flex min-w-0 flex-1 flex-wrap content-center items-center gap-x-3 gap-y-2 md:hidden"
1893
2037
  }
1894
2038
  ),
1895
2039
  isClosed ? /* @__PURE__ */ jsxs6(Fragment3, { children: [
1896
- /* @__PURE__ */ jsx6("p", { className: "hidden w-[160px] shrink-0 text-agg-base leading-agg-6 font-agg-bold text-agg-foreground md:block", children: (_e = position.closedTotalTradedLabel) != null ? _e : position.valueLabel }),
1897
- /* @__PURE__ */ jsxs6("div", { className: "hidden w-[160px] shrink-0 flex-col items-start gap-1 md:flex", children: [
1898
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
1899
- /* @__PURE__ */ jsx6("p", { className: "font-agg-sans text-agg-base leading-agg-6 font-agg-bold text-agg-foreground", children: (_f = position.closedAmountWonLabel) != null ? _f : position.valueLabel }),
1900
- /* @__PURE__ */ jsx6(ClosedResultBadge, { position, labels })
1901
- ] }),
1902
- /* @__PURE__ */ jsx6(
1903
- "p",
1904
- {
1905
- className: cn(
1906
- "font-agg-sans text-agg-base leading-agg-6 font-agg-normal",
1907
- closedReturnToneClass
1908
- ),
1909
- children: (_g = position.closedReturnLabel) != null ? _g : position.pnlLabel
1910
- }
1911
- )
1912
- ] }),
1913
- /* @__PURE__ */ jsx6("div", { className: "hidden min-w-[72px] shrink-0 items-center justify-center md:flex", children: /* @__PURE__ */ jsx6(
1914
- ClosedClaimState,
1915
- {
1916
- claimStatus: position.closedClaimStatus,
1917
- onClaim: onClaim ? () => void onClaim(position) : void 0,
1918
- isClaiming,
1919
- labels
1920
- }
1921
- ) }),
1922
- /* @__PURE__ */ jsx6("div", { className: "hidden w-11 shrink-0 items-center justify-end md:flex", children: /* @__PURE__ */ jsx6(
1923
- Icon,
2040
+ /* @__PURE__ */ jsx6("div", { className: "hidden w-[120px] shrink-0 md:block", children: /* @__PURE__ */ jsx6(OutcomePill, { label: model.resolutionLabel }) }),
2041
+ /* @__PURE__ */ jsx6(TotalTradedCell, { model, className: "hidden w-[140px] shrink-0 md:flex" }),
2042
+ /* @__PURE__ */ jsx6(PositionValueCell, { value: model.payout, className: "hidden w-[160px] shrink-0 md:flex" }),
2043
+ /* @__PURE__ */ jsx6("div", { className: "hidden w-[60px] shrink-0 items-center md:flex", children: /* @__PURE__ */ jsx6(ResultBadge, { status: model.positionStatus, labels }) })
2044
+ ] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
2045
+ /* @__PURE__ */ jsx6(TotalTradedCell, { model, className: "hidden w-[140px] shrink-0 md:flex" }),
2046
+ /* @__PURE__ */ jsx6(
2047
+ PositionValueCell,
1924
2048
  {
1925
- name: "chevron-right",
1926
- size: "small",
1927
- className: "size-5 shrink-0 text-agg-muted-foreground"
2049
+ value: model.currentValue,
2050
+ className: "hidden w-[160px] shrink-0 md:flex"
1928
2051
  }
1929
- ) })
1930
- ] }) : /* @__PURE__ */ jsxs6(Fragment3, { children: [
1931
- /* @__PURE__ */ jsx6("p", { className: "agg-position-average hidden w-[80px] shrink-0 agg-type-title text-agg-foreground md:block", children: position.averageLabel }),
1932
- /* @__PURE__ */ jsx6("p", { className: "agg-position-current hidden w-[80px] shrink-0 agg-type-title text-agg-foreground md:block", children: position.currentLabel }),
1933
- /* @__PURE__ */ jsxs6("div", { className: "hidden w-[120px] shrink-0 flex-col items-end justify-center gap-1 whitespace-nowrap md:flex", children: [
1934
- /* @__PURE__ */ jsx6("p", { className: "agg-position-value font-agg-sans text-agg-base leading-agg-6 font-agg-bold text-agg-foreground", children: position.valueLabel }),
1935
- /* @__PURE__ */ jsx6(
1936
- "p",
2052
+ ),
2053
+ /* @__PURE__ */ jsxs6("div", { className: "hidden w-[100px] shrink-0 items-center gap-2 md:flex", children: [
2054
+ /* @__PURE__ */ jsx6(StatusBadge, { status: model.positionStatus, labels }),
2055
+ model.canClaim ? /* @__PURE__ */ jsxs6(
2056
+ "button",
1937
2057
  {
1938
- className: cn(
1939
- "agg-position-pnl font-agg-sans text-agg-sm leading-agg-5 font-agg-normal",
1940
- position.isPnlPositive ? "text-agg-success" : "text-agg-error"
1941
- ),
1942
- children: position.pnlLabel
2058
+ type: "button",
2059
+ className: "inline-flex h-6 items-center justify-center gap-1 rounded-agg-full font-agg-sans text-agg-sm leading-agg-5 font-agg-bold text-agg-primary disabled:cursor-not-allowed disabled:opacity-60",
2060
+ onClick: handleClaim,
2061
+ disabled: isClaiming,
2062
+ "aria-busy": isClaiming || void 0,
2063
+ children: [
2064
+ isClaiming ? /* @__PURE__ */ jsx6(LoadingIcon, { size: "small", className: "text-agg-primary" }) : null,
2065
+ labels.claim
2066
+ ]
1943
2067
  }
1944
- )
1945
- ] }),
1946
- /* @__PURE__ */ jsx6("div", { className: "hidden w-11 shrink-0 items-center justify-end md:flex", children: /* @__PURE__ */ jsx6(
1947
- Icon,
1948
- {
1949
- name: "chevron-right",
1950
- size: "small",
1951
- className: "size-5 shrink-0 text-agg-muted-foreground"
1952
- }
1953
- ) })
1954
- ] })
2068
+ ) : null
2069
+ ] })
2070
+ ] }),
2071
+ /* @__PURE__ */ jsx6("div", { className: "hidden w-5 shrink-0 items-center justify-end md:flex", children: /* @__PURE__ */ jsx6(
2072
+ Icon,
2073
+ {
2074
+ name: "chevron-right",
2075
+ size: "small",
2076
+ className: "size-5 shrink-0 text-agg-muted-foreground"
2077
+ }
2078
+ ) })
1955
2079
  ]
1956
2080
  }
1957
2081
  ) }));
@@ -2012,18 +2136,45 @@ var PositionsActivity = ({
2012
2136
  const [positionFilter, setPositionFilter] = useState5(initialPositionFilter);
2013
2137
  const [searchValue, setSearchValue] = useState5("");
2014
2138
  const [isSearchFocused, setIsSearchFocused] = useState5(false);
2139
+ const [locallyClaimedPositionIds, setLocallyClaimedPositionIds] = useState5(
2140
+ () => /* @__PURE__ */ new Set()
2141
+ );
2015
2142
  const positionsLoadMoreRef = useRef3(null);
2016
2143
  const activitiesLoadMoreRef = useRef3(null);
2017
2144
  const rowsScrollRef = useRef3(null);
2018
2145
  const isPositionsTab = activeTab === USER_PROFILE_TAB_POSITIONS;
2019
2146
  const isActivityTab = activeTab === USER_PROFILE_TAB_ACTIVITY;
2020
2147
  const isClosedPositionsFilter = isPositionsTab && positionFilter === "closed";
2021
- const positionsForCurrentFilter = positionFilter === "active" ? activePositions : closedPositions;
2148
+ const positionsForCurrentFilter = useMemo2(() => {
2149
+ if (positionFilter === "active") {
2150
+ return activePositions.filter((position) => !locallyClaimedPositionIds.has(position.id));
2151
+ }
2152
+ const byId = /* @__PURE__ */ new Map();
2153
+ for (const position of closedPositions) {
2154
+ byId.set(position.id, position);
2155
+ }
2156
+ for (const position of activePositions) {
2157
+ if (!locallyClaimedPositionIds.has(position.id)) continue;
2158
+ byId.set(position.id, __spreadProps(__spreadValues({}, position), {
2159
+ status: "closed",
2160
+ closedClaimStatus: "redeemed"
2161
+ }));
2162
+ }
2163
+ return Array.from(byId.values());
2164
+ }, [activePositions, closedPositions, locallyClaimedPositionIds, positionFilter]);
2022
2165
  const filteredPositions = useMemo2(() => {
2023
2166
  if (!searchValue.trim()) return positionsForCurrentFilter;
2024
2167
  const q = searchValue.toLowerCase();
2025
2168
  return positionsForCurrentFilter.filter((p) => p.title.toLowerCase().includes(q));
2026
2169
  }, [positionsForCurrentFilter, searchValue]);
2170
+ const handleClaimPosition = (position) => __async(null, null, function* () {
2171
+ yield onClaim == null ? void 0 : onClaim(position);
2172
+ setLocallyClaimedPositionIds((prev) => {
2173
+ const next = new Set(prev);
2174
+ next.add(position.id);
2175
+ return next;
2176
+ });
2177
+ });
2027
2178
  const handlePositionFilterChange = (filter) => {
2028
2179
  setPositionFilter(filter);
2029
2180
  onPositionFilterChange == null ? void 0 : onPositionFilterChange(filter);
@@ -2039,10 +2190,14 @@ var PositionsActivity = ({
2039
2190
  title: position.title,
2040
2191
  thumbnailSrc: position.thumbnailSrc,
2041
2192
  metaPrimary: position.outcomeLabel,
2042
- metaSecondary: position.valueLabel,
2193
+ metaSecondary: toPositionRowViewModel(position, {
2194
+ avgPrefix: positionsLabels.avgPrefix,
2195
+ nowPrefix: positionsLabels.nowPrefix,
2196
+ finalPrefix: positionsLabels.finalPrefix
2197
+ }).currentValue.primaryLabel,
2043
2198
  raw: position
2044
2199
  }));
2045
- }, [filteredPositions, isPositionsTab, searchValue]);
2200
+ }, [filteredPositions, isPositionsTab, positionsLabels, searchValue]);
2046
2201
  const handleSearchChange = (event) => {
2047
2202
  setSearchValue(event.target.value);
2048
2203
  };
@@ -2140,7 +2295,7 @@ var PositionsActivity = ({
2140
2295
  "flex flex-1 cursor-pointer items-center justify-center px-3 py-3 font-agg-sans text-agg-sm leading-agg-5 sm:px-4 sm:text-agg-base sm:leading-agg-6",
2141
2296
  isActive ? "bg-agg-secondary-hover font-agg-bold text-agg-primary" : "bg-agg-secondary font-agg-normal text-agg-foreground hover:bg-agg-secondary-hover"
2142
2297
  ),
2143
- children: filter.label
2298
+ children: filter.value === "active" ? positionsLabels.activeFilter : positionsLabels.closedFilter
2144
2299
  }
2145
2300
  )
2146
2301
  ] }, filter.value);
@@ -2163,7 +2318,7 @@ var PositionsActivity = ({
2163
2318
  {
2164
2319
  value: searchValue,
2165
2320
  onChange: handleSearchChange,
2166
- placeholder: "Search...",
2321
+ placeholder: positionsLabels.searchPlaceholder,
2167
2322
  className: cn(
2168
2323
  "h-6 w-full min-w-0 border-0 bg-transparent p-0",
2169
2324
  "font-agg-sans text-agg-base leading-agg-6 font-agg-normal text-agg-foreground",
@@ -2251,25 +2406,26 @@ var PositionsActivity = ({
2251
2406
  );
2252
2407
  })
2253
2408
  }
2254
- ) : /* @__PURE__ */ jsx7("div", { className: "px-5 py-6 font-agg-sans text-agg-sm leading-agg-5 text-agg-muted-foreground", children: "No results" }) }) : null
2409
+ ) : /* @__PURE__ */ jsx7("div", { className: "px-5 py-6 font-agg-sans text-agg-sm leading-agg-5 text-agg-muted-foreground", children: positionsLabels.noResults }) }) : null
2255
2410
  ]
2256
2411
  }
2257
2412
  )
2258
2413
  ] }) : null,
2259
2414
  /* @__PURE__ */ jsxs7("div", { className: "agg-positions-table-wrapper flex w-full gap-0 flex-col", children: [
2260
2415
  /* @__PURE__ */ jsxs7("div", { className: "w-full px-4 sm:px-6", children: [
2261
- isPositionsTab && filteredPositions.length > 0 ? isClosedPositionsFilter ? /* @__PURE__ */ jsxs7("div", { className: "hidden items-start gap-10 px-0 md:flex", children: [
2262
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header min-w-0 flex-1", children: "Market" }),
2263
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[160px] shrink-0", children: positionsLabels.totalTradedHeader }),
2264
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[160px] shrink-0", children: positionsLabels.amountWonHeader }),
2265
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header min-w-[72px] shrink-0 text-center", children: positionsLabels.claimHeader }),
2266
- /* @__PURE__ */ jsx7("span", { className: "hidden w-11 shrink-0 sm:block", "aria-hidden": true })
2416
+ isPositionsTab && filteredPositions.length > 0 ? isClosedPositionsFilter ? /* @__PURE__ */ jsxs7("div", { className: "hidden items-start gap-8 px-0 md:flex", children: [
2417
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header min-w-0 flex-1", children: positionsLabels.marketHeader }),
2418
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[120px] shrink-0", children: positionsLabels.resolutionHeader }),
2419
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[140px] shrink-0", children: positionsLabels.totalTradedHeader }),
2420
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[160px] shrink-0", children: positionsLabels.payoutHeader }),
2421
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[60px] shrink-0", children: positionsLabels.resultHeader }),
2422
+ /* @__PURE__ */ jsx7("span", { className: "hidden w-5 shrink-0 sm:block", "aria-hidden": true })
2267
2423
  ] }) : /* @__PURE__ */ jsxs7("div", { className: "hidden items-start gap-6 px-0 md:flex", children: [
2268
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header min-w-0 flex-1", children: "Market" }),
2269
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[80px] shrink-0", children: "Average" }),
2270
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[80px] shrink-0", children: "Current" }),
2271
- /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[120px] shrink-0 text-right", children: "Value" }),
2272
- /* @__PURE__ */ jsx7("span", { className: "hidden w-11 shrink-0 sm:block", "aria-hidden": true })
2424
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header min-w-0 flex-1", children: positionsLabels.marketHeader }),
2425
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[140px] shrink-0", children: positionsLabels.totalTradedHeader }),
2426
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[160px] shrink-0", children: positionsLabels.currentValueHeader }),
2427
+ /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-[100px] shrink-0", children: positionsLabels.statusHeader }),
2428
+ /* @__PURE__ */ jsx7("span", { className: "hidden w-5 shrink-0 sm:block", "aria-hidden": true })
2273
2429
  ] }) : null,
2274
2430
  isActivityTab && filteredActivities.length > 0 ? /* @__PURE__ */ jsxs7("div", { className: "hidden items-start gap-6 px-0 md:flex", children: [
2275
2431
  /* @__PURE__ */ jsx7("p", { className: "agg-user-profile-table-header w-22 shrink-0", children: "Type" }),
@@ -2313,7 +2469,7 @@ var PositionsActivity = ({
2313
2469
  variant: positionFilter,
2314
2470
  href: getPositionHref == null ? void 0 : getPositionHref(position),
2315
2471
  onClick: onPositionClick,
2316
- onClaim,
2472
+ onClaim: handleClaimPosition,
2317
2473
  isClaiming: Boolean(
2318
2474
  claimingPositionKeys == null ? void 0 : claimingPositionKeys[(_a = position.marketId) != null ? _a : position.id]
2319
2475
  )
@@ -2827,7 +2983,8 @@ var OPEN_ORDER_STATUSES = /* @__PURE__ */ new Set([
2827
2983
  "submitting",
2828
2984
  "submitted"
2829
2985
  ]);
2830
- var OPEN_ORDERS_REFETCH_INTERVAL_MS = 1e4;
2986
+ var SHOW_SOLD_POSITIONS = false;
2987
+ var SOLD_POSITION_SHARES_THRESHOLD = 0.1;
2831
2988
  var isOpenOrderStatus = (status) => OPEN_ORDER_STATUSES.has(status.toLowerCase());
2832
2989
  var getActivityErrorMessage = (item) => {
2833
2990
  if (!("errorMessage" in item)) return null;
@@ -2985,7 +3142,9 @@ var UserProfilePage = ({
2985
3142
  const client = useAggClient();
2986
3143
  const labels = useLabels6();
2987
3144
  const queryClient = useQueryClient();
3145
+ const redeemMutation = useRedeem();
2988
3146
  const [internalCancellingIds, setInternalCancellingIds] = useState6({});
3147
+ const [internalClaimingIds, setInternalClaimingIds] = useState6({});
2989
3148
  const [profileUser, setProfileUser] = useState6(void 0);
2990
3149
  const shouldUseHookData = !user;
2991
3150
  const connectedVenues = useMemo3(() => {
@@ -3000,33 +3159,25 @@ var UserProfilePage = ({
3000
3159
  status: "active",
3001
3160
  limit: 25
3002
3161
  });
3003
- const [hasVisitedClosedTab, setHasVisitedClosedTab] = useState6(
3004
- initialPositionFilter === "closed"
3005
- );
3006
3162
  const closedPositionsQuery = useExecutionPositions({
3007
- enabled: shouldUseHookData && isAuthenticated && hasVisitedClosedTab,
3163
+ enabled: shouldUseHookData && isAuthenticated,
3008
3164
  status: "closed",
3009
3165
  limit: 25
3010
3166
  });
3011
3167
  const handlePositionFilterChange = useCallback3(
3012
3168
  (filter) => {
3013
3169
  setPositionFilter(filter);
3014
- if (filter === "closed") setHasVisitedClosedTab(true);
3015
3170
  onPositionFilterChangeProp == null ? void 0 : onPositionFilterChangeProp(filter);
3016
3171
  },
3017
3172
  [onPositionFilterChangeProp]
3018
3173
  );
3019
3174
  useEffect4(() => {
3020
3175
  setPositionFilter(initialPositionFilter);
3021
- if (initialPositionFilter === "closed") {
3022
- setHasVisitedClosedTab(true);
3023
- }
3024
3176
  }, [initialPositionFilter]);
3025
3177
  const ordersQuery = useExecutionOrders({
3026
3178
  enabled: shouldUseHookData && isAuthenticated,
3027
3179
  limit: 25
3028
3180
  });
3029
- const { refetch: refetchOrders } = ordersQuery;
3030
3181
  const activityQuery = useUserActivity({
3031
3182
  enabled: shouldUseHookData && isAuthenticated,
3032
3183
  limit: 25
@@ -3055,13 +3206,29 @@ var UserProfilePage = ({
3055
3206
  }),
3056
3207
  [client, onCancelOrder, queryClient]
3057
3208
  );
3058
- useEffect4(() => {
3059
- if (!shouldUseHookData || !isAuthenticated || typeof refetchOrders !== "function") return;
3060
- const intervalId = window.setInterval(() => {
3061
- void refetchOrders();
3062
- }, OPEN_ORDERS_REFETCH_INTERVAL_MS);
3063
- return () => window.clearInterval(intervalId);
3064
- }, [isAuthenticated, refetchOrders, shouldUseHookData]);
3209
+ const handleClaimPosition = useCallback3(
3210
+ (position) => __async(null, null, function* () {
3211
+ var _a, _b;
3212
+ if (onClaim) {
3213
+ yield onClaim(position);
3214
+ return;
3215
+ }
3216
+ const venueMarketOutcomeIds = (_a = position.winningOutcomeIds) != null ? _a : [];
3217
+ if (venueMarketOutcomeIds.length === 0) return;
3218
+ const claimKey = (_b = position.marketId) != null ? _b : position.id;
3219
+ setInternalClaimingIds((prev) => __spreadProps(__spreadValues({}, prev), { [claimKey]: true }));
3220
+ try {
3221
+ yield redeemMutation.mutateAsync({ venueMarketOutcomeIds });
3222
+ yield queryClient.invalidateQueries({ queryKey: ["current-user"] });
3223
+ } finally {
3224
+ setInternalClaimingIds((prev) => {
3225
+ const _a2 = prev, { [claimKey]: _removed } = _a2, rest = __objRest(_a2, [__restKey(claimKey)]);
3226
+ return rest;
3227
+ });
3228
+ }
3229
+ }),
3230
+ [onClaim, queryClient, redeemMutation]
3231
+ );
3065
3232
  useEffect4(() => {
3066
3233
  if (!shouldUseHookData || !isAuthenticated) {
3067
3234
  setProfileUser(void 0);
@@ -3261,17 +3428,28 @@ var UserProfilePage = ({
3261
3428
  (groups) => {
3262
3429
  return groups.flatMap((group) => {
3263
3430
  var _a, _b;
3264
- const closedTotals = group.status === "closed" ? computeClosedPositionTotals(group) : void 0;
3431
+ const closedTotals = computeClosedPositionTotals(group);
3265
3432
  const venueEventId = (_a = group.venueMarket.venueEventId) != null ? _a : void 0;
3266
3433
  const eventId = (_b = group.eventId) != null ? _b : venueEventId;
3267
3434
  const marketId = group.targetMarketId;
3268
3435
  return group.venueMarket.venueMarketOutcomes.map((outcome) => {
3269
3436
  var _a2, _b2, _c, _d;
3437
+ const isResolved = group.venueMarket.status === "resolved";
3270
3438
  const isUnpriced = outcome.priceSource === "entry";
3271
- const currentPriceCents = Math.round(outcome.currentPrice * 100);
3272
3439
  const averagePriceCents = Math.round(outcome.avgEntryPrice * 100);
3273
- const pnlPrefix = outcome.unrealizedPnl >= 0 ? "+" : "";
3274
- const pnlPercent = outcome.unrealizedPnlPercent.toFixed(2);
3440
+ const totalTradedValue = outcome.avgEntryPrice * outcome.totalSize;
3441
+ const finalPayoutValue = isResolved ? outcome.winner === true ? outcome.totalValue : 0 : outcome.totalValue;
3442
+ const finalPrice = isResolved ? outcome.winner === true ? 1 : 0 : outcome.currentPrice;
3443
+ const finalPnlValue = finalPayoutValue - totalTradedValue;
3444
+ const finalPnlPercent = totalTradedValue === 0 ? 0 : finalPnlValue / Math.abs(totalTradedValue) * 100;
3445
+ const displayCurrentPrice = isResolved ? finalPrice : isUnpriced ? null : outcome.currentPrice;
3446
+ const displayCurrentValue = isResolved ? finalPayoutValue : isUnpriced ? null : outcome.totalValue;
3447
+ const displayPnlValue = isResolved ? finalPnlValue : isUnpriced ? null : outcome.unrealizedPnl;
3448
+ const displayPnlPercent = isResolved ? finalPnlPercent : isUnpriced ? null : outcome.unrealizedPnlPercent;
3449
+ const currentPriceCents = typeof displayCurrentPrice === "number" ? Math.round(displayCurrentPrice * 100) : null;
3450
+ const pnlPrefix = (displayPnlValue != null ? displayPnlValue : 0) >= 0 ? "+" : "";
3451
+ const pnlPercent = displayPnlPercent == null ? null : displayPnlPercent.toFixed(2);
3452
+ const winningOutcomeIds = outcome.winner === true ? outcome.venueBreakdown.map((breakdown) => breakdown.venueMarketOutcomeId).filter((id) => !!id) : [];
3275
3453
  return {
3276
3454
  id: `${group.targetMarketId}-${outcome.label}-${(_a2 = outcome.title) != null ? _a2 : ""}`,
3277
3455
  eventId,
@@ -3280,20 +3458,31 @@ var UserProfilePage = ({
3280
3458
  title: group.venueMarket.question,
3281
3459
  outcomeLabel: ((_c = outcome.title) == null ? void 0 : _c.trim()) || outcome.label,
3282
3460
  venueShareBreakdown: buildVenueShareBreakdown(outcome),
3461
+ totalShares: outcome.totalSize,
3283
3462
  averageLabel: `${averagePriceCents}\xA2`,
3284
- currentLabel: isUnpriced ? "\u2014" : `${currentPriceCents}\xA2`,
3285
- valueLabel: isUnpriced ? "\u2014" : formatUsd(outcome.totalValue),
3286
- pnlLabel: isUnpriced ? "\u2014" : `${pnlPrefix}${formatUsd(outcome.unrealizedPnl)} (${pnlPrefix}${pnlPercent}%)`,
3287
- isPnlPositive: !isUnpriced && outcome.unrealizedPnl >= 0,
3463
+ averagePrice: outcome.avgEntryPrice,
3464
+ currentLabel: currentPriceCents == null ? "\u2014" : `${currentPriceCents}\xA2`,
3465
+ currentPrice: displayCurrentPrice,
3466
+ valueLabel: displayCurrentValue == null ? "\u2014" : formatUsd(displayCurrentValue),
3467
+ currentValue: displayCurrentValue,
3468
+ pnlLabel: displayPnlValue == null || pnlPercent == null ? "\u2014" : `${pnlPrefix}${formatUsd(displayPnlValue)} (${pnlPrefix}${pnlPercent}%)`,
3469
+ pnlValue: displayPnlValue,
3470
+ pnlPercent: displayPnlPercent,
3471
+ isPnlPositive: displayPnlValue != null && displayPnlValue >= 0,
3288
3472
  status: group.status,
3289
3473
  marketStatus: group.venueMarket.status,
3290
3474
  winner: (_d = outcome.winner) != null ? _d : null,
3291
3475
  resolutionDate: group.resolutionDate,
3292
- closedTotalTradedLabel: closedTotals ? formatUsd(closedTotals.totalTraded) : void 0,
3293
- closedAmountWonLabel: closedTotals ? formatUsd(closedTotals.amountWon) : void 0,
3294
- closedReturnLabel: closedTotals ? formatSignedPercentLabel(closedTotals.returnPct) : void 0,
3295
- closedClaimStatus: closedTotals ? group.redeemStatus : void 0,
3296
- winningOutcomeIds: closedTotals == null ? void 0 : closedTotals.winningOutcomeIds
3476
+ closedTotalTradedLabel: formatUsd(totalTradedValue),
3477
+ totalTradedValue,
3478
+ closedAmountWonLabel: formatUsd(finalPayoutValue),
3479
+ finalPayoutValue,
3480
+ finalPnlValue,
3481
+ finalPnlPercent,
3482
+ finalPrice,
3483
+ closedReturnLabel: formatSignedPercentLabel(finalPnlPercent / 100),
3484
+ closedClaimStatus: group.redeemStatus,
3485
+ winningOutcomeIds: winningOutcomeIds.length > 0 ? winningOutcomeIds : closedTotals.winningOutcomeIds
3297
3486
  };
3298
3487
  });
3299
3488
  });
@@ -3301,13 +3490,73 @@ var UserProfilePage = ({
3301
3490
  []
3302
3491
  );
3303
3492
  const resolvedActivePositions = useMemo3(() => {
3304
- if (activePositions) return activePositions;
3305
- return adaptPositionGroups(activePositionsQuery.positions);
3306
- }, [activePositions, activePositionsQuery.positions, adaptPositionGroups]);
3493
+ const shouldIncludeByShares = (position) => {
3494
+ if (SHOW_SOLD_POSITIONS) return true;
3495
+ if (typeof position.totalShares !== "number") return true;
3496
+ return position.totalShares >= SOLD_POSITION_SHARES_THRESHOLD;
3497
+ };
3498
+ const classifyPosition = (position) => {
3499
+ if (position.winner === true) {
3500
+ return position.closedClaimStatus === "redeemed" ? "closed" : "active";
3501
+ }
3502
+ if (position.winner === false) return "closed";
3503
+ if (position.marketStatus === "closed" || position.marketStatus === "resolved") {
3504
+ return "closed";
3505
+ }
3506
+ return "active";
3507
+ };
3508
+ const sourcePositions = activePositions || closedPositions ? [...activePositions != null ? activePositions : [], ...closedPositions != null ? closedPositions : []] : [
3509
+ ...adaptPositionGroups(activePositionsQuery.positions),
3510
+ ...adaptPositionGroups(closedPositionsQuery.positions)
3511
+ ];
3512
+ const deduped = /* @__PURE__ */ new Map();
3513
+ for (const position of sourcePositions) {
3514
+ deduped.set(position.id, position);
3515
+ }
3516
+ return Array.from(deduped.values()).filter(
3517
+ (position) => shouldIncludeByShares(position) && classifyPosition(position) === "active"
3518
+ );
3519
+ }, [
3520
+ activePositions,
3521
+ activePositionsQuery.positions,
3522
+ adaptPositionGroups,
3523
+ closedPositions,
3524
+ closedPositionsQuery.positions
3525
+ ]);
3307
3526
  const resolvedClosedPositions = useMemo3(() => {
3308
- const base = closedPositions != null ? closedPositions : adaptPositionGroups(closedPositionsQuery.positions);
3309
- return base.filter((p) => p.marketStatus === "resolved");
3310
- }, [closedPositions, closedPositionsQuery.positions, adaptPositionGroups]);
3527
+ const shouldIncludeByShares = (position) => {
3528
+ if (SHOW_SOLD_POSITIONS) return true;
3529
+ if (typeof position.totalShares !== "number") return true;
3530
+ return position.totalShares >= SOLD_POSITION_SHARES_THRESHOLD;
3531
+ };
3532
+ const classifyPosition = (position) => {
3533
+ if (position.winner === true) {
3534
+ return position.closedClaimStatus === "redeemed" ? "closed" : "active";
3535
+ }
3536
+ if (position.winner === false) return "closed";
3537
+ if (position.marketStatus === "closed" || position.marketStatus === "resolved") {
3538
+ return "closed";
3539
+ }
3540
+ return "active";
3541
+ };
3542
+ const sourcePositions = activePositions || closedPositions ? [...activePositions != null ? activePositions : [], ...closedPositions != null ? closedPositions : []] : [
3543
+ ...adaptPositionGroups(activePositionsQuery.positions),
3544
+ ...adaptPositionGroups(closedPositionsQuery.positions)
3545
+ ];
3546
+ const deduped = /* @__PURE__ */ new Map();
3547
+ for (const position of sourcePositions) {
3548
+ deduped.set(position.id, position);
3549
+ }
3550
+ return Array.from(deduped.values()).filter(
3551
+ (position) => shouldIncludeByShares(position) && classifyPosition(position) === "closed"
3552
+ );
3553
+ }, [
3554
+ activePositions,
3555
+ activePositionsQuery.positions,
3556
+ adaptPositionGroups,
3557
+ closedPositions,
3558
+ closedPositionsQuery.positions
3559
+ ]);
3311
3560
  return /* @__PURE__ */ jsx11(AggErrorBoundary, { onError, children: /* @__PURE__ */ jsx11(
3312
3561
  "section",
3313
3562
  {
@@ -3382,8 +3631,8 @@ var UserProfilePage = ({
3382
3631
  openOrders: resolvedOpenOrders,
3383
3632
  onPositionClick,
3384
3633
  getPositionHref,
3385
- onClaim,
3386
- claimingPositionKeys,
3634
+ onClaim: handleClaimPosition,
3635
+ claimingPositionKeys: claimingPositionKeys != null ? claimingPositionKeys : internalClaimingIds,
3387
3636
  onActivityClick,
3388
3637
  getActivityHref,
3389
3638
  onOpenOrderClick,