@loafmarkets/ui 0.1.13 → 0.1.16

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.
package/dist/index.js CHANGED
@@ -3374,6 +3374,7 @@ var YourOrders = React5__namespace.forwardRef(
3374
3374
  onTabChange,
3375
3375
  renderOrderActions,
3376
3376
  renderTabContent,
3377
+ pageSize: pageSizeOverride,
3377
3378
  ...props
3378
3379
  }, ref) => {
3379
3380
  const [internalActiveTab, setInternalActiveTab] = React5__namespace.useState(tabs?.[0]?.id ?? "portfolio");
@@ -3394,7 +3395,8 @@ var YourOrders = React5__namespace.forwardRef(
3394
3395
  const activeOrders = activeTab?.orders ?? orders ?? [];
3395
3396
  const DEFAULT_PAGE_SIZE = 5;
3396
3397
  const HISTORY_PAGE_SIZE = 3;
3397
- const pageSize = activeTab?.id === "order-history" || activeTab?.id === "trade-history" ? HISTORY_PAGE_SIZE : DEFAULT_PAGE_SIZE;
3398
+ const resolvedPageSize = pageSizeOverride ?? (activeTab?.id === "order-history" || activeTab?.id === "trade-history" ? HISTORY_PAGE_SIZE : DEFAULT_PAGE_SIZE);
3399
+ const pageSize = Math.max(1, resolvedPageSize);
3398
3400
  const totalOrders = activeOrders.length;
3399
3401
  const totalPages = Math.max(1, Math.ceil(totalOrders / pageSize));
3400
3402
  const safePage = Math.min(page, totalPages - 1);
@@ -4090,6 +4092,10 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
4090
4092
  propertyTypeLabel,
4091
4093
  onTrade,
4092
4094
  onMakeOffer,
4095
+ tradeButtonLabel = "Trade",
4096
+ makeOfferButtonLabel = "Make Offer",
4097
+ makeOfferDisabled = false,
4098
+ hideMakeOfferButton = false,
4093
4099
  ...props
4094
4100
  }, ref) => {
4095
4101
  const isPositive = changePercent == null ? void 0 : changePercent >= 0;
@@ -4098,6 +4104,17 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
4098
4104
  const [isTradeInteracting, setIsTradeInteracting] = React5__namespace.useState(false);
4099
4105
  const [isOfferInteracting, setIsOfferInteracting] = React5__namespace.useState(false);
4100
4106
  const hasAmenities = beds != null || baths != null || cars != null || propertyTypeLabel != null;
4107
+ const isTradeDisabled = !onTrade;
4108
+ const isMakeOfferButtonDisabled = makeOfferDisabled || !onMakeOffer;
4109
+ const showMakeOfferButton = !hideMakeOfferButton;
4110
+ const setTradeInteraction = (state) => {
4111
+ if (isTradeDisabled) return;
4112
+ setIsTradeInteracting(state);
4113
+ };
4114
+ const setOfferInteraction = (state) => {
4115
+ if (isMakeOfferButtonDisabled) return;
4116
+ setIsOfferInteracting(state);
4117
+ };
4101
4118
  const headingStyle = {
4102
4119
  fontSize: "clamp(1.6rem, 4vw, 2.5rem)",
4103
4120
  marginBottom: "0.5rem",
@@ -4182,54 +4199,60 @@ var PropertyHeroHeader = React5__namespace.forwardRef(
4182
4199
  "button",
4183
4200
  {
4184
4201
  type: "button",
4185
- onClick: onTrade,
4202
+ onClick: isTradeDisabled ? void 0 : onTrade,
4186
4203
  className: "flex items-center justify-center rounded border font-semibold transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_8px_rgba(0,0,0,0.2)] active:translate-y-0 active:shadow-[0_2px_4px_rgba(0,0,0,0.1)] text-[0.95rem] max-[480px]:text-[0.9rem]",
4187
4204
  style: {
4188
4205
  backgroundColor: isTradeInteracting ? tradeHoverColor : accentColor,
4189
4206
  color: "black",
4190
- width: "88.06px",
4191
- height: "43px",
4192
- minWidth: "88.06px",
4207
+ minWidth: "140px",
4208
+ padding: "0.65rem 1.5rem",
4193
4209
  borderColor: isTradeInteracting ? accentColor : "transparent",
4194
- boxShadow: isTradeInteracting ? `0 0 0 2px rgba(0,0,0,0.4), 0 0 0 4px ${accentColor}` : "none"
4210
+ boxShadow: isTradeInteracting ? `0 0 0 2px rgba(0,0,0,0.4), 0 0 0 4px ${accentColor}` : "none",
4211
+ opacity: isTradeDisabled ? 0.5 : 1,
4212
+ cursor: isTradeDisabled ? "not-allowed" : "pointer"
4195
4213
  },
4196
- onMouseEnter: () => setIsTradeInteracting(true),
4197
- onMouseLeave: () => setIsTradeInteracting(false),
4198
- onMouseDown: () => setIsTradeInteracting(true),
4199
- onMouseUp: () => setIsTradeInteracting(false),
4200
- onFocus: () => setIsTradeInteracting(true),
4201
- onBlur: () => setIsTradeInteracting(false),
4202
- onTouchStart: () => setIsTradeInteracting(true),
4203
- onTouchEnd: () => setIsTradeInteracting(false),
4204
- children: "Trade"
4214
+ onMouseEnter: () => setTradeInteraction(true),
4215
+ onMouseLeave: () => setTradeInteraction(false),
4216
+ onMouseDown: () => setTradeInteraction(true),
4217
+ onMouseUp: () => setTradeInteraction(false),
4218
+ onFocus: () => setTradeInteraction(true),
4219
+ onBlur: () => setTradeInteraction(false),
4220
+ onTouchStart: () => setTradeInteraction(true),
4221
+ onTouchEnd: () => setTradeInteraction(false),
4222
+ disabled: isTradeDisabled,
4223
+ "aria-disabled": isTradeDisabled,
4224
+ children: tradeButtonLabel
4205
4225
  }
4206
4226
  ),
4207
- /* @__PURE__ */ jsxRuntime.jsx(
4227
+ showMakeOfferButton ? /* @__PURE__ */ jsxRuntime.jsx(
4208
4228
  "button",
4209
4229
  {
4210
4230
  type: "button",
4211
- onClick: onMakeOffer,
4231
+ onClick: isMakeOfferButtonDisabled ? void 0 : onMakeOffer,
4212
4232
  className: "flex items-center justify-center rounded border font-semibold transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_4px_8px_rgba(0,0,0,0.2)] active:translate-y-0 active:shadow-[0_2px_4px_rgba(0,0,0,0.1)] text-[0.95rem] max-[480px]:text-[0.9rem]",
4213
4233
  style: {
4214
4234
  backgroundColor: isOfferInteracting ? accentColor : "transparent",
4215
4235
  borderColor: accentColor,
4216
4236
  color: isOfferInteracting ? "black" : accentColor,
4217
- width: "127.14px",
4218
- height: "43px",
4219
- minWidth: "127.14px",
4220
- boxShadow: isOfferInteracting ? `0 0 0 2px rgba(0,0,0,0.4), 0 0 0 4px ${accentColor}` : "none"
4237
+ minWidth: "140px",
4238
+ padding: "0.65rem 1.5rem",
4239
+ boxShadow: isOfferInteracting ? `0 0 0 2px rgba(0,0,0,0.4), 0 0 0 4px ${accentColor}` : "none",
4240
+ opacity: isMakeOfferButtonDisabled ? 0.5 : 1,
4241
+ cursor: isMakeOfferButtonDisabled ? "not-allowed" : "pointer"
4221
4242
  },
4222
- onMouseEnter: () => setIsOfferInteracting(true),
4223
- onMouseLeave: () => setIsOfferInteracting(false),
4224
- onMouseDown: () => setIsOfferInteracting(true),
4225
- onMouseUp: () => setIsOfferInteracting(false),
4226
- onFocus: () => setIsOfferInteracting(true),
4227
- onBlur: () => setIsOfferInteracting(false),
4228
- onTouchStart: () => setIsOfferInteracting(true),
4229
- onTouchEnd: () => setIsOfferInteracting(false),
4230
- children: "Make Offer"
4243
+ onMouseEnter: () => setOfferInteraction(true),
4244
+ onMouseLeave: () => setOfferInteraction(false),
4245
+ onMouseDown: () => setOfferInteraction(true),
4246
+ onMouseUp: () => setOfferInteraction(false),
4247
+ onFocus: () => setOfferInteraction(true),
4248
+ onBlur: () => setOfferInteraction(false),
4249
+ onTouchStart: () => setOfferInteraction(true),
4250
+ onTouchEnd: () => setOfferInteraction(false),
4251
+ disabled: isMakeOfferButtonDisabled,
4252
+ "aria-disabled": isMakeOfferButtonDisabled,
4253
+ children: makeOfferButtonLabel
4231
4254
  }
4232
- )
4255
+ ) : null
4233
4256
  ] })
