@loafmarkets/ui 0.1.14 → 0.1.17

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
  ] }),
@@ -4418,11 +4441,14 @@ var DEFAULT_TRADE_URL = "https://loafx-frontend-web.vercel.app/";
4418
4441
  var DEFAULT_TRADE_PATH = "/trade";
4419
4442
  var DEFAULT_HOME_PATH = "/";
4420
4443
  var DEFAULT_ABOUT_PATH = "/about";
4444
+ var DEFAULT_LEARN_PATH = "/learn";
4421
4445
  var DEFAULT_OFFERINGS_PATH = "/ipo/musgrave";
4422
4446
  var DEFAULT_PROPERTY_MAP_PATH = "/map";
4447
+ var DEFAULT_PORTFOLIO_PATH = "/portfolio";
4423
4448
  var DEFAULT_LOAF_LIQUIDITY_PATH = "/loaf-liquidity";
4424
4449
  var DEFAULT_AUTH_LOGIN_URL = "http://localhost:5174/";
4425
4450
  var DEFAULT_AUTH_RETURN_PARAM = "returnTo";
4451
+ var LOGIN_POPUP_EVENT = "loaf:open-login-popup";
4426
4452
  var Header = ({
4427
4453
  currentUser,
4428
4454
  isAuthenticated = false,
@@ -4436,8 +4462,10 @@ var Header = ({
4436
4462
  tradePath = DEFAULT_TRADE_PATH,
4437
4463
  homePath = DEFAULT_HOME_PATH,
4438
4464
  aboutPath = DEFAULT_ABOUT_PATH,
4465
+ learnPath = DEFAULT_LEARN_PATH,
4439
4466
  offeringsPath = DEFAULT_OFFERINGS_PATH,
4440
4467
  propertyMapPath = DEFAULT_PROPERTY_MAP_PATH,
4468
+ portfolioPath = DEFAULT_PORTFOLIO_PATH,
4441
4469
  loafLiquidityPath = DEFAULT_LOAF_LIQUIDITY_PATH,
4442
4470
  authLoginUrl = DEFAULT_AUTH_LOGIN_URL,
4443
4471
  authReturnParam = DEFAULT_AUTH_RETURN_PARAM,
@@ -4455,13 +4483,23 @@ var Header = ({
4455
4483
  const [isMoreMenuOpen, setIsMoreMenuOpen] = React5.useState(false);
4456
4484
  const [showLoginPopup, setShowLoginPopup] = React5.useState(false);
4457
4485
  const [loginPopupInitialView, setLoginPopupInitialView] = React5.useState(void 0);
4486
+ React5.useEffect(() => {
4487
+ console.log("[LoginTrace][Header] mounted");
4488
+ return () => console.log("[LoginTrace][Header] unmounted");
4489
+ }, []);
4490
+ React5.useEffect(() => {
4491
+ console.log("[LoginTrace][Header] showLoginPopup changed", { showLoginPopup, loginPopupInitialView });
4492
+ }, [showLoginPopup, loginPopupInitialView]);
4493
+ React5.useEffect(() => {
4494
+ console.log("[LoginTrace][Header] loginPopupComponent updated", { hasComponent: Boolean(LoginPopupComponent) });
4495
+ }, [LoginPopupComponent]);
4458
4496
  React5.useEffect(() => {
4459
4497
  const handleClickOutside = (event) => {
4460
4498
  const target = event.target;
4461
4499
  if (!target) return;
4462
4500
  const clickedInsideUserMenu = target.closest(".user-menu") || target.closest(".user-menu-dropdown");
4463
4501
  if (isUserMenuOpen && !clickedInsideUserMenu) {
4464
- console.log("[Header] Closing user menu due to outside click");
4502
+ console.log("[LoginTrace][Header] Closing user menu due to outside click");
4465
4503
  setIsUserMenuOpen(false);
4466
4504
  }
4467
4505
  if (isMobileMenuOpen && !target.closest(".mobile-menu") && !target.closest(".mobile-menu-button")) {
@@ -4476,6 +4514,19 @@ var Header = ({
4476
4514
  document.removeEventListener("mousedown", handleClickOutside);
4477
4515
  };
4478
4516
  }, [isUserMenuOpen, isMobileMenuOpen, isMoreMenuOpen]);
4517
+ React5.useEffect(() => {
4518
+ if (typeof window === "undefined") return;
4519
+ const handleExternalLoginPopup = (event) => {
4520
+ const customEvent = event;
4521
+ setLoginPopupInitialView(customEvent.detail?.initialView);
4522
+ console.log("[LoginTrace][Header] Received LOGIN_POPUP_EVENT", customEvent.detail);
4523
+ setShowLoginPopup(true);
4524
+ };
4525
+ window.addEventListener(LOGIN_POPUP_EVENT, handleExternalLoginPopup);
4526
+ return () => {
4527
+ window.removeEventListener(LOGIN_POPUP_EVENT, handleExternalLoginPopup);
4528
+ };
4529
+ }, []);
4479
4530
  const closeMenus = () => {
4480
4531
  setIsMobileMenuOpen(false);
4481
4532
  setIsUserMenuOpen(false);
@@ -4483,7 +4534,7 @@ var Header = ({
4483
4534
  };
4484
4535
  const handleUserMenuToggle = () => {
4485
4536
  const nextState = !isUserMenuOpen;
4486
- console.log("[Header] User dropdown toggle clicked", { nextState });
4537
+ console.log("[LoginTrace][Header] User dropdown toggle clicked", { nextState });
4487
4538
  setIsUserMenuOpen(nextState);
4488
4539
  };
4489
4540
  const performNavigation = (path) => {
@@ -4527,18 +4578,30 @@ var Header = ({
4527
4578
  const handleLogoutClick = async (event) => {
4528
4579
  event?.preventDefault();
4529
4580
  closeMenus();
4530
- console.log("[Header] Logout option selected, invoking onLogout handler");
4581
+ console.log("[LoginTrace][Header] Logout option selected, invoking onLogout handler");
4531
4582
  await onLogout?.();
4532
4583
  };
4533
4584
  const handleAddFundingClick = (event) => {
4534
4585
  event?.preventDefault();
4535
4586
  closeMenus();
4536
- console.log("[Header] Add funding selected");
4587
+ console.log("[LoginTrace][Header] Add funding selected");
4537
4588
  if (LoginPopupComponent) {
4538
- setLoginPopupInitialView(void 0);
4589
+ setLoginPopupInitialView("funding");
4539
4590
  setShowLoginPopup(true);
4540
4591
  }
4541
4592
  };
4593
+ const handlePortfolioNavigate = (event) => {
4594
+ event?.preventDefault();
4595
+ closeMenus();
4596
+ console.log("[LoginTrace][Header] Portfolio selected");
4597
+ if (_onOrdersNavigate) {
4598
+ _onOrdersNavigate();
4599
+ return;
4600
+ }
4601
+ if (onNavigate) {
4602
+ onNavigate("/portfolio");
4603
+ }
4604
+ };
4542
4605
  const userPrimaryLabel = currentUser?.displayName?.trim() || "User";
4543
4606
  const resolveAuthReturnUrl = () => {
4544
4607
  if (getAuthReturnUrl) {
@@ -4572,6 +4635,7 @@ var Header = ({
4572
4635
  return false;
4573
4636
  };
4574
4637
  const handleSignIn = () => {
4638
+ console.log("[LoginTrace][Header] handleSignIn invoked", { hasCustomHandler: Boolean(onSignInClick) });
4575
4639
  if (onSignInClick) {
4576
4640
  onSignInClick();
4577
4641
  return;
@@ -4580,15 +4644,23 @@ var Header = ({
4580
4644
  return;
4581
4645
  }
4582
4646
  if (LoginPopupComponent) {
4647
+ console.log("[LoginTrace][Header] Opening login popup via handleSignIn");
4583
4648
  setShowLoginPopup(true);
4584
4649
  }
4585
4650
  };
4651
+ const handleLoginPopupClose = React5__namespace.default.useCallback(() => {
4652
+ console.log("[LoginTrace][Header] Closing login popup via onClose handler");
4653
+ setShowLoginPopup(false);
4654
+ setLoginPopupInitialView(void 0);
4655
+ }, []);
4586
4656
  const inferredActiveTab = (() => {
4587
4657
  if (locationPath === tradePath) return "trade";
4588
4658
  if (locationPath === homePath) return "home";
4589
4659
  if (locationPath === aboutPath) return "about";
4660
+ if (locationPath === learnPath) return "learn";
4590
4661
  if (locationPath.startsWith(offeringsPath)) return "offerings";
4591
4662
  if (locationPath === propertyMapPath) return "propertyMap";
4663
+ if (locationPath === portfolioPath) return "portfolio";
4592
4664
  return null;
4593
4665
  })();
4594
4666
  const resolvedActiveTab = activeTab ?? inferredActiveTab;
@@ -4597,6 +4669,8 @@ var Header = ({
4597
4669
  const offeringsActive = resolvedActiveTab === "offerings";
4598
4670
  const propertyMapActive = resolvedActiveTab === "propertyMap";
4599
4671
  const aboutActive = resolvedActiveTab === "about";
4672
+ const portfolioActive = resolvedActiveTab === "portfolio";
4673
+ const learnActive = resolvedActiveTab === "learn";
4600
4674
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
4601
4675
  /* @__PURE__ */ jsxRuntime.jsx(Overlay, { $isOpen: isMobileMenuOpen, onClick: () => setIsMobileMenuOpen(false) }),
4602
4676
  /* @__PURE__ */ jsxRuntime.jsxs(HeaderContainer, { children: [
@@ -4636,6 +4710,18 @@ var Header = ({
4636
4710
  children: "Trade"
4637
4711
  }
4638
4712
  ),
4713
+ /* @__PURE__ */ jsxRuntime.jsx(
4714
+ NavLink,
4715
+ {
4716
+ href: portfolioPath,
4717
+ className: portfolioActive ? "active" : "",
4718
+ onClick: (event) => {
4719
+ event.preventDefault();
4720
+ handleNavigation(portfolioPath);
4721
+ },
4722
+ children: "Portfolio"
4723
+ }
4724
+ ),
4639
4725
  /* @__PURE__ */ jsxRuntime.jsx(
4640
4726
  NavLink,
4641
4727
  {
@@ -4645,7 +4731,7 @@ var Header = ({
4645
4731
  event.preventDefault();
4646
4732
  handleNavigation(offeringsPath);
4647
4733
  },
4648
- children: "Offerings"
4734
+ children: "Initial Offerings"
4649
4735
  }
4650
4736
  ),
4651
4737
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4660,6 +4746,18 @@ var Header = ({
4660
4746
  children: "Property Map"
4661
4747
  }
4662
4748
  ),
4749
+ /* @__PURE__ */ jsxRuntime.jsx(
4750
+ NavLink,
4751
+ {
4752
+ href: learnPath,
4753
+ className: learnActive ? "active" : "",
4754
+ onClick: (event) => {
4755
+ event.preventDefault();
4756
+ handleNavigation(learnPath);
4757
+ },
4758
+ children: "Learn"
4759
+ }
4760
+ ),
4663
4761
  /* @__PURE__ */ jsxRuntime.jsx(
4664
4762
  NavLink,
4665
4763
  {
@@ -4707,8 +4805,10 @@ var Header = ({
4707
4805
  children: "Trade"
4708
4806
  }
4709
4807
  ),
4710
- /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(offeringsPath), children: "Offerings" }),
4808
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(portfolioPath), children: "Portfolio" }),
4809
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(offeringsPath), children: "Initial Offerings" }),
4711
4810
  /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(propertyMapPath), children: "Property Map" }),
4811
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(learnPath), children: "Learn" }),
4712
4812
  /* @__PURE__ */ jsxRuntime.jsx(MobileNavItem, { onClick: () => handleNavigation(aboutPath), children: "About" }),
4713
4813
  /* @__PURE__ */ jsxRuntime.jsx("div", { style: { borderTop: "1px solid #2b3139", margin: "8px 0" } }),
4714
4814
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4750,14 +4850,13 @@ var Header = ({
4750
4850
  ),
4751
4851
  isUserMenuOpen && /* @__PURE__ */ jsxRuntime.jsxs(DropdownMenu, { className: "user-menu-dropdown", children: [
4752
4852
  /* @__PURE__ */ jsxRuntime.jsx(
4753
- "div",
4853
+ "button",
4754
4854
  {
4755
- style: {
4756
- padding: "12px 16px",
4757
- borderBottom: "1px solid rgba(255,255,255,0.08)",
4758
- textAlign: "left"
4855
+ type: "button",
4856
+ onClick: (event) => {
4857
+ handlePortfolioNavigate(event);
4759
4858
  },
4760
- children: /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontWeight: 600 }, children: userPrimaryLabel })
4859
+ children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { children: "Portfolio" })
4761
4860
  }
4762
4861
  ),
4763
4862
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -4765,7 +4864,7 @@ var Header = ({
4765
4864
  {
4766
4865
  type: "button",
4767
4866
  onClick: (event) => {
4768
- console.log("[Header] Add funding menu item clicked");
4867
+ console.log("[LoginTrace][Header] Add funding menu item clicked");
4769
4868
  handleAddFundingClick(event);
4770
4869
  },
4771
4870
  children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { children: "Add funding" })
@@ -4776,7 +4875,7 @@ var Header = ({
4776
4875
  {
4777
4876
  type: "button",
4778
4877
  onClick: (event) => {
4779
- console.log("[Header] Logout menu item clicked");
4878
+ console.log("[LoginTrace][Header] Logout menu item clicked");
4780
4879
  void handleLogoutClick(event);
4781
4880
  },
4782
4881
  children: /* @__PURE__ */ jsxRuntime.jsx(MenuItem, { className: "logout", children: "Logout" })
@@ -4811,10 +4910,7 @@ var Header = ({
4811
4910
  LoginPopupComponent && showLoginPopup && /* @__PURE__ */ jsxRuntime.jsx(
4812
4911
  LoginPopupComponent,
4813
4912
  {
4814
- onClose: () => {
4815
- setShowLoginPopup(false);
4816
- setLoginPopupInitialView(void 0);
4817
- },
4913
+ onClose: handleLoginPopupClose,
4818
4914
  initialView: loginPopupInitialView
4819
4915
  }
4820
4916
  )
@@ -5342,6 +5438,7 @@ var OTP_INPUT_LENGTH = 6;
5342
5438
  var LoginPopup = ({
5343
5439
  onClose,
5344
5440
  onOpenEarlyAccess,
5441
+ onWalletLogin,
5345
5442
  isAuthenticated,
5346
5443
  currentUser,
5347
5444
  onSendEmailCode,
@@ -5366,38 +5463,74 @@ var LoginPopup = ({
5366
5463
  const [fundingLoading, setFundingLoading] = React5.useState(false);
5367
5464
  const [fundingError, setFundingError] = React5.useState("");
5368
5465
  const suppressAutoCloseRef = React5__namespace.default.useRef(false);
5466
+ React5.useEffect(() => {
5467
+ console.log("[LoginTrace][Popup] mounted");
5468
+ return () => console.log("[LoginTrace][Popup] unmounted");
5469
+ }, []);
5470
+ React5.useEffect(() => {
5471
+ console.log("[LoginTrace][Popup] view updated", { view });
5472
+ }, [view]);
5473
+ React5.useEffect(() => {
5474
+ console.log("[LoginTrace][Popup] auth props updated", { isAuthenticated, hasUser: Boolean(currentUser) });
5475
+ }, [isAuthenticated, currentUser]);
5369
5476
  React5.useEffect(() => {
5370
5477
  if (typeof initialView === "string") {
5478
+ console.log("[LoginTrace][Popup] initialView prop changed", { initialView });
5371
5479
  setView(initialView);
5372
5480
  }
5373
5481
  }, [initialView]);
5374
5482
  React5.useEffect(() => {
5375
5483
  if (!autoCloseOnAuth) {
5484
+ console.log("[LoginTrace][Popup] autoClose disabled", { autoCloseOnAuth, view });
5376
5485
  return;
5377
5486
  }
5378
5487
  if (suppressAutoCloseRef.current) {
5488
+ console.log("[LoginTrace][Popup] autoClose suppressed", { view });
5379
5489
  return;
5380
5490
  }
5381
5491
  if (view === "kyc" || view === "kyc-success" || view === "kyc-failed" || view === "funding") {
5492
+ console.log("[LoginTrace][Popup] autoClose skipped due to onboarding view", { view });
5382
5493
  return;
5383
5494
  }
5495
+ console.log("[LoginTrace][Popup] autoClose effect evaluating", {
5496
+ autoCloseOnAuth,
5497
+ isAuthenticated,
5498
+ hasUser: Boolean(currentUser),
5499
+ view
5500
+ });
5384
5501
  if (isAuthenticated || currentUser) {
5502
+ console.log("[LoginTrace][Popup] autoClose triggered", { isAuthenticated, hasUser: Boolean(currentUser), view });
5385
5503
  onClose();
5386
5504
  }
5387
5505
  }, [autoCloseOnAuth, currentUser, isAuthenticated, onClose, view]);
5388
- const handleWalletLogin = () => {
5506
+ const handleWalletLogin = async () => {
5507
+ console.log("[LoginTrace][Popup] Wallet login clicked, onWalletLogin:", !!onWalletLogin);
5508
+ if (onWalletLogin) {
5509
+ try {
5510
+ console.log("[LoginTrace][Popup] Calling onWalletLogin...");
5511
+ await onWalletLogin();
5512
+ console.log("[LoginTrace][Popup] onWalletLogin completed, closing popup");
5513
+ onClose();
5514
+ return;
5515
+ } catch (err) {
5516
+ console.error("[LoginTrace][Popup] Wallet login failed", err);
5517
+ }
5518
+ }
5519
+ console.log("[LoginTrace][Popup] No onWalletLogin handler, closing popup");
5389
5520
  onClose();
5390
5521
  if (onOpenEarlyAccess) {
5391
5522
  onOpenEarlyAccess();
5392
5523
  }
5393
5524
  };
5394
5525
  const handleEmailClick = (signUp = false) => {
5526
+ console.log("[LoginTrace][Popup] handleEmailClick", { signUp });
5395
5527
  setIsSignUp(signUp);
5396
5528
  setView("email");
5397
5529
  setError("");
5398
5530
  };
5399
5531
  const handleSendCode = async (event) => {
5400
5532
  event?.preventDefault();
5533
+ console.log("[LoginTrace][Popup] handleSendCode invoked", { email, isSignUp, handle, eventType: event?.type });
5401
5534
  if (!email || !email.includes("@")) {
5402
5535
  setError("Please enter a valid email address");
5403
5536
  return;
@@ -5410,13 +5543,15 @@ var LoginPopup = ({
5410
5543
  setError("");
5411
5544
  const normalizedHandle = isSignUp ? handle.trim() : void 0;
5412
5545
  try {
5546
+ console.log("[LoginTrace][Popup] Attempting demo login fallback", { hasDemoHandler: Boolean(onDemoLogin) });
5413
5547
  const demoResult = await onDemoLogin?.(email, normalizedHandle ?? null);
5414
5548
  if (demoResult && demoResult.success) {
5549
+ console.log("[LoginTrace][Popup] Demo login succeeded, skipping OTP flow");
5415
5550
  setLoading(false);
5416
5551
  return;
5417
5552
  }
5418
5553
  } catch (err) {
5419
- console.warn("Demo login failed, attempting email OTP", err);
5554
+ console.warn("[LoginTrace][Popup] Demo login failed, attempting email OTP", err);
5420
5555
  }
5421
5556
  if (!onSendEmailCode) {
5422
5557
  setError("Email authentication is not configured for this popup.");
@@ -5424,10 +5559,13 @@ var LoginPopup = ({
5424
5559
  return;
5425
5560
  }
5426
5561
  try {
5562
+ console.log("[LoginTrace][Popup] Calling onSendEmailCode", { email, isSignUp, normalizedHandle });
5427
5563
  await onSendEmailCode({ email, isSignUp, handle: normalizedHandle ?? null });
5564
+ console.log("[LoginTrace][Popup] onSendEmailCode resolved, switching to OTP view");
5428
5565
  setView("otp");
5429
5566
  setOtp(Array(OTP_INPUT_LENGTH).fill(""));
5430
5567
  } catch (err) {
5568
+ console.error("[LoginTrace][Popup] onSendEmailCode threw", err);
5431
5569
  setError(err instanceof Error ? err.message : "Failed to send verification code");
5432
5570
  } finally {
5433
5571
  setLoading(false);
@@ -5460,9 +5598,32 @@ var LoginPopup = ({
5460
5598
  document.getElementById(`otp-${index - 1}`)?.focus();
5461
5599
  }
5462
5600
  };
5601
+ const handleOTPInput = (index, event) => {
5602
+ const rawValue = event.currentTarget.value ?? "";
5603
+ const nativeEvent = event.nativeEvent;
5604
+ const isPasteLike = nativeEvent?.inputType === "insertFromPaste" || rawValue.length > 1;
5605
+ if (isPasteLike) {
5606
+ handleOTPChange(index, rawValue);
5607
+ }
5608
+ };
5609
+ const handleOTPPaste = (event) => {
5610
+ event.preventDefault();
5611
+ const pasted = event.clipboardData?.getData("text") ?? "";
5612
+ const digits = pasted.replace(/\D/g, "").slice(0, OTP_INPUT_LENGTH).split("");
5613
+ if (digits.length === 0) return;
5614
+ const next = Array.from({ length: OTP_INPUT_LENGTH }, (_, i) => digits[i] ?? "");
5615
+ setOtp(next);
5616
+ const lastIndex = Math.min(digits.length, OTP_INPUT_LENGTH) - 1;
5617
+ if (lastIndex >= 0) {
5618
+ requestAnimationFrame(() => {
5619
+ document.getElementById(`otp-${lastIndex}`)?.focus();
5620
+ });
5621
+ }
5622
+ };
5463
5623
  const handleVerifyCode = async (event) => {
5464
5624
  event.preventDefault();
5465
5625
  const code = otp.join("");
5626
+ console.log("[LoginTrace][Popup] handleVerifyCode", { codeLength: code.length, isSignUp });
5466
5627
  if (code.length !== OTP_INPUT_LENGTH) {
5467
5628
  setError("Please enter the 6-digit code");
5468
5629
  return;
@@ -5477,13 +5638,16 @@ var LoginPopup = ({
5477
5638
  suppressAutoCloseRef.current = true;
5478
5639
  }
5479
5640
  try {
5641
+ console.log("[LoginTrace][Popup] Calling onVerifyEmailCode");
5480
5642
  await onVerifyEmailCode({ code, email });
5481
5643
  if (isSignUp) {
5644
+ console.log("[LoginTrace][Popup] Signup OTP verified, moving to KYC view");
5482
5645
  setView("kyc");
5483
5646
  setLoading(false);
5484
5647
  return;
5485
5648
  }
5486
5649
  } catch (err) {
5650
+ console.error("[LoginTrace][Popup] onVerifyEmailCode threw", err);
5487
5651
  suppressAutoCloseRef.current = false;
5488
5652
  setError(err instanceof Error ? err.message : "Invalid verification code");
5489
5653
  } finally {
@@ -5668,6 +5832,9 @@ var LoginPopup = ({
5668
5832
  value: digit,
5669
5833
  onChange: (event) => handleOTPChange(index, event.target.value),
5670
5834
  onKeyDown: (event) => handleOTPKeyDown(index, event),
5835
+ onInput: (event) => handleOTPInput(index, event),
5836
+ onPaste: handleOTPPaste,
5837
+ autoComplete: index === 0 ? "one-time-code" : "off",
5671
5838
  autoFocus: index === 0
5672
5839
  },
5673
5840
  index
@@ -6724,27 +6891,55 @@ var PriceChange = styled23__default.default.span`
6724
6891
  gap: 0.35rem;
6725
6892
  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
6893
  `;
6727
- function PropertyOverview({ propertyName: _propertyName, location: _location, midPrice: _midPrice, onTradeClick: _onTradeClick }) {
6894
+ function PropertyOverview({
6895
+ propertyName: _propertyName,
6896
+ location: _location,
6897
+ midPrice: _midPrice,
6898
+ onTradeClick: _onTradeClick,
6899
+ overviewData,
6900
+ minimumParticipation,
6901
+ bedrooms,
6902
+ bathrooms,
6903
+ carSpaces,
6904
+ propertyTypeLabel
6905
+ }) {
6906
+ const description = overviewData?.description ?? "N/A";
6907
+ const tokensIssued = overviewData?.tokensIssued ?? null;
6908
+ const offeringValuation = overviewData?.offeringValuation ?? null;
6909
+ const weeklyRent = overviewData?.weeklyRent ?? null;
6910
+ const indicativeListing = overviewData?.indicativeListing ?? "N/A";
6911
+ const minParticipationValue = minimumParticipation ?? overviewData?.minimumParticipation ?? null;
6912
+ const landSize = overviewData?.landSizeSqm ?? null;
6913
+ const buildingSize = overviewData?.buildingSizeSqm ?? null;
6914
+ const propertyType = propertyTypeLabel ?? overviewData?.propertyType ?? "N/A";
6915
+ overviewData?.yearBuilt ?? null;
6916
+ const ownership = overviewData?.ownership ?? "N/A";
6917
+ const zoning = overviewData?.zoning ?? "N/A";
6918
+ const levels = overviewData?.levels ?? null;
6919
+ const daStatus = overviewData?.daStatus ?? "N/A";
6920
+ const unitPrice = tokensIssued && offeringValuation ? offeringValuation / tokensIssued : null;
6921
+ const formattedPropertyType = propertyType !== "N/A" ? propertyType.charAt(0).toUpperCase() + propertyType.slice(1).toLowerCase() : "N/A";
6728
6922
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6729
6923
  /* @__PURE__ */ jsxRuntime.jsxs(TwoColGrid, { children: [
6730
6924
  /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
6731
6925
  /* @__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
- ] })
6926
+ /* @__PURE__ */ jsxRuntime.jsx(BodyText, { children: description === "N/A" ? description : description.split("\n\n").map((paragraph, i) => /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
6927
+ paragraph,
6928
+ i < description.split("\n\n").length - 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6929
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
6930
+ /* @__PURE__ */ jsxRuntime.jsx("br", {})
6931
+ ] })
6932
+ ] }, i)) })
6738
6933
  ] }),
6739
6934
  /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
6740
6935
  /* @__PURE__ */ jsxRuntime.jsx(SectionHeading, { children: "The Offering" }),
6741
6936
  /* @__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 }
6937
+ { label: "Units Issued", value: tokensIssued?.toLocaleString() ?? "-", gold: false },
6938
+ { label: "Issue Price", value: unitPrice ? `$${unitPrice.toFixed(2)} / Unit` : "-", gold: true },
6939
+ { label: "Implied Value", value: offeringValuation ? `$${offeringValuation.toLocaleString()}` : "-", gold: false },
6940
+ { label: "Minimum Participation", value: minParticipationValue != null ? `$${minParticipationValue.toLocaleString()}` : "-", gold: false },
6941
+ { label: "Est. Cash Flow", value: weeklyRent ? `$${weeklyRent.toLocaleString()}/wk` : "-", gold: true },
6942
+ { label: "Indicative Listing Date", value: indicativeListing, gold: false }
6748
6943
  ].map(({ label, value, gold }) => /* @__PURE__ */ jsxRuntime.jsxs(OfferingItem, { children: [
6749
6944
  /* @__PURE__ */ jsxRuntime.jsx(OfferingLabel, { children: label }),
6750
6945
  /* @__PURE__ */ jsxRuntime.jsx(OfferingValue, { $gold: gold, children: value })
@@ -6757,10 +6952,10 @@ function PropertyOverview({ propertyName: _propertyName, location: _location, mi
6757
6952
  /* @__PURE__ */ jsxRuntime.jsx(AssetDetailsTitle, { children: "Asset Details" })
6758
6953
  ] }),
6759
6954
  /* @__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}" }
6955
+ { label: "Bedrooms", value: bedrooms != null ? bedrooms.toString() : "-", icon: "\u{1F6CF}\uFE0F" },
6956
+ { label: "Bathrooms", value: bathrooms != null ? bathrooms.toString() : "-", icon: "\u{1F6BF}" },
6957
+ { type: "dual", label1: "Land", value1: landSize?.toString() ?? "-", label2: "Floor", value2: buildingSize?.toString() ?? "-", unit: "sqm", highlight: true },
6958
+ { label: "Car Spaces", value: carSpaces != null ? carSpaces.toString() : "-", icon: "\u{1F697}" }
6764
6959
  ].map((stat, i) => /* @__PURE__ */ jsxRuntime.jsx(StatCard, { $highlight: !!stat.highlight, children: stat.type === "dual" ? /* @__PURE__ */ jsxRuntime.jsxs(DualStatInner, { children: [
6765
6960
  /* @__PURE__ */ jsxRuntime.jsxs(DualStatCol, { children: [
6766
6961
  /* @__PURE__ */ jsxRuntime.jsx(StatLabel, { $gold: true, children: stat.label1 }),
@@ -6782,14 +6977,14 @@ function PropertyOverview({ propertyName: _propertyName, location: _location, mi
6782
6977
  /* @__PURE__ */ jsxRuntime.jsx(StatBigValue, { $gold: !!stat.highlight, children: stat.value })
6783
6978
  ] }) }, i)) }),
6784
6979
  /* @__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" }
6980
+ { label: "Last Sale", value: "-" },
6981
+ { label: "Suburb Median", value: "-" },
6982
+ { label: "Replication Cost of Architecture", value: "-" },
6983
+ { label: "DA Status", value: daStatus, status: daStatus.toLowerCase() === "approved" ? "success" : "progress" },
6984
+ { label: "Property Type", value: formattedPropertyType },
6985
+ { label: "Ownership", value: ownership ?? "N/A" },
6986
+ { label: "Zoning", value: zoning ?? "N/A" },
6987
+ { label: "Levels", value: levels?.toString() ?? "N/A" }
6793
6988
  ].map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(DetailCell, { $borderBottom: i < 4, $borderRight: (i + 1) % 4 !== 0, children: [
6794
6989
  /* @__PURE__ */ jsxRuntime.jsx(DetailCellLabel, { children: item.label }),
6795
6990
  /* @__PURE__ */ jsxRuntime.jsxs(DetailCellValue, { $status: item.status, children: [
@@ -7675,7 +7870,7 @@ var DocIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height
7675
7870
  /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
7676
7871
  /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "10 9 9 9 8 9" })
7677
7872
  ] });
7678
- var docs = [
7873
+ var fallbackDocs = [
7679
7874
  { href: "/documents/musgrave-valuation-report.pdf", label: "Valuation Report" },
7680
7875
  { href: "/documents/musgrave-offering-material.pdf", label: "Offering Material" },
7681
7876
  { href: "/documents/musgrave-mortgage-agreement.pdf", label: "Mortgage Agreement" },
@@ -7684,13 +7879,26 @@ var docs = [
7684
7879
  { href: "/documents/musgrave-risk-disclosure.pdf", label: "Risk Disclosure Statement" },
7685
7880
  { href: "/documents/musgrave-building-inspection.pdf", label: "Building & Pest Inspection Report" }
7686
7881
  ];
7687
- function PropertyDocuments() {
7882
+ function PropertyDocuments({ documentsData }) {
7883
+ const backendDocuments = Array.isArray(documentsData?.documents) ? documentsData.documents : null;
7884
+ const hasBackendDocuments = !!backendDocuments?.length;
7885
+ const documents = hasBackendDocuments ? backendDocuments : fallbackDocs.map((doc) => ({
7886
+ title: doc.label,
7887
+ documentUrl: doc.href
7888
+ }));
7688
7889
  return /* @__PURE__ */ jsxRuntime.jsxs(Section2, { children: [
7689
7890
  /* @__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)) })
7891
+ /* @__PURE__ */ jsxRuntime.jsx(DocList, { children: documents.map(({ documentUrl, title }) => {
7892
+ const isAvailable = Boolean(documentUrl);
7893
+ return /* @__PURE__ */ jsxRuntime.jsx(DocItem, { children: hasBackendDocuments && isAvailable ? /* @__PURE__ */ jsxRuntime.jsxs(DocLink, { href: documentUrl, target: "_blank", rel: "noopener noreferrer", children: [
7894
+ /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
7895
+ title
7896
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(DocItemDisabled, { children: [
7897
+ /* @__PURE__ */ jsxRuntime.jsx(DocIconWrapper, { children: /* @__PURE__ */ jsxRuntime.jsx(DocIcon, {}) }),
7898
+ title,
7899
+ /* @__PURE__ */ jsxRuntime.jsx(ComingSoonBadge, { children: "Coming Soon" })
7900
+ ] }) }, `${title}-${documentUrl ?? "pending"}`);
7901
+ }) })
7694
7902
  ] });
7695
7903
  }
7696
7904
  var Section2 = styled23__default.default.section`
@@ -7734,11 +7942,29 @@ var DocLink = styled23__default.default.a`
7734
7942
  color: var(--color-accent);
7735
7943
  }
7736
7944
  `;
7945
+ var DocItemDisabled = styled23__default.default.div`
7946
+ display: flex;
7947
+ align-items: center;
7948
+ color: var(--color-text-secondary);
7949
+ cursor: not-allowed;
7950
+ opacity: 0.6;
7951
+ `;
7737
7952
  var DocIconWrapper = styled23__default.default.span`
7738
7953
  margin-right: 0.75rem;
7739
7954
  flex-shrink: 0;
7740
7955
  color: var(--color-text-secondary);
7741
7956
  `;
7957
+ var ComingSoonBadge = styled23__default.default.span`
7958
+ margin-left: auto;
7959
+ padding: 0.25rem 0.5rem;
7960
+ background: rgba(212, 175, 55, 0.1);
7961
+ color: #D4AF37;
7962
+ border-radius: 0.25rem;
7963
+ font-size: 0.7rem;
7964
+ font-weight: 500;
7965
+ text-transform: uppercase;
7966
+ letter-spacing: 0.05em;
7967
+ `;
7742
7968
  var formatIsoDate = (value) => {
7743
7969
  const parsed = new Date(value);
7744
7970
  if (Number.isNaN(parsed.getTime())) return value;
@@ -8025,7 +8251,7 @@ function AssetSelectorBar({ propertyName, tokenPrice, offeringValuation }) {
8025
8251
  /* @__PURE__ */ jsxRuntime.jsxs(SelectorMetrics, { children: [
8026
8252
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8027
8253
  /* @__PURE__ */ jsxRuntime.jsx(MetricLabel, { children: "Unit Price" }),
8028
- /* @__PURE__ */ jsxRuntime.jsxs(MetricValue, { accent: true, children: [
8254
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricValue, { $accent: true, children: [
8029
8255
  "$",
8030
8256
  tokenPrice.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })
8031
8257
  ] })
@@ -8120,7 +8346,7 @@ var MetricLabel = styled23__default.default.span`
8120
8346
  var MetricValue = styled23__default.default.span`
8121
8347
  font-size: 1.1rem;
8122
8348
  font-weight: 700;
8123
- color: ${(p) => p.accent ? "#D4AF37" : "#fff"};
8349
+ color: ${(p) => p.$accent ? "#D4AF37" : "#fff"};
8124
8350
  `;
8125
8351
  var Separator = styled23__default.default.span`
8126
8352
  font-size: 1rem;
@@ -8239,7 +8465,7 @@ function OfferingProgressCard({
8239
8465
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u24D8" })
8240
8466
  ] }),
8241
8467
  /* @__PURE__ */ jsxRuntime.jsxs(LivePercent, { children: [
8242
- percentSold.toFixed(1),
8468
+ percentSold < 0.1 && percentSold > 0 ? percentSold.toFixed(3) : percentSold.toFixed(1),
8243
8469
  "%",
8244
8470
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u2191" })
8245
8471
  ] })
@@ -8592,6 +8818,7 @@ function OrderPanel({
8592
8818
  statusLabel,
8593
8819
  statusColor,
8594
8820
  ipoStarted,
8821
+ isAuthenticated,
8595
8822
  tokenPrice,
8596
8823
  feeRate,
8597
8824
  supplyToSell,
@@ -8609,10 +8836,14 @@ function OrderPanel({
8609
8836
  setSliderValue,
8610
8837
  setManualOrderAmount,
8611
8838
  onOrderButtonClick,
8839
+ onSignInClick,
8612
8840
  orderButtonText,
8613
8841
  isOrderButtonDisabled,
8614
8842
  hasInsufficientFunds,
8615
- onPlaceAnotherOrder
8843
+ onPlaceAnotherOrder,
8844
+ onDeposit,
8845
+ tokenDisplayName,
8846
+ tokenSymbol
8616
8847
  }) {
8617
8848
  const [payInputValue, setPayInputValue] = React5.useState("");
8618
8849
  const [receiveInputValue, setReceiveInputValue] = React5.useState("");
@@ -8621,11 +8852,14 @@ function OrderPanel({
8621
8852
  const handlePayBlur = () => {
8622
8853
  setIsPayInputFocused(false);
8623
8854
  const parsed = parseInt(payInputValue.replace(/[^0-9]/g, ""), 10) || 0;
8624
- if (parsed > availableBalance) {
8625
- setManualOrderAmount(parsed);
8855
+ if (parsed <= 0) {
8856
+ setManualOrderAmount(null);
8857
+ setSliderValue(0);
8858
+ } else if (parsed >= availableBalance) {
8859
+ setManualOrderAmount(null);
8626
8860
  setSliderValue(100);
8627
8861
  } else {
8628
- setManualOrderAmount(null);
8862
+ setManualOrderAmount(parsed);
8629
8863
  const ratio = availableBalance === 0 ? 0 : Math.round(Math.max(0, parsed / availableBalance * 100));
8630
8864
  setSliderValue(ratio);
8631
8865
  }
@@ -8634,11 +8868,14 @@ function OrderPanel({
8634
8868
  setIsReceiveInputFocused(false);
8635
8869
  const parsed = parseFloat(receiveInputValue) || 0;
8636
8870
  const newOrderTotal = Math.round(parsed * tokenPrice);
8637
- if (newOrderTotal > availableBalance) {
8638
- setManualOrderAmount(newOrderTotal);
8871
+ if (newOrderTotal <= 0) {
8872
+ setManualOrderAmount(null);
8873
+ setSliderValue(0);
8874
+ } else if (newOrderTotal >= availableBalance) {
8875
+ setManualOrderAmount(null);
8639
8876
  setSliderValue(100);
8640
8877
  } else {
8641
- setManualOrderAmount(null);
8878
+ setManualOrderAmount(newOrderTotal);
8642
8879
  const ratio = availableBalance === 0 ? 0 : Math.round(Math.max(0, newOrderTotal / availableBalance * 100));
8643
8880
  setSliderValue(ratio);
8644
8881
  }
@@ -8664,10 +8901,10 @@ function OrderPanel({
8664
8901
  ] }),
8665
8902
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "success-body", children: [
8666
8903
  [
8667
- { label: "Units Acquired", value: `${lastOrderDetails?.tokens?.toFixed(2) || "0.00"} MUS` },
8904
+ { label: "Units Acquired", value: `${lastOrderDetails?.tokens?.toFixed(2) || "0.00"} ${tokenSymbol}` },
8668
8905
  { label: "Price Per Unit", value: `$${tokenPrice.toFixed(2)}` },
8669
8906
  {
8670
- label: "Musgrave Exposure",
8907
+ label: `${tokenDisplayName} Exposure`,
8671
8908
  value: `${((lastOrderDetails?.tokens ?? 0) / supplyToSell * 100).toFixed(3)}%`
8672
8909
  }
8673
8910
  ].map((row) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "success-row", children: [
@@ -8708,7 +8945,7 @@ function OrderPanel({
8708
8945
  }
8709
8946
  }
8710
8947
  ),
8711
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "AUD" })
8948
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "USDC" })
8712
8949
  ] }),
8713
8950
  /* @__PURE__ */ jsxRuntime.jsx(QuickSelectRow, { children: [25, 50, 75, 100].map((pct) => /* @__PURE__ */ jsxRuntime.jsxs(
8714
8951
  "button",
@@ -8729,13 +8966,19 @@ function OrderPanel({
8729
8966
  ] }),
8730
8967
  /* @__PURE__ */ jsxRuntime.jsxs(FundsRow, { children: [
8731
8968
  /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8732
- "Available Funds: ",
8733
- /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8734
- "$",
8735
- availableBalance.toLocaleString()
8736
- ] })
8969
+ "Available Funds:",
8970
+ " ",
8971
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: isAuthenticated ? `$${availableBalance.toLocaleString()}` : "\u2014" })
8737
8972
  ] }),
8738
- /* @__PURE__ */ jsxRuntime.jsx(DepositButton, { type: "button", children: "+ Deposit" })
8973
+ /* @__PURE__ */ jsxRuntime.jsx(
8974
+ DepositButton,
8975
+ {
8976
+ type: "button",
8977
+ onClick: isAuthenticated ? onDeposit : void 0,
8978
+ disabled: !isAuthenticated,
8979
+ children: "+ Deposit"
8980
+ }
8981
+ )
8739
8982
  ] }),
8740
8983
  /* @__PURE__ */ jsxRuntime.jsx(Divider2, { children: "\u2193" }),
8741
8984
  /* @__PURE__ */ jsxRuntime.jsxs(Card2, { children: [
@@ -8767,7 +9010,7 @@ function OrderPanel({
8767
9010
  }
8768
9011
  }
8769
9012
  ),
8770
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "MUSGRAVE" })
9013
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: tokenDisplayName })
8771
9014
  ] })
8772
9015
  ] }),
8773
9016
  /* @__PURE__ */ jsxRuntime.jsxs(OrderSummary, { children: [
@@ -8783,7 +9026,8 @@ function OrderPanel({
8783
9026
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Buying" }),
8784
9027
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8785
9028
  tokenQuantity.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 }),
8786
- " units"
9029
+ " ",
9030
+ tokenSymbol
8787
9031
  ] })
8788
9032
  ] }),
8789
9033
  /* @__PURE__ */ jsxRuntime.jsxs(SummaryRow, { children: [
@@ -8794,7 +9038,8 @@ function OrderPanel({
8794
9038
  ] }),
8795
9039
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8796
9040
  feeInTokens.toFixed(2),
8797
- " units"
9041
+ " ",
9042
+ tokenSymbol
8798
9043
  ] })
8799
9044
  ] }),
8800
9045
  /* @__PURE__ */ jsxRuntime.jsxs(SummaryTotal, { children: [
@@ -8802,7 +9047,7 @@ function OrderPanel({
8802
9047
  /* @__PURE__ */ jsxRuntime.jsxs("strong", { children: [
8803
9048
  "$",
8804
9049
  orderTotal.toLocaleString(),
8805
- " AUD"
9050
+ " USDC"
8806
9051
  ] })
8807
9052
  ] })
8808
9053
  ] })
@@ -8813,32 +9058,46 @@ function OrderPanel({
8813
9058
  type: "button",
8814
9059
  disabled: isOrderButtonDisabled,
8815
9060
  "data-green": orderButtonText === "Place Order",
8816
- onClick: onOrderButtonClick,
9061
+ onClick: () => {
9062
+ if (!isAuthenticated) {
9063
+ onSignInClick();
9064
+ return;
9065
+ }
9066
+ onOrderButtonClick();
9067
+ },
8817
9068
  children: orderButtonText
8818
9069
  }
8819
9070
  ),
8820
- /* @__PURE__ */ jsxRuntime.jsxs(BalanceCards, { children: [
9071
+ isAuthenticated && /* @__PURE__ */ jsxRuntime.jsxs(BalanceCards, { children: [
8821
9072
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceCard, { children: [
8822
9073
  /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: "Available to Invest" }),
8823
9074
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceValue, { children: [
8824
9075
  "$",
8825
9076
  availableBalance.toLocaleString()
8826
9077
  ] }),
8827
- /* @__PURE__ */ jsxRuntime.jsx(BalanceAction, { children: "+ Deposit" })
9078
+ /* @__PURE__ */ jsxRuntime.jsx(BalanceAction, { onClick: onDeposit, style: { cursor: onDeposit ? "pointer" : "default" }, children: "+ Deposit" })
8828
9079
  ] }),
8829
9080
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceCard, { children: [
8830
- /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: "Musgrave Owned" }),
9081
+ /* @__PURE__ */ jsxRuntime.jsx(BalanceLabel, { children: `${tokenDisplayName} Owned` }),
8831
9082
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceValue, { children: [
8832
9083
  displayedOwnedTokens.toFixed(2),
9084
+ " ",
9085
+ tokenSymbol,
8833
9086
  ownedTokensJustUpdated && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
8834
9087
  "+",
8835
- lastOrderQuantity.toFixed(2)
9088
+ lastOrderQuantity.toFixed(2),
9089
+ " ",
9090
+ tokenSymbol
8836
9091
  ] })
8837
9092
  ] }),
8838
9093
  /* @__PURE__ */ jsxRuntime.jsxs(BalanceSub, { children: [
8839
9094
  "$",
8840
- (displayedOwnedTokens * tokenPrice).toLocaleString(),
8841
- " \u2022 ",
9095
+ (displayedOwnedTokens * tokenPrice).toLocaleString("en-US", {
9096
+ minimumFractionDigits: 0,
9097
+ maximumFractionDigits: 0
9098
+ }),
9099
+ " ",
9100
+ "\u2022 ",
8842
9101
  (displayedOwnedTokens / supplyToSell * 100).toFixed(3),
8843
9102
  "%"
8844
9103
  ] })
@@ -9456,7 +9715,23 @@ var IframeShield = styled23__default.default.div`
9456
9715
  z-index: 1;
9457
9716
  cursor: pointer;
9458
9717
  `;
9459
- function NewsOrdersSection({ newsItems, userSubscription, tokenPrice }) {
9718
+ var SUBSCRIPTIONS_PAGE_SIZE = 6;
9719
+ function NewsOrdersSection({ newsItems, userSubscriptions, tokenPrice }) {
9720
+ const [page, setPage] = React5.useState(0);
9721
+ const totalPages = Math.max(1, Math.ceil(userSubscriptions.length / SUBSCRIPTIONS_PAGE_SIZE));
9722
+ React5.useEffect(() => {
9723
+ if (page > totalPages - 1) {
9724
+ setPage(totalPages - 1);
9725
+ }
9726
+ }, [page, totalPages]);
9727
+ React5.useEffect(() => {
9728
+ setPage(0);
9729
+ }, [userSubscriptions]);
9730
+ const paginatedSubscriptions = React5.useMemo(() => {
9731
+ const start = page * SUBSCRIPTIONS_PAGE_SIZE;
9732
+ return userSubscriptions.slice(start, start + SUBSCRIPTIONS_PAGE_SIZE);
9733
+ }, [page, userSubscriptions]);
9734
+ const hasPagination = userSubscriptions.length > SUBSCRIPTIONS_PAGE_SIZE;
9460
9735
  return /* @__PURE__ */ jsxRuntime.jsxs(Row2, { children: [
9461
9736
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsPanel, { children: [
9462
9737
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsHeader, { children: [
@@ -9483,34 +9758,57 @@ function NewsOrdersSection({ newsItems, userSubscription, tokenPrice }) {
9483
9758
  ] }),
9484
9759
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsPanel, { children: [
9485
9760
  /* @__PURE__ */ jsxRuntime.jsxs(TradeNewsHeader, { children: [
9486
- /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Your Orders" }),
9487
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Offering Subscriptions" })
9761
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9762
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: "Your Orders" }),
9763
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Offering Subscriptions" })
9764
+ ] }),
9765
+ hasPagination ? /* @__PURE__ */ jsxRuntime.jsxs(Pagination, { children: [
9766
+ /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => setPage((prev) => Math.max(prev - 1, 0)), disabled: page === 0, children: "Prev" }),
9767
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
9768
+ "Page ",
9769
+ page + 1,
9770
+ "/",
9771
+ totalPages
9772
+ ] }),
9773
+ /* @__PURE__ */ jsxRuntime.jsx(
9774
+ "button",
9775
+ {
9776
+ type: "button",
9777
+ onClick: () => setPage((prev) => Math.min(prev + 1, totalPages - 1)),
9778
+ disabled: page >= totalPages - 1,
9779
+ children: "Next"
9780
+ }
9781
+ )
9782
+ ] }) : null
9488
9783
  ] }),
9489
9784
  /* @__PURE__ */ jsxRuntime.jsxs(OrdersTable, { children: [
9490
9785
  /* @__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: [
9786
+ paginatedSubscriptions.length ? paginatedSubscriptions.map((subscription) => {
9787
+ const subscriptionDate = new Date(subscription.timestamp);
9788
+ return /* @__PURE__ */ jsxRuntime.jsxs(OrdersRow, { children: [
9789
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9790
+ subscriptionDate.toLocaleDateString("en-AU", {
9791
+ day: "2-digit",
9792
+ month: "short",
9793
+ year: "numeric"
9794
+ }),
9795
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: subscriptionDate.toLocaleTimeString("en-AU", {
9796
+ hour: "2-digit",
9797
+ minute: "2-digit"
9798
+ }) })
9799
+ ] }),
9800
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "units", children: subscription.tokens.toFixed(2) }),
9801
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9802
+ "$",
9803
+ tokenPrice.toFixed(2)
9804
+ ] }),
9805
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "total", children: [
9806
+ "$",
9807
+ subscription.value.toLocaleString()
9808
+ ] }),
9809
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "status", children: subscription.status ?? "Confirmed" })
9810
+ ] }, `${subscription.timestamp}-${subscription.tokens}`);
9811
+ }) : /* @__PURE__ */ jsxRuntime.jsxs(OrdersEmpty, { children: [
9514
9812
  /* @__PURE__ */ jsxRuntime.jsx("div", { children: "\u{1F4CB}" }),
9515
9813
  /* @__PURE__ */ jsxRuntime.jsx("p", { children: "No orders yet" }),
9516
9814
  /* @__PURE__ */ jsxRuntime.jsx("small", { children: "Subscribe to the IPO above to place your first order" })
@@ -9637,6 +9935,28 @@ var OrdersTable = styled23__default.default.div`
9637
9935
  flex: 1;
9638
9936
  overflow: auto;
9639
9937
  `;
9938
+ var Pagination = styled23__default.default.div`
9939
+ display: flex;
9940
+ align-items: center;
9941
+ gap: 0.75rem;
9942
+ font-size: 0.75rem;
9943
+ color: var(--color-text-secondary);
9944
+
9945
+ button {
9946
+ border: 1px solid rgba(255,255,255,0.2);
9947
+ background: rgba(255,255,255,0.05);
9948
+ color: #fff;
9949
+ border-radius: 9999px;
9950
+ padding: 0.25rem 0.9rem;
9951
+ font-size: 0.7rem;
9952
+ cursor: pointer;
9953
+ transition: opacity 0.2s;
9954
+ &:disabled {
9955
+ opacity: 0.4;
9956
+ cursor: not-allowed;
9957
+ }
9958
+ }
9959
+ `;
9640
9960
  var OrdersHead = styled23__default.default.div`
9641
9961
  display: grid;
9642
9962
  grid-template-columns: 1fr 1fr 1fr 1fr 1.2fr;
@@ -9906,19 +10226,24 @@ var ButtonRow = styled23__default.default.div`
9906
10226
  }
9907
10227
  `;
9908
10228
  function PropertyBuy({
9909
- propertyName = "8c Mcleod Street (Musgrave)",
9910
- propertyLocation: propertyLocationLabel = "Mosman, Sydney",
10229
+ propertyName = "Loaf Property",
10230
+ propertyLocation: propertyLocationLabel = "Sydney, NSW",
10231
+ tokenDisplayName = "Property Token",
10232
+ tokenSymbol = "LOAF",
9911
10233
  isAuthenticated,
9912
10234
  onSignIn,
9913
10235
  saleData,
9914
10236
  walletUsdcBalance,
10237
+ walletPropertyTokenBalance,
9915
10238
  onPurchase,
9916
10239
  purchaseStatus = "idle",
9917
- purchaseError
10240
+ purchaseError,
10241
+ onDeposit,
10242
+ initialUserSubscriptions = []
9918
10243
  }) {
9919
10244
  const [sliderValue, setSliderValue] = React5.useState(0);
9920
10245
  const [availableBalance, setAvailableBalance] = React5.useState(walletUsdcBalance ?? 125e3);
9921
- const [userSubscription, setUserSubscription] = React5.useState(null);
10246
+ const [optimisticUserSubscriptions, setOptimisticUserSubscriptions] = React5.useState([]);
9922
10247
  const [manualOrderAmount, setManualOrderAmount] = React5.useState(null);
9923
10248
  const [ownedTokens, setOwnedTokens] = React5.useState(0);
9924
10249
  const [displayedOwnedTokens, setDisplayedOwnedTokens] = React5.useState(0);
@@ -9936,6 +10261,12 @@ function PropertyBuy({
9936
10261
  isNew: false
9937
10262
  }))
9938
10263
  );
10264
+ const resolvedUserSubscriptions = initialUserSubscriptions && initialUserSubscriptions.length > 0 ? initialUserSubscriptions : optimisticUserSubscriptions;
10265
+ React5.useEffect(() => {
10266
+ if (initialUserSubscriptions?.length) {
10267
+ setOptimisticUserSubscriptions([]);
10268
+ }
10269
+ }, [initialUserSubscriptions]);
9939
10270
  const tokenPrice = saleData?.tokenPrice ?? 250;
9940
10271
  const feeRate = (saleData?.feePercent ?? 0.5) / 100;
9941
10272
  const totalSold = saleData?.totalSold ?? 0;
@@ -9958,11 +10289,13 @@ function PropertyBuy({
9958
10289
  setAvailableBalance(walletUsdcBalance);
9959
10290
  }
9960
10291
  }, [walletUsdcBalance]);
9961
- const handleOrderButtonClick = () => {
9962
- if (!isAuthenticated) {
9963
- onSignIn();
9964
- return;
10292
+ React5.useEffect(() => {
10293
+ if (walletPropertyTokenBalance != null) {
10294
+ setOwnedTokens(walletPropertyTokenBalance);
10295
+ setDisplayedOwnedTokens(walletPropertyTokenBalance);
9965
10296
  }
10297
+ }, [walletPropertyTokenBalance]);
10298
+ const handleOrderButtonClick = () => {
9966
10299
  if (!ipoStarted || tokenQuantity === 0) {
9967
10300
  return;
9968
10301
  }
@@ -10007,15 +10340,17 @@ function PropertyBuy({
10007
10340
  setOwnedTokensJustUpdated(true);
10008
10341
  setLastOrderQuantity(tokenAmountInt);
10009
10342
  setTimeout(() => setOwnedTokensJustUpdated(false), 2e3);
10010
- setUserSubscription({
10343
+ const optimisticEntry = {
10011
10344
  propertyName,
10012
- tokenSymbol: "MUS",
10345
+ tokenSymbol,
10013
10346
  tokens: tokenAmountInt,
10014
10347
  value: orderTotal,
10015
10348
  avgPrice: tokenPrice,
10016
10349
  percentOfProperty: estExposure,
10017
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
10018
- });
10350
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10351
+ status: "pending"
10352
+ };
10353
+ setOptimisticUserSubscriptions((prev) => [optimisticEntry, ...prev]);
10019
10354
  setLastOrderDetails({
10020
10355
  tokens: tokenAmountInt,
10021
10356
  total: orderTotal,
@@ -10077,36 +10412,43 @@ function PropertyBuy({
10077
10412
  }
10078
10413
  ),
10079
10414
  /* @__PURE__ */ jsxRuntime.jsx(VideoActivitySection, { ipoStarted }),
10080
- /* @__PURE__ */ jsxRuntime.jsx(
10081
- OrderPanel,
10082
- {
10083
- statusLabel,
10084
- statusColor,
10085
- ipoStarted,
10086
- isAuthenticated,
10087
- tokenPrice,
10088
- feeRate,
10089
- supplyToSell,
10090
- availableBalance,
10091
- displayedOwnedTokens,
10092
- ownedTokensJustUpdated,
10093
- lastOrderQuantity,
10094
- orderPlacedSuccess,
10095
- lastOrderDetails,
10096
- tokenQuantity,
10097
- feeInTokens,
10098
- orderTotal,
10099
- sliderValue,
10100
- manualOrderAmount,
10101
- setSliderValue,
10102
- setManualOrderAmount,
10103
- onOrderButtonClick: handleOrderButtonClick,
10104
- orderButtonText: getOrderButtonText(),
10105
- isOrderButtonDisabled: isOrderButtonDisabled(),
10106
- hasInsufficientFunds,
10107
- onPlaceAnotherOrder: () => setOrderPlacedSuccess(false)
10108
- }
10109
- )
10415
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexDirection: "column" }, children: [
10416
+ /* @__PURE__ */ jsxRuntime.jsx(
10417
+ OrderPanel,
10418
+ {
10419
+ statusLabel,
10420
+ statusColor,
10421
+ ipoStarted,
10422
+ tokenDisplayName,
10423
+ tokenSymbol,
10424
+ isAuthenticated,
10425
+ tokenPrice,
10426
+ feeRate,
10427
+ supplyToSell,
10428
+ availableBalance,
10429
+ displayedOwnedTokens,
10430
+ ownedTokensJustUpdated,
10431
+ lastOrderQuantity,
10432
+ orderPlacedSuccess,
10433
+ lastOrderDetails,
10434
+ tokenQuantity,
10435
+ feeInTokens,
10436
+ orderTotal,
10437
+ sliderValue,
10438
+ manualOrderAmount,
10439
+ setSliderValue,
10440
+ setManualOrderAmount,
10441
+ onSignInClick: onSignIn,
10442
+ onOrderButtonClick: handleOrderButtonClick,
10443
+ orderButtonText: getOrderButtonText(),
10444
+ isOrderButtonDisabled: isOrderButtonDisabled(),
10445
+ hasInsufficientFunds,
10446
+ onPlaceAnotherOrder: () => setOrderPlacedSuccess(false),
10447
+ onDeposit
10448
+ }
10449
+ ),
10450
+ 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 })
10451
+ ] })
10110
10452
  ] }),
10111
10453
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-6", children: [
10112
10454
  /* @__PURE__ */ jsxRuntime.jsx(GalleryMapSection, { propertyLocation: propertyLocationLabel }),
@@ -10114,7 +10456,7 @@ function PropertyBuy({
10114
10456
  NewsOrdersSection,
10115
10457
  {
10116
10458
  newsItems,
10117
- userSubscription,
10459
+ userSubscriptions: resolvedUserSubscriptions,
10118
10460
  tokenPrice
10119
10461
  }
10120
10462
  )
@@ -12469,6 +12811,191 @@ function GalleryContent({ galleryImages, startIndex, title, subtitle, onClose })
12469
12811
  }
12470
12812
  );
12471
12813
  }
12814
+ var slideIn = styled23.keyframes`
12815
+ from { transform: translateX(110%); opacity: 0; }
12816
+ to { transform: translateX(0); opacity: 1; }
12817
+ `;
12818
+ var slideOut = styled23.keyframes`
12819
+ from { transform: translateX(0); opacity: 1; }
12820
+ to { transform: translateX(110%); opacity: 0; }
12821
+ `;
12822
+ var progressShrink = styled23.keyframes`
12823
+ from { width: 100%; }
12824
+ to { width: 0%; }
12825
+ `;
12826
+ var VARIANT_COLORS = {
12827
+ success: { accent: "#0ecb81", icon: "\u2713" },
12828
+ error: { accent: "#f6465d", icon: "\u2715" },
12829
+ info: { accent: "#E6C656", icon: "\u2139" },
12830
+ pending: { accent: "#7EB3E6", icon: "\u25CC" }
12831
+ };
12832
+ var Wrapper = styled23__default.default.div`
12833
+ position: relative;
12834
+ display: flex;
12835
+ flex-direction: column;
12836
+ gap: 0;
12837
+ width: 340px;
12838
+ background: #0d0f1a;
12839
+ border: 1px solid rgba(255, 255, 255, 0.08);
12840
+ border-radius: 10px;
12841
+ overflow: hidden;
12842
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255,255,255,0.04);
12843
+ 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`};
12844
+ pointer-events: all;
12845
+ `;
12846
+ var Body = styled23__default.default.div`
12847
+ display: flex;
12848
+ align-items: flex-start;
12849
+ gap: 12px;
12850
+ padding: 14px 16px 12px;
12851
+ `;
12852
+ var IconDot = styled23__default.default.div`
12853
+ flex-shrink: 0;
12854
+ width: 28px;
12855
+ height: 28px;
12856
+ border-radius: 50%;
12857
+ background: ${({ $color }) => $color}1a;
12858
+ border: 1px solid ${({ $color }) => $color}55;
12859
+ display: flex;
12860
+ align-items: center;
12861
+ justify-content: center;
12862
+ font-size: 0.75rem;
12863
+ font-weight: 700;
12864
+ color: ${({ $color }) => $color};
12865
+ margin-top: 1px;
12866
+ `;
12867
+ var Content = styled23__default.default.div`
12868
+ flex: 1;
12869
+ min-width: 0;
12870
+ `;
12871
+ var Title2 = styled23__default.default.p`
12872
+ margin: 0 0 2px;
12873
+ font-size: 0.8rem;
12874
+ font-weight: 600;
12875
+ color: #fff;
12876
+ letter-spacing: 0.01em;
12877
+ `;
12878
+ var Amount = styled23__default.default.p`
12879
+ margin: 0 0 6px;
12880
+ font-size: 1.05rem;
12881
+ font-weight: 700;
12882
+ color: #E6C656;
12883
+ letter-spacing: -0.01em;
12884
+ `;
12885
+ var TxRow = styled23__default.default.a`
12886
+ display: inline-flex;
12887
+ align-items: center;
12888
+ gap: 5px;
12889
+ font-family: 'IBM Plex Mono', 'Space Mono', monospace;
12890
+ font-size: 0.68rem;
12891
+ color: rgba(255, 255, 255, 0.4);
12892
+ text-decoration: none;
12893
+ transition: color 0.15s;
12894
+ &:hover {
12895
+ color: #7EB3E6;
12896
+ }
12897
+ `;
12898
+ var TxArrow = styled23__default.default.span`
12899
+ font-size: 0.6rem;
12900
+ opacity: 0.6;
12901
+ `;
12902
+ var CloseBtn = styled23__default.default.button`
12903
+ flex-shrink: 0;
12904
+ background: none;
12905
+ border: none;
12906
+ padding: 2px 4px;
12907
+ cursor: pointer;
12908
+ color: rgba(255, 255, 255, 0.25);
12909
+ font-size: 0.9rem;
12910
+ line-height: 1;
12911
+ transition: color 0.15s;
12912
+ &:hover { color: rgba(255, 255, 255, 0.7); }
12913
+ `;
12914
+ var ProgressBar2 = styled23__default.default.div`
12915
+ height: 2px;
12916
+ background: rgba(255, 255, 255, 0.06);
12917
+ position: relative;
12918
+ &::after {
12919
+ content: '';
12920
+ position: absolute;
12921
+ left: 0;
12922
+ top: 0;
12923
+ height: 100%;
12924
+ background: ${({ $color }) => $color};
12925
+ animation: ${styled23.css`${progressShrink} ${({ $duration }) => $duration}ms linear forwards`};
12926
+ }
12927
+ `;
12928
+ var Container2 = styled23__default.default.div`
12929
+ position: fixed;
12930
+ bottom: 24px;
12931
+ right: 24px;
12932
+ z-index: 9999;
12933
+ display: flex;
12934
+ flex-direction: column-reverse;
12935
+ gap: 10px;
12936
+ pointer-events: none;
12937
+ `;
12938
+ var DEFAULT_EXPLORER = "https://sepolia.basescan.org/tx/";
12939
+ function truncateHash(hash) {
12940
+ return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
12941
+ }
12942
+ function ToastItem({ toast, onDismiss }) {
12943
+ const [exiting, setExiting] = React5.useState(false);
12944
+ const timerRef = React5.useRef(null);
12945
+ const dismiss = React5.useCallback(() => {
12946
+ setExiting(true);
12947
+ setTimeout(() => onDismiss(toast.id), 280);
12948
+ }, [onDismiss, toast.id]);
12949
+ React5.useEffect(() => {
12950
+ const duration2 = toast.duration ?? 6e3;
12951
+ if (duration2 > 0) {
12952
+ timerRef.current = setTimeout(dismiss, duration2);
12953
+ }
12954
+ return () => {
12955
+ if (timerRef.current) clearTimeout(timerRef.current);
12956
+ };
12957
+ }, [dismiss, toast.duration]);
12958
+ const { accent, icon } = VARIANT_COLORS[toast.variant];
12959
+ const duration = toast.duration ?? 6e3;
12960
+ const explorerBase = toast.explorerUrl ?? DEFAULT_EXPLORER;
12961
+ const txUrl = toast.txHash ? `${explorerBase}${toast.txHash}` : void 0;
12962
+ return /* @__PURE__ */ jsxRuntime.jsxs(Wrapper, { $exiting: exiting, children: [
12963
+ /* @__PURE__ */ jsxRuntime.jsxs(Body, { children: [
12964
+ /* @__PURE__ */ jsxRuntime.jsx(IconDot, { $color: accent, children: icon }),
12965
+ /* @__PURE__ */ jsxRuntime.jsxs(Content, { children: [
12966
+ /* @__PURE__ */ jsxRuntime.jsx(Title2, { children: toast.title }),
12967
+ toast.amount && /* @__PURE__ */ jsxRuntime.jsx(Amount, { children: toast.amount }),
12968
+ toast.txHash && txUrl && /* @__PURE__ */ jsxRuntime.jsxs(TxRow, { href: txUrl, target: "_blank", rel: "noopener noreferrer", children: [
12969
+ truncateHash(toast.txHash),
12970
+ /* @__PURE__ */ jsxRuntime.jsx(TxArrow, { children: "\u2197" })
12971
+ ] })
12972
+ ] }),
12973
+ /* @__PURE__ */ jsxRuntime.jsx(CloseBtn, { type: "button", onClick: dismiss, "aria-label": "Dismiss", children: "\u2715" })
12974
+ ] }),
12975
+ duration > 0 && /* @__PURE__ */ jsxRuntime.jsx(ProgressBar2, { $color: accent, $duration: duration })
12976
+ ] });
12977
+ }
12978
+ var ToastContext = React5.createContext(null);
12979
+ function ToastProvider({ children }) {
12980
+ const [toasts, setToasts] = React5.useState([]);
12981
+ const addToast = React5.useCallback((data) => {
12982
+ const id = `toast-${Date.now()}-${Math.random().toString(36).slice(2, 7)}`;
12983
+ setToasts((prev) => [...prev, { ...data, id }]);
12984
+ return id;
12985
+ }, []);
12986
+ const dismiss = React5.useCallback((id) => {
12987
+ setToasts((prev) => prev.filter((t) => t.id !== id));
12988
+ }, []);
12989
+ return /* @__PURE__ */ jsxRuntime.jsxs(ToastContext.Provider, { value: { toast: addToast, dismiss }, children: [
12990
+ children,
12991
+ /* @__PURE__ */ jsxRuntime.jsx(Container2, { children: toasts.map((t) => /* @__PURE__ */ jsxRuntime.jsx(ToastItem, { toast: t, onDismiss: dismiss }, t.id)) })
12992
+ ] });
12993
+ }
12994
+ function useToast() {
12995
+ const ctx = React5.useContext(ToastContext);
12996
+ if (!ctx) throw new Error("useToast must be used within a ToastProvider");
12997
+ return ctx;
12998
+ }
12472
12999
 
12473
13000
  exports.Badge = Badge;
12474
13001
  exports.Button = Button;
@@ -12503,10 +13030,12 @@ exports.PropertyPhotoGallery = PropertyPhotoGallery;
12503
13030
  exports.PropertySubheader = PropertySubheader;
12504
13031
  exports.PropertyTour = PropertyTour;
12505
13032
  exports.PropertyValuation = PropertyValuation;
13033
+ exports.ToastProvider = ToastProvider;
12506
13034
  exports.TradeConfirmationModal = TradeConfirmationModal;
12507
13035
  exports.TradingSlider = TradingSlider;
12508
13036
  exports.YourOrders = YourOrders;
12509
13037
  exports.badgeVariants = badgeVariants;
12510
13038
  exports.buttonVariants = buttonVariants;
13039
+ exports.useToast = useToast;
12511
13040
  //# sourceMappingURL=index.js.map
12512
13041
  //# sourceMappingURL=index.js.map