4234
4257
  ] })
4235
4258
  ] }),
@@ -4535,10 +4558,22 @@ var Header = ({
4535
4558
  closeMenus();
4536
4559
  console.log("[Header] Add funding selected");
4537
4560
  if (LoginPopupComponent) {
4538
- setLoginPopupInitialView(void 0);
4561
+ setLoginPopupInitialView("funding");
4539
4562
  setShowLoginPopup(true);
4540
4563
  }
4541
4564
  };
4565
+ const handlePortfolioNavigate = (event) => {
4566
+ event?.preventDefault();
4567
+ closeMenus();
4568
+ console.log("[Header] Portfolio selected");
4569
+ if (_onOrdersNavigate) {
4570
+ _onOrdersNavigate();
4571
+ return;
4572
+ }
4573
+ if (onNavigate) {
4574
+ onNavigate("/portfolio");
4575
+ }
4576
+ };
4542
4577
  const userPrimaryLabel = currentUser?.displayName?.trim() || "User";
4543
4578
  const resolveAuthReturnUrl = () => {
4544
4579
  if (getAuthReturnUrl) {
@@ -4750,14 +4785,13 @@ var Header = ({
4750
4785
  ),
4751
4786
  isUserMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { className: "user-menu-dropdown", children: [
4752
4787
  /* @__PURE__ */ jsxRuntime.jsx(
4753
- "div",
4788
+ "button",
4754
4789
  {
4755
- style: {
4756
- padding: "12px 16px",
4757
- borderBottom: "1px solid rgba(255,255,255,0.08)",
4758
- textAlign: "left"
4790
+ type: "button",
4791
+ onClick: (event) => {
4792
+ handlePortfolioNavigate(event);
4759
4793
  },
4760
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontWeight: 600 }, children: userPrimaryLabel })
4794
+ children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { children: "Portfolio" })
4761
4795
  }
4762
4796
  ),
4763
4797
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -6724,27 +6758,55 @@ var PriceChange = styled23__default.default.span`
6724
6758
  gap: 0.35rem;
6725
6759
  color: ${(props) => props.$isPositive == null ? "var(--color-text-secondary, rgba(255, 255, 255, 0.6))" : props.$isPositive ? "var(--color-positive, #0ecb81)" : "var(--color-negative, #f6465d)"};
6726
6760
  `;
6727
- function PropertyOverview({ propertyName: _propertyName, location: _location, midPrice: _midPrice, onTradeClick: _onTradeClick }) {
6761
+ function PropertyOverview({
6762
+ propertyName: _propertyName,
6763
+ location: _location,
6764
+ midPrice: _midPrice,
6765
+ onTradeClick: _onTradeClick,
6766
+ overviewData,
6767
+ minimumParticipation,
6768
+ bedrooms,
6769
+ bathrooms,
6770
+ carSpaces,
6771
+ propertyTypeLabel
6772
+ }) {
6773
+ const description = overviewData?.description ?? "N/A";
6774
+ const tokensIssued = overviewData?.tokensIssued ?? null;
6775
+ const offeringValuation = overviewData?.offeringValuation ?? null;
6776
+ const weeklyRent = overviewData?.weeklyRent ?? null;
6777
+ const indicativeListing = overviewData?.indicativeListing ?? "N/A";
6778
+ const minParticipationValue = minimumParticipation ?? overviewData?.minimumParticipation ?? null;
6779
+ const landSize = overviewData?.landSizeSqm ?? null;
6780
+ const buildingSize = overviewData?.buildingSizeSqm ?? null;
6781
+ const propertyType = propertyTypeLabel ?? overviewData?.propertyType ?? "N/A";
6782
+ overviewData?.yearBuilt ?? null;
6783
+ const ownership = overviewData?.ownership ?? "N/A";
6784
+ const zoning = overviewData?.zoning ?? "N/A";
6785
+ const levels = overviewData?.levels ?? null;
6786
+ const daStatus = overviewData?.daStatus ?? "N/A";
6787
+ const unitPrice = tokensIssued && offeringValuation ? offeringValuation / tokensIssued : null;
6788
+ const formattedPropertyType = propertyType !== "N/A" ? propertyType.charAt(0).toUpperCase() + propertyType.slice(1).toLowerCase() : "N/A";
6728
6789
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6729
6790
  /* @__PURE__ */ jsxRuntime.jsxs(TwoColGrid, { children: [
6730
6791
  /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
6731
6792
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeading, { children: "About This Property" }),
6732
- /* @__PURE__ */ jsxRuntime.jsxs(BodyText, { children: [
6733
- "Musgrave is Mosman's oldest mansion. Built in 1880 and meticulously maintained for over 140 years. This is not just property - it's legacy.",
6734
- /* @__PURE__ */ jsxRuntime.jsx("br", {}),
6735
- /* @__PURE__ */ jsxRuntime.jsx("br", {}),
6736
- "Assets like this are irreplaceable. Pre-Federation sandstone architecture of this calibre simply cannot be recreated. With fewer than a handful of comparable estates remaining, scarcity drives enduring value."
6737
- ] })
6793
+ /* @__PURE__ */ jsxRuntime.jsx(BodyText, { children: description === "N/A" ? description : description.split("\n\n").map((paragraph, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6794
+ paragraph,
6795
+ i < description.split("\n\n").length - 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6796
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
6797
+ /* @__PURE__ */ jsxRuntime.jsx("br", {})
6798
+ ] })
6799
+ ] }, i)) })
6738
6800
  ] }),
6739
6801
  /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
6740
6802
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeading, { children: "The Offering" }),
6741
6803
  /* @__PURE__ */ jsxRuntime.jsx(OfferingGrid, { children: [
6742
- { label: "Units Issued", value: "50,000", gold: false },
6743
- { label: "Issue Price", value: "$250 / Unit", gold: true },
6744
- { label: "Implied Value", value: "$26,000,000", gold: false },
6745
- { label: "Minimum Participation", value: "$20,000", gold: false },
6746
- { label: "Est. Cash Flow", value: "$6000/wk", gold: true },
6747
- { label: "Indicative Listing Date", value: "MAY 2026", gold: false }
6804
+ { label: "Units Issued", value: tokensIssued?.toLocaleString() ?? "-", gold: false },
6805
+ { label: "Issue Price", value: unitPrice ? `$${unitPrice.toFixed(2)} / Unit` : "-", gold: true },
6806
+ { label: "Implied Value", value: offeringValuation ? `$${offeringValuation.toLocaleString()}` : "-", gold: false },
6807
+ { label: "Minimum Participation", value: minParticipationValue != null ? `$${minParticipationValue.toLocaleString()}` : "-", gold: false },
6808
+ { label: "Est. Cash Flow", value: weeklyRent ? `$${weeklyRent.toLocaleString()}/wk` : "-", gold: true },
6809
+ { label: "Indicative Listing Date", value: indicativeListing, gold: false }
6748
6810
  ].map(({ label, value, gold }) => /* @__PURE__ */ jsxRuntime.jsxs(OfferingItem, { children: [
6749
6811
  /* @__PURE__ */ jsxRuntime.jsx(OfferingLabel, { children: label }),
6750
6812
  /* @__PURE__ */ jsxRuntime.jsx(OfferingValue, { $gold: gold, children: value })
@@ -6757,10 +6819,10 @@ function PropertyOverview({ propertyName: _propertyName, location: _location, mi
6757
6819
  /* @__PURE__ */ jsxRuntime.jsx(AssetDetailsTitle, { children: "Asset Details" })
6758
6820
  ] }),
6759
6821
  /* @__PURE__ */ jsxRuntime.jsx(StatGrid, { children: [
6760
- { label: "Bedrooms", value: "6", icon: "\u{1F6CF}\uFE0F" },
6761
- { label: "Bathrooms", value: "6", icon: "\u{1F6BF}" },
6762
- { type: "dual", label1: "Land", value1: "1,862", label2: "Floor", value2: "700", unit: "sqm", highlight: true },
6763
- { label: "Car Spaces", value: "6", icon: "\u{1F697}" }
6822
+ { label: "Bedrooms", value: bedrooms != null ? bedrooms.toString() : "-", icon: "\u{1F6CF}\uFE0F" },
6823
+ { label: "Bathrooms", value: bathrooms != null ? bathrooms.toString() : "-", icon: "\u{1F6BF}" },
6824
+ { type: "dual", label1: "Land", value1: landSize?.toString() ?? "-", label2: "Floor", value2: buildingSize?.toString() ?? "-", unit: "sqm", highlight: true },
6825
+ { label: "Car Spaces", value: carSpaces != null ? carSpaces.toString() : "-", icon: "\u{1F697}" }
6764
6826
  ].map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatCard, { $highlight: !!stat.highlight, children: stat.type === "dual" ? /* @__PURE__ */ jsxRuntime.jsxs(DualStatInner, { children: [
6765
6827
  /* @__PURE__ */ jsxRuntime.jsxs(DualStatCol, { children: [
6766
6828
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { $gold: true, children: stat.label1 }),
@@ -6782,14 +6844,14 @@ function PropertyOverview({ propertyName: _propertyName, location: _location, mi
6782
6844
  /* @__PURE__ */ jsxRuntime.jsx(StatBigValue, { $gold: !!stat.highlight, children: stat.value })
6783
6845
  ] }) }, i)) }),
6784
6846
  /* @__PURE__ */ jsxRuntime.jsx(DetailTable, { children: /* @__PURE__ */ jsxRuntime.jsx(DetailTableGrid, { children: [
6785
- { label: "Last Sale", value: "$13M (2021)" },
6786
- { label: "Suburb Median", value: "$7M" },
6787
- { label: "Replication Cost of Architecture", value: "$7M" },
6788
- { label: "DA Status", value: "In Progress", status: "progress" },
6789
- { label: "Property Type", value: "Heritage Home" },
6790
- { label: "Ownership", value: "Freehold" },
6791
- { label: "Zoning", value: "R2 Low Density" },
6792
- { label: "Levels", value: "3" }
6847
+ { label: "Last Sale", value: "-" },
6848
+ { label: "Suburb Median", value: "-" },
6849
+ { label: "Replication Cost of Architecture", value: "-" },
6850
+ { label: "DA Status", value: daStatus, status: daStatus.toLowerCase() === "approved" ? "success" : "progress" },
6851
+ { label: "Property Type", value: formattedPropertyType },
6852
+ { label: "Ownership", value: ownership ?? "N/A" },
6853
+ { label: "Zoning", value: zoning ?? "N/A" },
6854
+ { label: "Levels", value: levels?.toString() ?? "N/A" }
6793
6855
  ].map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(DetailCell, { $borderBottom: i < 4, $borderRight: (i + 1) % 4 !== 0, children: [
6794
6856
  /* @__PURE__ */ jsxRuntime.jsx(DetailCellLabel, { children: item.label }),
6795
6857
  /* @__PURE__ */ jsxRuntime.jsxs(DetailCellValue, { $status: item.status, children: [
@@ -7675,7 +7737,7 @@ var DocIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height
7675
7737
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
7676
7738
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "10 9 9 9 8 9" })
7677
7739
  ] });
7678
- var docs = [
7740
+ var fallbackDocs = [
7679
7741
  { href: "/documents/musgrave-valuation-report.pdf", label: "Valuation Report" },
7680
7742
  { href: "/documents/musgrave-offering-material.pdf", label: "Offering Material" },
7681
7743
  { href: "/documents/musgrave-mortgage-agreement.pdf", label: "Mortgage Agreement" },
@@ -7684,13 +7746,26 @@ var docs = [
7684
7746
  { href: "/documents/musgrave-risk-disclosure.pdf", label: "Risk Disclosure Statement" },
7685
7747
  { href: "/documents/musgrave-building-inspection.pdf", label: "Building & Pest Inspection Report" }
7686
7748
  ];
7687
- function PropertyDocuments() {
7749
+ function PropertyDocuments({ documentsData }) {
7750
+ const backendDocuments = Array.isArray(documentsData?.documents) ? documentsData.documents : null;
7751
+ const hasBackendDocuments = !!backendDocuments?.length;
7752
+ const documents = hasBackendDocuments ? backendDocuments : fallbackDocs.map((doc) => ({
7753
+ title: doc.label,
7754
+ documentUrl: doc.href
7755
+ }));
7688
7756
  return /* @__PURE__ */ jsxRuntime.jsxs(Section2, { children: [
7689
7757
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeading2, { children: "Investment Documents" }),
7690
- /* @__PURE__ */ jsxRuntime.jsx(DocList, { children: docs.map(({ href, label }) => /* @__PURE__ */ jsxRuntime.jsx(DocItem, { children: /* @__PURE__ */ jsxRuntime.jsxs(DocLink, { href, target: "_blank", rel: "noopener noreferrer", children: [
7691
- /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
7692
- label
7693
- ] }) }, href)) })
7758
+ /* @__PURE__ */ jsxRuntime.jsx(DocList, { children: documents.map(({ documentUrl, title }) => {
7759
+ const isAvailable = Boolean(documentUrl);
7760
+ return /* @__PURE__ */ jsxRuntime.jsx(DocItem, { children: hasBackendDocuments && isAvailable ? /* @__PURE__ */ jsxRuntime.jsxs(DocLink, { href: documentUrl, target: "_blank", rel: "noopener noreferrer", children: [
7761
+ /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
7762
+ title
7763
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(DocItemDisabled, { children: [
7764
+ /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
7765
+ title,
7766
+ /* @__PURE__ */ jsxRuntime.jsx(ComingSoonBadge, { children: "Coming Soon" })
7767
+ ] }) }, `${title}-${documentUrl ?? "pending"}`);
7768
+ }) })
7694
7769
  ] });
7695
7770
  }
7696
7771
  var Section2 = styled23__default.default.section`
@@ -7734,11 +7809,29 @@ var DocLink = styled23__default.default.a`
7734
7809
  color: var(--color-accent);
7735
7810
  }
7736
7811
  `;
7812
+ var DocItemDisabled = styled23__default.default.div`
7813
+ display: flex;
7814
+ align-items: center;
7815
+ color: var(--color-text-secondary);
7816
+ cursor: not-allowed;
7817
+ opacity: 0.6;
7818
+ `;
7737
7819
  var DocIconWrapper = styled23__default.default.span`
7738
7820
  margin-right: 0.75rem;
7739
7821
  flex-shrink: 0;
7740
7822
  color: var(--color-text-secondary);
7741
7823
  `;
7824
+ var ComingSoonBadge = styled23__default.default.span`
7825
+ margin-left: auto;
7826
+ padding: 0.25rem 0.5rem;
7827
+ background: rgba(212, 175, 55, 0.1);
7828
+ color: #D4AF37;
7829
+ border-radius: 0.25rem;
7830
+ font-size: 0.7rem;
7831
+ font-weight: 500;
7832
+ text-transform: uppercase;
7833
+ letter-spacing: 0.05em;
7834
+ `;
7742
7835
  var formatIsoDate = (value) => {
7743
7836
  const parsed = new Date(value);
7744
7837
  if (Number.isNaN(parsed.getTime())) return value;
@@ -8025,7 +8118,7 @@ function AssetSelectorBar({ propertyName, tokenPrice, offeringValuation }) {
8025
8118
  /* @__PURE__ */ jsxRuntime.jsxs(SelectorMetrics, { children: [
8026
8119
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8027
8120
  /* @__PURE__ */ jsxRuntime.jsx(MetricLabel, { children: "Unit Price" }),
8028
- /* @__PURE__ */ jsxRuntime.jsxs(MetricValue, { accent: true, children: [
8121
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricValue, { $accent: true, children: [
8029
8122
  "$",
8030
8123
  tokenPrice.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
8031
8124
  ] })
@@ -8120,7 +8213,7 @@ var MetricLabel = styled23__default.default.span`
8120
8213
  var MetricValue = styled23__default.default.span`
8121
8214
  font-size: 1.1rem;
8122
8215
  font-weight: 700;
8123
- color: ${(p) => p.accent ? "#D4AF37" : "#fff"};
8216
+ color: ${(p) => p.$accent ? "#D4AF37" : "#fff"};
8124
8217
  `;
8125
8218
  var Separator = styled23__default.default.span`
8126
8219
  font-size: 1rem;
@@ -8239,7 +8332,7 @@ function OfferingProgressCard({
8239
8332
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u24D8" })
8240
8333
  ] }),
8241
8334
  /* @__PURE__ */ jsxRuntime.jsxs(LivePercent, { children: [
8242
- percentSold.toFixed(1),
8335
+ percentSold < 0.1 && percentSold > 0 ? percentSold.toFixed(3) : percentSold.toFixed(1),
8243
8336
  "%",
8244
8337
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2191" })
8245
8338
  ] })
@@ -8612,7 +8705,8 @@ function OrderPanel({
8612
8705
  orderButtonText,
8613
8706
  isOrderButtonDisabled,
8614
8707
  hasInsufficientFunds,
8615
- onPlaceAnotherOrder
8708
+ onPlaceAnotherOrder,
8709
+ onDeposit
8616
8710
  }) {
8617
8711
  const [payInputValue, setPayInputValue] = React5.useState("");
8618
8712
  const [receiveInputValue, setReceiveInputValue] = React5.useState("");
@@ -8621,11 +8715,14 @@ function OrderPanel({
8621
8715
  const handlePayBlur = () => {
8622
8716
  setIsPayInputFocused(false);
8623
8717
  const parsed = parseInt(payInputValue.replace(/[^0-9]/g, ""), 10) || 0;
8624
- if (parsed > availableBalance) {
8625
- setManualOrderAmount(parsed);
8718
+ if (parsed <= 0) {
8719
+ setManualOrderAmount(null);
8720
+ setSliderValue(0);
8721
+ } else if (parsed >= availableBalance) {
8722
+ setManualOrderAmount(null);
8626
8723
  setSliderValue(100);
8627
8724
  } else {
8628
- setManualOrderAmount(null);
8725
+ setManualOrderAmount(parsed);
8629
8726
  const ratio = availableBalance === 0 ? 0 : Math.round(Math.max(0, parsed / availableBalance * 100));
8630
8727
  setSliderValue(ratio);
8631
8728
  }
@@ -8634,11 +8731,14 @@ function OrderPanel({
8634
8731
  setIsReceiveInputFocused(false);
8635
8732
  const parsed = parseFloat(receiveInputValue) || 0;
8636
8733
  const newOrderTotal = Math.round(parsed * tokenPrice);
8637
- if (newOrderTotal > availableBalance) {
8638
- setManualOrderAmount(newOrderTotal);
8734
+ if (newOrderTotal <= 0) {
8735
+ setManualOrderAmount(null);
8736
+ setSliderValue(0);
8737
+ } else if (newOrderTotal >= availableBalance) {
8738
+ setManualOrderAmount(null);
8639
8739
  setSliderValue(100);
8640
8740
  } else {
8641
- setManualOrderAmount(null);
8741
+ setManualOrderAmount(newOrderTotal);
8642
8742
  const ratio = availableBalance === 0 ? 0 : Math.round(Math.max(0, newOrderTotal / availableBalance * 100));
8643
8743
  setSliderValue(ratio);
8644
8744
  }
@@ -8708,7 +8808,7 @@ function OrderPanel({
8708
8808
  }
8709
8809
  }
8710
8810
  ),
8711
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "AUD" })
8811
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "USDC" })
8712
8812
  ] }),
8713
8813
  /* @__PURE__ */ jsxRuntime.jsx(QuickSelectRow, { children: [25, 50, 75, 100].map((pct) => /* @__PURE__ */ jsxRuntime.jsxs(
8714
8814
  "button",
@@ -8735,7 +8835,7 @@ function OrderPanel({
8735
8835
  availableBalance.toLocaleString()
8736
8836
  ] })
8737
8837
  ] }),
8738
- /* @__PURE__ */ jsxRuntime.jsx(DepositButton, { type: "button", children: "+ Deposit" })
8838
+ /* @__PURE__ */ jsxRuntime.jsx(DepositButton, { type: "button", onClick: onDeposit, children: "+ Deposit" })
8739
8839
  ] }),
8740
8840
  /* @__PURE__ */ jsxRuntime.jsx(Divider2, { children: "\u2193" }),
8741
8841
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
@@ -8802,7 +8902,7 @@ function OrderPanel({
8802
8902
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8803
8903
  "$",
8804
8904
  orderTotal.toLocaleString(),
8805
- " AUD"
8905
+ " USDC"
8806
8906
  ] })
8807
8907
  ] })
8808
8908
  ] })
@@ -8824,7 +8924,7 @@ function OrderPanel({
8824
8924
  "$",
8825
8925
  availableBalance.toLocaleString()
8826
8926
  ] }),
8827
- /* @__PURE__ */ jsxRuntime.jsx(BalanceAction, { children: "+ Deposit" })
8927
+ /* @__PURE__ */ jsxRuntime.jsx(BalanceAction, { onClick: onDeposit, style: { cursor: onDeposit ? "pointer" : "default" }, children: "+ Deposit" })
8828
8928
  ] }),
8829
8929
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceCard, { children: [
8830
8930
  /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: "Musgrave Owned" }),
@@ -9456,7 +9556,23 @@ var IframeShield = styled23__default.default.div`
9456
9556
  z-index: 1;
9457
9557
  cursor: pointer;
9458
9558
  `;
9459
- function NewsOrdersSection({ newsItems, userSubscription, tokenPrice }) {
9559
+ var SUBSCRIPTIONS_PAGE_SIZE = 6;
9560
+ function NewsOrdersSection({ newsItems, userSubscriptions, tokenPrice }) {
9561
+ const [page, setPage] = React5.useState(0);
9562
+ const totalPages = Math.max(1, Math.ceil(userSubscriptions.length / SUBSCRIPTIONS_PAGE_SIZE));
9563
+ React5.useEffect(() => {
9564
+ if (page > totalPages - 1) {
9565
+ setPage(totalPages - 1);
9566
+ }
9567
+ }, [page, totalPages]);
9568
+ React5.useEffect(() => {
9569
+ setPage(0);
9570
+ }, [userSubscriptions]);
9571
+ const paginatedSubscriptions = React5.useMemo(() => {
9572
+ const start = page * SUBSCRIPTIONS_PAGE_SIZE;
9573
+ return userSubscriptions.slice(start, start + SUBSCRIPTIONS_PAGE_SIZE);
9574
+ }, [page, userSubscriptions]);
9575
+ const hasPagination = userSubscriptions.length > SUBSCRIPTIONS_PAGE_SIZE;
9460
9576
  return /* @__PURE__ */ jsxRuntime.jsxs(Row2, { children: [
9461
9577
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsPanel, { children: [
9462
9578
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsHeader, { children: [
@@ -9483,34 +9599,57 @@ function NewsOrdersSection({ newsItems, userSubscription, tokenPrice }) {
9483
9599
  ] }),
9484
9600
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsPanel, { children: [
9485
9601
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsHeader, { children: [
9486
- /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Your Orders" }),
9487
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Offering Subscriptions" })
9602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9603
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Your Orders" }),
9604
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Offering Subscriptions" })
9605
+ ] }),
9606
+ hasPagination ? /* @__PURE__ */ jsxRuntime.jsxs(Pagination, { children: [
9607
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => setPage((prev) => Math.max(prev - 1, 0)), disabled: page === 0, children: "Prev" }),
9608
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9609
+ "Page ",
9610
+ page + 1,
9611
+ "/",
9612
+ totalPages
9613
+ ] }),
9614
+ /* @__PURE__ */ jsxRuntime.jsx(
9615
+ "button",
9616
+ {
9617
+ type: "button",
9618
+ onClick: () => setPage((prev) => Math.min(prev + 1, totalPages - 1)),
9619
+ disabled: page >= totalPages - 1,
9620
+ children: "Next"
9621
+ }
9622
+ )
9623
+ ] }) : null
9488
9624
  ] }),
9489
9625
  /* @__PURE__ */ jsxRuntime.jsxs(OrdersTable, { children: [
9490
9626
  /* @__PURE__ */ jsxRuntime.jsx(OrdersHead, { children: ["Date", "Units", "Price", "Total", "Status"].map((h) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: h }, h)) }),
9491
- userSubscription ? /* @__PURE__ */ jsxRuntime.jsxs(OrdersRow, { children: [
9492
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9493
- new Date(userSubscription.timestamp).toLocaleDateString("en-AU", {
9494
- day: "2-digit",
9495
- month: "short",
9496
- year: "numeric"
9497
- }),
9498
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: new Date(userSubscription.timestamp).toLocaleTimeString("en-AU", {
9499
- hour: "2-digit",
9500
- minute: "2-digit"
9501
- }) })
9502
- ] }),
9503
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "units", children: userSubscription.tokens.toFixed(2) }),
9504
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9505
- "$",
9506
- tokenPrice.toFixed(2)
9507
- ] }),
9508
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "total", children: [
9509
- "$",
9510
- userSubscription.value.toLocaleString()
9511
- ] }),
9512
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "status", children: "Confirmed" })
9513
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(OrdersEmpty, { children: [
9627
+ paginatedSubscriptions.length ? paginatedSubscriptions.map((subscription) => {
9628
+ const subscriptionDate = new Date(subscription.timestamp);
9629
+ return /* @__PURE__ */ jsxRuntime.jsxs(OrdersRow, { children: [
9630
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9631
+ subscriptionDate.toLocaleDateString("en-AU", {
9632
+ day: "2-digit",
9633
+ month: "short",
9634
+ year: "numeric"
9635
+ }),
9636
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: subscriptionDate.toLocaleTimeString("en-AU", {
9637
+ hour: "2-digit",
9638
+ minute: "2-digit"
9639
+ }) })
9640
+ ] }),
9641
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "units", children: subscription.tokens.toFixed(2) }),
9642
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9643
+ "$",
9644
+ tokenPrice.toFixed(2)
9645
+ ] }),
9646
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "total", children: [
9647
+ "$",
9648
+ subscription.value.toLocaleString()
9649
+ ] }),
9650
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "status", children: subscription.status ?? "Confirmed" })
9651
+ ] }, `${subscription.timestamp}-${subscription.tokens}`);
9652
+ }) : /* @__PURE__ */ jsxRuntime.jsxs(OrdersEmpty, { children: [
9514
9653
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: "\u{1F4CB}" }),
9515
9654
  /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No orders yet" }),
9516
9655
  /* @__PURE__ */ jsxRuntime.jsx("small", { children: "Subscribe to the IPO above to place your first order" })
@@ -9637,6 +9776,28 @@ var OrdersTable = styled23__default.default.div`
9637
9776
  flex: 1;
9638
9777
  overflow: auto;
9639
9778
  `;
9779
+ var Pagination = styled23__default.default.div`
9780
+ display: flex;
9781
+ align-items: center;
9782
+ gap: 0.75rem;
9783
+ font-size: 0.75rem;
9784
+ color: var(--color-text-secondary);
9785
+
9786
+ button {
9787
+ border: 1px solid rgba(255,255,255,0.2);
9788
+ background: rgba(255,255,255,0.05);
9789
+ color: #fff;
9790
+ border-radius: 9999px;
9791
+ padding: 0.25rem 0.9rem;
9792
+ font-size: 0.7rem;
9793
+ cursor: pointer;
9794
+ transition: opacity 0.2s;
9795
+ &:disabled {
9796
+ opacity: 0.4;
9797
+ cursor: not-allowed;
9798
+ }
9799
+ }
9800
+ `;
9640
9801
  var OrdersHead = styled23__default.default.div`
9641
9802
  display: grid;
9642
9803
  grid-template-columns: 1fr 1fr 1fr 1fr 1.2fr;
@@ -9910,11 +10071,18 @@ function PropertyBuy({
9910
10071
  propertyLocation: propertyLocationLabel = "Mosman, Sydney",
9911
10072
  isAuthenticated,
9912
10073
  onSignIn,
9913
- saleData
10074
+ saleData,
10075
+ walletUsdcBalance,
10076
+ walletPropertyTokenBalance,
10077
+ onPurchase,
10078
+ purchaseStatus = "idle",
10079
+ purchaseError,
10080
+ onDeposit,
10081
+ initialUserSubscriptions = []
9914
10082
  }) {
9915
10083
  const [sliderValue, setSliderValue] = React5.useState(0);
9916
- const [availableBalance, setAvailableBalance] = React5.useState(125e3);
9917
- const [userSubscription, setUserSubscription] = React5.useState(null);
10084
+ const [availableBalance, setAvailableBalance] = React5.useState(walletUsdcBalance ?? 125e3);
10085
+ const [optimisticUserSubscriptions, setOptimisticUserSubscriptions] = React5.useState([]);
9918
10086
  const [manualOrderAmount, setManualOrderAmount] = React5.useState(null);
9919
10087
  const [ownedTokens, setOwnedTokens] = React5.useState(0);
9920
10088
  const [displayedOwnedTokens, setDisplayedOwnedTokens] = React5.useState(0);
@@ -9932,6 +10100,12 @@ function PropertyBuy({
9932
10100
  isNew: false
9933
10101
  }))
9934
10102
  );
10103
+ const resolvedUserSubscriptions = initialUserSubscriptions && initialUserSubscriptions.length > 0 ? initialUserSubscriptions : optimisticUserSubscriptions;
10104
+ React5.useEffect(() => {
10105
+ if (initialUserSubscriptions?.length) {
10106
+ setOptimisticUserSubscriptions([]);
10107
+ }
10108
+ }, [initialUserSubscriptions]);
9935
10109
  const tokenPrice = saleData?.tokenPrice ?? 250;
9936
10110
  const feeRate = (saleData?.feePercent ?? 0.5) / 100;
9937
10111
  const totalSold = saleData?.totalSold ?? 0;
@@ -9949,6 +10123,17 @@ function PropertyBuy({
9949
10123
  const orderTotal = totalSpend;
9950
10124
  const estExposure = (tokenQuantity / supplyToSell * 100).toFixed(4);
9951
10125
  const hasInsufficientFunds = orderTotal > availableBalance;
10126
+ React5.useEffect(() => {
10127
+ if (walletUsdcBalance != null) {
10128
+ setAvailableBalance(walletUsdcBalance);
10129
+ }
10130
+ }, [walletUsdcBalance]);
10131
+ React5.useEffect(() => {
10132
+ if (walletPropertyTokenBalance != null) {
10133
+ setOwnedTokens(walletPropertyTokenBalance);
10134
+ setDisplayedOwnedTokens(walletPropertyTokenBalance);
10135
+ }
10136
+ }, [walletPropertyTokenBalance]);
9952
10137
  const handleOrderButtonClick = () => {
9953
10138
  if (!isAuthenticated) {
9954
10139
  onSignIn();
@@ -9959,8 +10144,12 @@ function PropertyBuy({
9959
10144
  }
9960
10145
  setShowOrderConfirmModal(true);
9961
10146
  };
10147
+ const isPurchaseInFlight = purchaseStatus === "checking-allowance" || purchaseStatus === "approving" || purchaseStatus === "purchasing";
9962
10148
  const getOrderButtonText = () => {
9963
10149
  if (!isAuthenticated) return "Sign In to Invest";
10150
+ if (purchaseStatus === "checking-allowance") return "Checking allowance\u2026";
10151
+ if (purchaseStatus === "approving") return "Approving USDC\u2026";
10152
+ if (purchaseStatus === "purchasing") return "Confirming purchase\u2026";
9964
10153
  if (scStatus === 0) return "Sale Not Open Yet";
9965
10154
  if (scStatus === 2) return "Sale Completed";
9966
10155
  if (scStatus === 3) return "Sale Paused";
@@ -9969,30 +10158,44 @@ function PropertyBuy({
9969
10158
  };
9970
10159
  const isOrderButtonDisabled = () => {
9971
10160
  if (!isAuthenticated) return false;
10161
+ if (isPurchaseInFlight) return true;
9972
10162
  if (scStatus !== 1) return true;
9973
10163
  if (tokenQuantity === 0) return true;
9974
10164
  return false;
9975
10165
  };
9976
- const confirmOrder = () => {
10166
+ const confirmOrder = async () => {
9977
10167
  setShowOrderConfirmModal(false);
9978
- setAvailableBalance((prev) => prev - orderTotal);
9979
- const newTokens = ownedTokens + tokenQuantity;
10168
+ const tokenAmountInt = Math.floor(tokenQuantity);
10169
+ if (tokenAmountInt <= 0) return;
10170
+ if (onPurchase) {
10171
+ try {
10172
+ await onPurchase(tokenAmountInt);
10173
+ } catch {
10174
+ return;
10175
+ }
10176
+ }
10177
+ if (walletUsdcBalance == null) {
10178
+ setAvailableBalance((prev) => prev - orderTotal);
10179
+ }
10180
+ const newTokens = ownedTokens + tokenAmountInt;
9980
10181
  setOwnedTokens(newTokens);
9981
10182
  setDisplayedOwnedTokens(newTokens);
9982
10183
  setOwnedTokensJustUpdated(true);
9983
- setLastOrderQuantity(tokenQuantity);
10184
+ setLastOrderQuantity(tokenAmountInt);
9984
10185
  setTimeout(() => setOwnedTokensJustUpdated(false), 2e3);
9985
- setUserSubscription({
10186
+ const optimisticEntry = {
9986
10187
  propertyName,
9987
10188
  tokenSymbol: "MUS",
9988
- tokens: tokenQuantity,
10189
+ tokens: tokenAmountInt,
9989
10190
  value: orderTotal,
9990
10191
  avgPrice: tokenPrice,
9991
10192
  percentOfProperty: estExposure,
9992
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
9993
- });
10193
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10194
+ status: "pending"
10195
+ };
10196
+ setOptimisticUserSubscriptions((prev) => [optimisticEntry, ...prev]);
9994
10197
  setLastOrderDetails({
9995
- tokens: tokenQuantity,
10198
+ tokens: tokenAmountInt,
9996
10199
  total: orderTotal,
9997
10200
  price: tokenPrice,
9998
10201
  orderNumber: Math.floor(1e7 + Math.random() * 9e7)
@@ -10052,36 +10255,40 @@ function PropertyBuy({
10052
10255
  }
10053
10256
  ),
10054
10257
  /* @__PURE__ */ jsxRuntime.jsx(VideoActivitySection, { ipoStarted }),
10055
- /* @__PURE__ */ jsxRuntime.jsx(
10056
- OrderPanel,
10057
- {
10058
- statusLabel,
10059
- statusColor,
10060
- ipoStarted,
10061
- isAuthenticated,
10062
- tokenPrice,
10063
- feeRate,
10064
- supplyToSell,
10065
- availableBalance,
10066
- displayedOwnedTokens,
10067
- ownedTokensJustUpdated,
10068
- lastOrderQuantity,
10069
- orderPlacedSuccess,
10070
- lastOrderDetails,
10071
- tokenQuantity,
10072
- feeInTokens,
10073
- orderTotal,
10074
- sliderValue,
10075
- manualOrderAmount,
10076
- setSliderValue,
10077
- setManualOrderAmount,
10078
- onOrderButtonClick: handleOrderButtonClick,
10079
- orderButtonText: getOrderButtonText(),
10080
- isOrderButtonDisabled: isOrderButtonDisabled(),
10081
- hasInsufficientFunds,
10082
- onPlaceAnotherOrder: () => setOrderPlacedSuccess(false)
10083
- }
10084
- )
10258
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
10259
+ /* @__PURE__ */ jsxRuntime.jsx(
10260
+ OrderPanel,
10261
+ {
10262
+ statusLabel,
10263
+ statusColor,
10264
+ ipoStarted,
10265
+ isAuthenticated,
10266
+ tokenPrice,
10267
+ feeRate,
10268
+ supplyToSell,
10269
+ availableBalance,
10270
+ displayedOwnedTokens,
10271
+ ownedTokensJustUpdated,
10272
+ lastOrderQuantity,
10273
+ orderPlacedSuccess,
10274
+ lastOrderDetails,
10275
+ tokenQuantity,
10276
+ feeInTokens,
10277
+ orderTotal,
10278
+ sliderValue,
10279
+ manualOrderAmount,
10280
+ setSliderValue,
10281
+ setManualOrderAmount,
10282
+ onOrderButtonClick: handleOrderButtonClick,
10283
+ orderButtonText: getOrderButtonText(),
10284
+ isOrderButtonDisabled: isOrderButtonDisabled(),
10285
+ hasInsufficientFunds,
10286
+ onPlaceAnotherOrder: () => setOrderPlacedSuccess(false),
10287
+ onDeposit
10288
+ }
10289
+ ),
10290
+ purchaseError && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { marginTop: "0.75rem", padding: "0.75rem 1rem", borderRadius: "8px", background: "rgba(246,70,93,0.1)", border: "1px solid rgba(246,70,93,0.3)", color: "#f6465d", fontSize: "0.8rem", fontWeight: 500 }, children: purchaseError })
10291
+ ] })
10085
10292
  ] }),
10086
10293
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
10087
10294
  /* @__PURE__ */ jsxRuntime.jsx(GalleryMapSection, { propertyLocation: propertyLocationLabel }),
@@ -10089,7 +10296,7 @@ function PropertyBuy({
10089
10296
  NewsOrdersSection,
10090
10297
  {
10091
10298
  newsItems,
10092
- userSubscription,
10299
+ userSubscriptions: resolvedUserSubscriptions,
10093
10300
  tokenPrice
10094
10301
  }
10095
10302
  )
@@ -12444,6 +12651,191 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
12444
12651
  }
12445
12652
  );
12446
12653
  }
12654
+ var slideIn = styled23.keyframes`
12655
+ from { transform: translateX(110%); opacity: 0; }
12656
+ to { transform: translateX(0); opacity: 1; }
12657
+ `;
12658
+ var slideOut = styled23.keyframes`
12659
+ from { transform: translateX(0); opacity: 1; }
12660
+ to { transform: translateX(110%); opacity: 0; }
12661
+ `;
12662
+ var progressShrink = styled23.keyframes`
12663
+ from { width: 100%; }
12664
+ to { width: 0%; }
12665
+ `;
12666
+ var VARIANT_COLORS = {
12667
+ success: { accent: "#0ecb81", icon: "\u2713" },
12668
+ error: { accent: "#f6465d", icon: "\u2715" },
12669
+ info: { accent: "#E6C656", icon: "\u2139" },
12670
+ pending: { accent: "#7EB3E6", icon: "\u25CC" }
12671
+ };
12672
+ var Wrapper = styled23__default.default.div`
12673
+ position: relative;
12674
+ display: flex;
12675
+ flex-direction: column;
12676
+ gap: 0;
12677
+ width: 340px;
12678
+ background: #0d0f1a;
12679
+ border: 1px solid rgba(255, 255, 255, 0.08);
12680
+ border-radius: 10px;
12681
+ overflow: hidden;
12682
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.04);
12683
+ animation: ${({ $exiting }) => $exiting ? styled23.css`${slideOut} 0.28s cubic-bezier(0.4,0,1,1) forwards` : styled23.css`${slideIn} 0.32s cubic-bezier(0,0,0.2,1) forwards`};
12684
+ pointer-events: all;
12685
+ `;
12686
+ var Body = styled23__default.default.div`
12687
+ display: flex;
12688
+ align-items: flex-start;
12689
+ gap: 12px;
12690
+ padding: 14px 16px 12px;
12691
+ `;
12692
+ var IconDot = styled23__default.default.div`
12693
+ flex-shrink: 0;
12694
+ width: 28px;
12695
+ height: 28px;
12696
+ border-radius: 50%;
12697
+ background: ${({ $color }) => $color}1a;
12698
+ border: 1px solid ${({ $color }) => $color}55;
12699
+ display: flex;
12700
+ align-items: center;
12701
+ justify-content: center;
12702
+ font-size: 0.75rem;
12703
+ font-weight: 700;
12704
+ color: ${({ $color }) => $color};
12705
+ margin-top: 1px;
12706
+ `;
12707
+ var Content = styled23__default.default.div`
12708
+ flex: 1;
12709
+ min-width: 0;
12710
+ `;
12711
+ var Title2 = styled23__default.default.p`
12712
+ margin: 0 0 2px;
12713
+ font-size: 0.8rem;
12714
+ font-weight: 600;
12715
+ color: #fff;
12716
+ letter-spacing: 0.01em;
12717
+ `;
12718
+ var Amount = styled23__default.default.p`
12719
+ margin: 0 0 6px;
12720
+ font-size: 1.05rem;
12721
+ font-weight: 700;
12722
+ color: #E6C656;
12723
+ letter-spacing: -0.01em;
12724
+ `;
12725
+ var TxRow = styled23__default.default.a`
12726
+ display: inline-flex;
12727
+ align-items: center;
12728
+ gap: 5px;
12729
+ font-family: 'IBM Plex Mono', 'Space Mono', monospace;
12730
+ font-size: 0.68rem;
12731
+ color: rgba(255, 255, 255, 0.4);
12732
+ text-decoration: none;
12733
+ transition: color 0.15s;
12734
+ &:hover {
12735
+ color: #7EB3E6;
12736
+ }
12737
+ `;
12738
+ var TxArrow = styled23__default.default.span`
12739
+ font-size: 0.6rem;
12740
+ opacity: 0.6;
12741
+ `;
12742
+ var CloseBtn = styled23__default.default.button`
12743
+ flex-shrink: 0;
12744
+ background: none;
12745
+ border: none;
12746
+ padding: 2px 4px;
12747
+ cursor: pointer;
12748
+ color: rgba(255, 255, 255, 0.25);
12749
+ font-size: 0.9rem;
12750
+ line-height: 1;
12751
+ transition: color 0.15s;
12752
+ &:hover { color: rgba(255, 255, 255, 0.7); }
12753
+ `;
12754
+ var ProgressBar2 = styled23__default.default.div`
12755
+ height: 2px;
12756
+ background: rgba(255, 255, 255, 0.06);
12757
+ position: relative;
12758
+ &::after {
12759
+ content: '';
12760
+ position: absolute;
12761
+ left: 0;
12762
+ top: 0;
12763
+ height: 100%;
12764
+ background: ${({ $color }) => $color};
12765
+ animation: ${styled23.css`${progressShrink} ${({ $duration }) => $duration}ms linear forwards`};
12766
+ }
12767
+ `;
12768
+ var Container2 = styled23__default.default.div`
12769
+ position: fixed;
12770
+ bottom: 24px;
12771
+ right: 24px;
12772
+ z-index: 9999;
12773
+ display: flex;
12774
+ flex-direction: column-reverse;
12775
+ gap: 10px;
12776
+ pointer-events: none;
12777
+ `;
12778
+ var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
12779
+ function truncateHash(hash) {
12780
+ return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
12781
+ }
12782
+ function ToastItem({ toast, onDismiss }) {
12783
+ const [exiting, setExiting] = React5.useState(false);
12784
+ const timerRef = React5.useRef(null);
12785
+ const dismiss = React5.useCallback(() => {
12786
+ setExiting(true);
12787
+ setTimeout(() => onDismiss(toast.id), 280);
12788
+ }, [onDismiss, toast.id]);
12789
+ React5.useEffect(() => {
12790
+ const duration2 = toast.duration ?? 6e3;
12791
+ if (duration2 > 0) {
12792
+ timerRef.current = setTimeout(dismiss, duration2);
12793
+ }
12794
+ return () => {
12795
+ if (timerRef.current) clearTimeout(timerRef.current);
12796
+ };
12797
+ }, [dismiss, toast.duration]);
12798
+ const { accent, icon } = VARIANT_COLORS[toast.variant];
12799
+ const duration = toast.duration ?? 6e3;
12800
+ const explorerBase = toast.explorerUrl ?? DEFAULT_EXPLORER;
12801
+ const txUrl = toast.txHash ? `${explorerBase}${toast.txHash}` : void 0;
12802
+ return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { $exiting: exiting, children: [
12803
+ /* @__PURE__ */ jsxRuntime.jsxs(Body, { children: [
12804
+ /* @__PURE__ */ jsxRuntime.jsx(IconDot, { $color: accent, children: icon }),
12805
+ /* @__PURE__ */ jsxRuntime.jsxs(Content, { children: [
12806
+ /* @__PURE__ */ jsxRuntime.jsx(Title2, { children: toast.title }),
12807
+ toast.amount && /* @__PURE__ */ jsxRuntime.jsx(Amount, { children: toast.amount }),
12808
+ toast.txHash && txUrl && /* @__PURE__ */ jsxRuntime.jsxs(TxRow, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: [
12809
+ truncateHash(toast.txHash),
12810
+ /* @__PURE__ */ jsxRuntime.jsx(TxArrow, { children: "\u2197" })
12811
+ ] })
12812
+ ] }),
12813
+ /* @__PURE__ */ jsxRuntime.jsx(CloseBtn, { type: "button", onClick: dismiss, "aria-label": "Dismiss", children: "\u2715" })
12814
+ ] }),
12815
+ duration > 0 && /* @__PURE__ */ jsxRuntime.jsx(ProgressBar2, { $color: accent, $duration: duration })
12816
+ ] });
12817
+ }
12818
+ var ToastContext = React5.createContext(null);
12819
+ function ToastProvider({ children }) {
12820
+ const [toasts, setToasts] = React5.useState([]);
12821
+ const addToast = React5.useCallback((data) => {
12822
+ const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
12823
+ setToasts((prev) => [...prev, { ...data, id }]);
12824
+ return id;
12825
+ }, []);
12826
+ const dismiss = React5.useCallback((id) => {
12827
+ setToasts((prev) => prev.filter((t) => t.id !== id));
12828
+ }, []);
12829
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
12830
+ children,
12831
+ /* @__PURE__ */ jsxRuntime.jsx(Container2, { children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
12832
+ ] });
12833
+ }
12834
+ function useToast() {
12835
+ const ctx = React5.useContext(ToastContext);
12836
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
12837
+ return ctx;
12838
+ }
12447
12839
 
12448
12840
  exports.Badge = Badge;
12449
12841
  exports.Button = Button;
@@ -12478,10 +12870,12 @@ exports.PropertyPhotoGallery = PropertyPhotoGallery;
12478
12870
  exports.PropertySubheader = PropertySubheader;
12479
12871
  exports.PropertyTour = PropertyTour;
12480
12872
  exports.PropertyValuation = PropertyValuation;
12873
+ exports.ToastProvider = ToastProvider;
12481
12874
  exports.TradeConfirmationModal = TradeConfirmationModal;
12482
12875
  exports.TradingSlider = TradingSlider;
12483
12876
  exports.YourOrders = YourOrders;
12484
12877
  exports.badgeVariants = badgeVariants;
12485
12878
  exports.buttonVariants = buttonVariants;
12879
+ exports.useToast = useToast;
12486
12880
  //# sourceMappingURL=index.js.map
12487
12881
  //# sourceMappingURL=index.js.map