@burdenoff/microfe-housingvista 2026.703.4 → 2026.703.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/dist/housingvista/HousingVistaRoutes.js.map +1 -1
  2. package/dist/housingvista/components/Breadcrumbs.js.map +1 -1
  3. package/dist/housingvista/components/ContactOwnerDialog.js +21 -19
  4. package/dist/housingvista/components/ContactOwnerDialog.js.map +1 -1
  5. package/dist/housingvista/components/ReviewsSection.js.map +1 -1
  6. package/dist/housingvista/hooks/index.js +4 -1
  7. package/dist/housingvista/hooks/index.js.map +1 -1
  8. package/dist/housingvista/pages/amc/AMCManagementPage.js.map +1 -1
  9. package/dist/housingvista/pages/analytics/AnalyticsPage.js.map +1 -1
  10. package/dist/housingvista/pages/assets/AssetDetailPage.js.map +1 -1
  11. package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
  12. package/dist/housingvista/pages/finance/HomeLoanDetailPage.js.map +1 -1
  13. package/dist/housingvista/pages/investments/InvestmentDetailPage.js.map +1 -1
  14. package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
  15. package/dist/housingvista/pages/legal/LegalServiceDetailPage.js.map +1 -1
  16. package/dist/housingvista/pages/marketplace/MarketplacePage.js.map +1 -1
  17. package/dist/housingvista/pages/marketplace/ServiceDetailPage.js.map +1 -1
  18. package/dist/housingvista/pages/offers/OffersPage.js.map +1 -1
  19. package/dist/housingvista/pages/rental/RentalManagementPage.js.map +1 -1
  20. package/dist/housingvista/pages/settings/ProfilePage.js.map +1 -1
  21. package/dist/housingvista/pages/settings/SettingsPage.js.map +1 -1
  22. package/dist/housingvista/pages/transactions/TransactionDetailPage.js.map +1 -1
  23. package/dist/housingvista/pages/verification/VerificationDetailPage.js.map +1 -1
  24. package/dist/housingvista/pages/viewings/ViewingsPage.js.map +1 -1
  25. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"HousingVistaRoutes.js","names":[],"sources":["../../src/housingvista/HousingVistaRoutes.tsx"],"sourcesContent":["/**\n * HousingVista Routes\n * All route definitions with lazy loading.\n * @module housingvista\n */\n\nimport { lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\n\n// Eagerly load the home page\nimport { HomePage } from './pages/HomePage';\n\n// Loading fallback\nconst PageLoader = () => (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"text-sm text-text-secondary\">Loading...</div>\n </div>\n);\n\n// ── Properties ──────────────────────────────────────────────────────────────\nconst PropertiesPage = lazy(() =>\n import('./pages/properties/PropertiesPage').then((m) => ({ default: m.PropertiesPage }))\n);\nconst AddPropertyPage = lazy(() =>\n import('./pages/properties/AddPropertyPage').then((m) => ({ default: m.AddPropertyPage }))\n);\nconst PropertyDetailPage = lazy(() =>\n import('./pages/properties/PropertyDetailPage').then((m) => ({ default: m.PropertyDetailPage }))\n);\nconst ShortlistPage = lazy(() => import('./pages/shortlist/ShortlistPage').then((m) => ({ default: m.ShortlistPage })));\n\n// ── Transactions ────────────────────────────────────────────────────────────\nconst TransactionsPage = lazy(() =>\n import('./pages/transactions/TransactionsPage').then((m) => ({ default: m.TransactionsPage }))\n);\nconst TransactionDetailPage = lazy(() =>\n import('./pages/transactions/TransactionDetailPage').then((m) => ({ default: m.TransactionDetailPage }))\n);\n\n// ── Investments ─────────────────────────────────────────────────────────────\nconst InvestmentsPage = lazy(() =>\n import('./pages/investments/InvestmentsPage').then((m) => ({ default: m.InvestmentsPage }))\n);\nconst InvestmentDetailPage = lazy(() =>\n import('./pages/investments/InvestmentDetailPage').then((m) => ({ default: m.InvestmentDetailPage }))\n);\n\n// ── Offers ──────────────────────────────────────────────────────────────────\nconst OffersPage = lazy(() => import('./pages/offers/OffersPage').then((m) => ({ default: m.OffersPage })));\n\n// ── Viewings ────────────────────────────────────────────────────────────────\nconst ViewingsPage = lazy(() =>\n import('./pages/viewings/ViewingsPage').then((m) => ({ default: m.ViewingsPage }))\n);\n\n// ── Analytics ───────────────────────────────────────────────────────────────\nconst AnalyticsPage = lazy(() => import('./pages/analytics/AnalyticsPage').then((m) => ({ default: m.AnalyticsPage })));\n\n// ── Rental Management ───────────────────────────────────────────────────────\nconst RentalManagementPage = lazy(() =>\n import('./pages/rental/RentalManagementPage').then((m) => ({ default: m.RentalManagementPage }))\n);\n\n// ── Asset Management ────────────────────────────────────────────────────────\nconst AssetManagementPage = lazy(() =>\n import('./pages/assets/AssetManagementPage').then((m) => ({ default: m.AssetManagementPage }))\n);\nconst AssetDetailPage = lazy(() =>\n import('./pages/assets/AssetDetailPage').then((m) => ({ default: m.AssetDetailPage }))\n);\n\n// ── AMC Management ──────────────────────────────────────────────────────────\nconst AMCManagementPage = lazy(() =>\n import('./pages/amc/AMCManagementPage').then((m) => ({ default: m.AMCManagementPage }))\n);\n\n// ── Marketplace ─────────────────────────────────────────────────────────────\nconst MarketplacePage = lazy(() =>\n import('./pages/marketplace/MarketplacePage').then((m) => ({ default: m.MarketplacePage }))\n);\nconst ServiceDetailPage = lazy(() =>\n import('./pages/marketplace/ServiceDetailPage').then((m) => ({ default: m.ServiceDetailPage }))\n);\n\n// ── Verification ────────────────────────────────────────────────────────────\nconst VerificationPage = lazy(() =>\n import('./pages/verification/VerificationPage').then((m) => ({ default: m.VerificationPage }))\n);\nconst VerificationDetailPage = lazy(() =>\n import('./pages/verification/VerificationDetailPage').then((m) => ({ default: m.VerificationDetailPage }))\n);\n\n// ── Legal ───────────────────────────────────────────────────────────────────\nconst LegalPage = lazy(() => import('./pages/legal/LegalPage').then((m) => ({ default: m.LegalPage })));\nconst LegalServiceDetailPage = lazy(() =>\n import('./pages/legal/LegalServiceDetailPage').then((m) => ({ default: m.LegalServiceDetailPage }))\n);\n\n// ── Finance ─────────────────────────────────────────────────────────────────\nconst HomeLoansPage = lazy(() => import('./pages/finance/HomeLoansPage').then((m) => ({ default: m.HomeLoansPage })));\nconst HomeLoanDetailPage = lazy(() =>\n import('./pages/finance/HomeLoanDetailPage').then((m) => ({ default: m.HomeLoanDetailPage }))\n);\n\n// ── Market ──────────────────────────────────────────────────────────────────\nconst MarketAnalyticsPage = lazy(() =>\n import('./pages/market/MarketAnalyticsPage').then((m) => ({ default: m.MarketAnalyticsPage }))\n);\nconst AreaInsightsPage = lazy(() =>\n import('./pages/market/AreaInsightsPage').then((m) => ({ default: m.AreaInsightsPage }))\n);\n\n// ── Settings ────────────────────────────────────────────────────────────────\nconst SettingsPage = lazy(() => import('./pages/settings/SettingsPage').then((m) => ({ default: m.SettingsPage })));\nconst ProfilePage = lazy(() => import('./pages/settings/ProfilePage').then((m) => ({ default: m.ProfilePage })));\n\n// ============================================================================\n// Routes\n// ============================================================================\n\nexport function HousingVistaRoutes() {\n return (\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Dashboard */}\n <Route index element={<HomePage />} />\n\n {/* Properties */}\n <Route path=\"properties\" element={<PropertiesPage />} />\n <Route path=\"properties/new\" element={<AddPropertyPage />} />\n <Route path=\"properties/:id\" element={<PropertyDetailPage />} />\n\n {/* Shortlist */}\n <Route path=\"shortlist\" element={<ShortlistPage />} />\n\n {/* Transactions */}\n <Route path=\"transactions\" element={<TransactionsPage />} />\n <Route path=\"transactions/:id\" element={<TransactionDetailPage />} />\n\n {/* Investments */}\n <Route path=\"investments\" element={<InvestmentsPage />} />\n <Route path=\"investments/:id\" element={<InvestmentDetailPage />} />\n\n {/* Offers */}\n <Route path=\"offers\" element={<OffersPage />} />\n\n {/* Viewings */}\n <Route path=\"viewings\" element={<ViewingsPage />} />\n\n {/* Analytics */}\n <Route path=\"analytics\" element={<AnalyticsPage />} />\n\n {/* Rental Management */}\n <Route path=\"rental\" element={<RentalManagementPage />} />\n\n {/* Asset Management */}\n <Route path=\"assets\" element={<AssetManagementPage />} />\n <Route path=\"assets/:id\" element={<AssetDetailPage />} />\n\n {/* AMC Management */}\n <Route path=\"amc\" element={<AMCManagementPage />} />\n\n {/* Marketplace */}\n <Route path=\"marketplace\" element={<MarketplacePage />} />\n <Route path=\"marketplace/:id\" element={<ServiceDetailPage />} />\n\n {/* Verification */}\n <Route path=\"verification\" element={<VerificationPage />} />\n <Route path=\"verification/:id\" element={<VerificationDetailPage />} />\n\n {/* Legal */}\n <Route path=\"legal\" element={<LegalPage />} />\n <Route path=\"legal/:id\" element={<LegalServiceDetailPage />} />\n\n {/* Home Loans */}\n <Route path=\"home-loans\" element={<HomeLoansPage />} />\n <Route path=\"home-loans/:id/apply\" element={<HomeLoanDetailPage />} />\n\n {/* Market Analytics */}\n <Route path=\"market-analytics\" element={<MarketAnalyticsPage />} />\n <Route path=\"area-insights\" element={<AreaInsightsPage />} />\n\n {/* Settings & Profile */}\n <Route path=\"settings\" element={<SettingsPage />} />\n <Route path=\"profile\" element={<ProfilePage />} />\n\n {/* Catch-all: redirect to dashboard */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"HousingVistaRoutes.js","names":[],"sources":["../../src/housingvista/HousingVistaRoutes.tsx"],"sourcesContent":["/**\n * HousingVista Routes\n * All route definitions with lazy loading.\n * @module housingvista\n */\n\nimport { lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate } from 'react-router-dom';\n\n// Eagerly load the home page\nimport { HomePage } from './pages/HomePage';\n\n// Loading fallback\nconst PageLoader = () => (\n <div className=\"flex items-center justify-center p-12\">\n <div className=\"text-sm text-text-secondary\">Loading...</div>\n </div>\n);\n\n// ── Properties ──────────────────────────────────────────────────────────────\nconst PropertiesPage = lazy(() =>\n import('./pages/properties/PropertiesPage').then((m) => ({ default: m.PropertiesPage }))\n);\nconst AddPropertyPage = lazy(() =>\n import('./pages/properties/AddPropertyPage').then((m) => ({ default: m.AddPropertyPage }))\n);\nconst PropertyDetailPage = lazy(() =>\n import('./pages/properties/PropertyDetailPage').then((m) => ({ default: m.PropertyDetailPage }))\n);\nconst ShortlistPage = lazy(() => import('./pages/shortlist/ShortlistPage').then((m) => ({ default: m.ShortlistPage })));\n\n// ── Transactions ────────────────────────────────────────────────────────────\nconst TransactionsPage = lazy(() =>\n import('./pages/transactions/TransactionsPage').then((m) => ({ default: m.TransactionsPage }))\n);\nconst TransactionDetailPage = lazy(() =>\n import('./pages/transactions/TransactionDetailPage').then((m) => ({ default: m.TransactionDetailPage }))\n);\n\n// ── Investments ─────────────────────────────────────────────────────────────\nconst InvestmentsPage = lazy(() =>\n import('./pages/investments/InvestmentsPage').then((m) => ({ default: m.InvestmentsPage }))\n);\nconst InvestmentDetailPage = lazy(() =>\n import('./pages/investments/InvestmentDetailPage').then((m) => ({ default: m.InvestmentDetailPage }))\n);\n\n// ── Offers ──────────────────────────────────────────────────────────────────\nconst OffersPage = lazy(() => import('./pages/offers/OffersPage').then((m) => ({ default: m.OffersPage })));\n\n// ── Viewings ────────────────────────────────────────────────────────────────\nconst ViewingsPage = lazy(() => import('./pages/viewings/ViewingsPage').then((m) => ({ default: m.ViewingsPage })));\n\n// ── Analytics ───────────────────────────────────────────────────────────────\nconst AnalyticsPage = lazy(() => import('./pages/analytics/AnalyticsPage').then((m) => ({ default: m.AnalyticsPage })));\n\n// ── Rental Management ───────────────────────────────────────────────────────\nconst RentalManagementPage = lazy(() =>\n import('./pages/rental/RentalManagementPage').then((m) => ({ default: m.RentalManagementPage }))\n);\n\n// ── Asset Management ────────────────────────────────────────────────────────\nconst AssetManagementPage = lazy(() =>\n import('./pages/assets/AssetManagementPage').then((m) => ({ default: m.AssetManagementPage }))\n);\nconst AssetDetailPage = lazy(() =>\n import('./pages/assets/AssetDetailPage').then((m) => ({ default: m.AssetDetailPage }))\n);\n\n// ── AMC Management ──────────────────────────────────────────────────────────\nconst AMCManagementPage = lazy(() =>\n import('./pages/amc/AMCManagementPage').then((m) => ({ default: m.AMCManagementPage }))\n);\n\n// ── Marketplace ─────────────────────────────────────────────────────────────\nconst MarketplacePage = lazy(() =>\n import('./pages/marketplace/MarketplacePage').then((m) => ({ default: m.MarketplacePage }))\n);\nconst ServiceDetailPage = lazy(() =>\n import('./pages/marketplace/ServiceDetailPage').then((m) => ({ default: m.ServiceDetailPage }))\n);\n\n// ── Verification ────────────────────────────────────────────────────────────\nconst VerificationPage = lazy(() =>\n import('./pages/verification/VerificationPage').then((m) => ({ default: m.VerificationPage }))\n);\nconst VerificationDetailPage = lazy(() =>\n import('./pages/verification/VerificationDetailPage').then((m) => ({ default: m.VerificationDetailPage }))\n);\n\n// ── Legal ───────────────────────────────────────────────────────────────────\nconst LegalPage = lazy(() => import('./pages/legal/LegalPage').then((m) => ({ default: m.LegalPage })));\nconst LegalServiceDetailPage = lazy(() =>\n import('./pages/legal/LegalServiceDetailPage').then((m) => ({ default: m.LegalServiceDetailPage }))\n);\n\n// ── Finance ─────────────────────────────────────────────────────────────────\nconst HomeLoansPage = lazy(() => import('./pages/finance/HomeLoansPage').then((m) => ({ default: m.HomeLoansPage })));\nconst HomeLoanDetailPage = lazy(() =>\n import('./pages/finance/HomeLoanDetailPage').then((m) => ({ default: m.HomeLoanDetailPage }))\n);\n\n// ── Market ──────────────────────────────────────────────────────────────────\nconst MarketAnalyticsPage = lazy(() =>\n import('./pages/market/MarketAnalyticsPage').then((m) => ({ default: m.MarketAnalyticsPage }))\n);\nconst AreaInsightsPage = lazy(() =>\n import('./pages/market/AreaInsightsPage').then((m) => ({ default: m.AreaInsightsPage }))\n);\n\n// ── Settings ────────────────────────────────────────────────────────────────\nconst SettingsPage = lazy(() => import('./pages/settings/SettingsPage').then((m) => ({ default: m.SettingsPage })));\nconst ProfilePage = lazy(() => import('./pages/settings/ProfilePage').then((m) => ({ default: m.ProfilePage })));\n\n// ============================================================================\n// Routes\n// ============================================================================\n\nexport function HousingVistaRoutes() {\n return (\n <Suspense fallback={<PageLoader />}>\n <Routes>\n {/* Dashboard */}\n <Route index element={<HomePage />} />\n\n {/* Properties */}\n <Route path=\"properties\" element={<PropertiesPage />} />\n <Route path=\"properties/new\" element={<AddPropertyPage />} />\n <Route path=\"properties/:id\" element={<PropertyDetailPage />} />\n\n {/* Shortlist */}\n <Route path=\"shortlist\" element={<ShortlistPage />} />\n\n {/* Transactions */}\n <Route path=\"transactions\" element={<TransactionsPage />} />\n <Route path=\"transactions/:id\" element={<TransactionDetailPage />} />\n\n {/* Investments */}\n <Route path=\"investments\" element={<InvestmentsPage />} />\n <Route path=\"investments/:id\" element={<InvestmentDetailPage />} />\n\n {/* Offers */}\n <Route path=\"offers\" element={<OffersPage />} />\n\n {/* Viewings */}\n <Route path=\"viewings\" element={<ViewingsPage />} />\n\n {/* Analytics */}\n <Route path=\"analytics\" element={<AnalyticsPage />} />\n\n {/* Rental Management */}\n <Route path=\"rental\" element={<RentalManagementPage />} />\n\n {/* Asset Management */}\n <Route path=\"assets\" element={<AssetManagementPage />} />\n <Route path=\"assets/:id\" element={<AssetDetailPage />} />\n\n {/* AMC Management */}\n <Route path=\"amc\" element={<AMCManagementPage />} />\n\n {/* Marketplace */}\n <Route path=\"marketplace\" element={<MarketplacePage />} />\n <Route path=\"marketplace/:id\" element={<ServiceDetailPage />} />\n\n {/* Verification */}\n <Route path=\"verification\" element={<VerificationPage />} />\n <Route path=\"verification/:id\" element={<VerificationDetailPage />} />\n\n {/* Legal */}\n <Route path=\"legal\" element={<LegalPage />} />\n <Route path=\"legal/:id\" element={<LegalServiceDetailPage />} />\n\n {/* Home Loans */}\n <Route path=\"home-loans\" element={<HomeLoansPage />} />\n <Route path=\"home-loans/:id/apply\" element={<HomeLoanDetailPage />} />\n\n {/* Market Analytics */}\n <Route path=\"market-analytics\" element={<MarketAnalyticsPage />} />\n <Route path=\"area-insights\" element={<AreaInsightsPage />} />\n\n {/* Settings & Profile */}\n <Route path=\"settings\" element={<SettingsPage />} />\n <Route path=\"profile\" element={<ProfilePage />} />\n\n {/* Catch-all: redirect to dashboard */}\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Breadcrumbs.js","names":[],"sources":["../../../src/housingvista/components/Breadcrumbs.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { ChevronRight, Home } from 'lucide-react';\nimport { Link } from 'react-router-dom';\nimport { cn } from '../utils/helpers';\nimport { useHousingVista } from '../context/HousingVistaContext';\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n}\n\ninterface BreadcrumbsProps {\n items: BreadcrumbItem[];\n className?: string;\n}\n\nexport const Breadcrumbs: FC<BreadcrumbsProps> = ({ items, className }) => {\n // The Home crumb must land on the HousingVista dashboard root regardless of\n // how deep the current route is nested, so link to the absolute mount path.\n const { basePath } = useHousingVista();\n const homeHref = basePath && basePath !== '/' ? basePath : '/';\n return (\n <nav aria-label=\"Breadcrumb\" className={cn('flex items-center gap-1 text-sm', className)}>\n <Link to={homeHref} className=\"flex items-center text-text-secondary hover:text-text-primary\" aria-label=\"Dashboard\">\n <Home className=\"h-3.5 w-3.5\" />\n </Link>\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n return (\n <span key={item.label} className=\"flex items-center gap-1\">\n <ChevronRight className=\"h-3.5 w-3.5 text-text-secondary/50\" />\n {isLast || !item.href ? (\n <span className={cn(isLast ? 'font-medium text-text-primary' : 'text-text-secondary')}>{item.label}</span>\n ) : (\n <Link to={item.href} className=\"text-text-secondary hover:text-text-primary\">\n {item.label}\n </Link>\n )}\n </span>\n );\n })}\n </nav>\n );\n};\n"],"mappings":";;;;;;AAgBA,IAAa,KAAqC,EAAE,UAAO,mBAAgB;CAGzE,IAAM,EAAE,gBAAa,GAAiB,EAChC,IAAW,KAAY,MAAa,MAAM,IAAW;AAC3D,QACE,kBAAC,OAAD;EAAK,cAAW;EAAa,WAAW,EAAG,mCAAmC,EAAU;YAAxF,CACE,kBAAC,GAAD;GAAM,IAAI;GAAU,WAAU;GAAgE,cAAW;aACvG,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA;GAC3B,CAAA,EACN,EAAM,KAAK,GAAM,MAAU;GAC1B,IAAM,IAAS,MAAU,EAAM,SAAS;AACxC,UACE,kBAAC,QAAD;IAAuB,WAAU;cAAjC,CACE,kBAAC,GAAD,EAAc,WAAU,sCAAuC,CAAA,EAC9D,KAAU,CAAC,EAAK,OACf,kBAAC,QAAD;KAAM,WAAW,EAAG,IAAS,kCAAkC,sBAAsB;eAAG,EAAK;KAAa,CAAA,GAE1G,kBAAC,GAAD;KAAM,IAAI,EAAK;KAAM,WAAU;eAC5B,EAAK;KACD,CAAA,CAEJ;MATI,EAAK,MAST;IAET,CACE"}
1
+ {"version":3,"file":"Breadcrumbs.js","names":[],"sources":["../../../src/housingvista/components/Breadcrumbs.tsx"],"sourcesContent":["import type { FC } from 'react';\nimport { ChevronRight, Home } from 'lucide-react';\nimport { Link } from 'react-router-dom';\nimport { cn } from '../utils/helpers';\nimport { useHousingVista } from '../context/HousingVistaContext';\n\nexport interface BreadcrumbItem {\n label: string;\n href?: string;\n}\n\ninterface BreadcrumbsProps {\n items: BreadcrumbItem[];\n className?: string;\n}\n\nexport const Breadcrumbs: FC<BreadcrumbsProps> = ({ items, className }) => {\n // The Home crumb must land on the HousingVista dashboard root regardless of\n // how deep the current route is nested, so link to the absolute mount path.\n const { basePath } = useHousingVista();\n const homeHref = basePath && basePath !== '/' ? basePath : '/';\n return (\n <nav aria-label=\"Breadcrumb\" className={cn('flex items-center gap-1 text-sm', className)}>\n <Link\n to={homeHref}\n className=\"flex items-center text-text-secondary hover:text-text-primary\"\n aria-label=\"Dashboard\"\n >\n <Home className=\"h-3.5 w-3.5\" />\n </Link>\n {items.map((item, index) => {\n const isLast = index === items.length - 1;\n return (\n <span key={item.label} className=\"flex items-center gap-1\">\n <ChevronRight className=\"h-3.5 w-3.5 text-text-secondary/50\" />\n {isLast || !item.href ? (\n <span className={cn(isLast ? 'font-medium text-text-primary' : 'text-text-secondary')}>{item.label}</span>\n ) : (\n <Link to={item.href} className=\"text-text-secondary hover:text-text-primary\">\n {item.label}\n </Link>\n )}\n </span>\n );\n })}\n </nav>\n );\n};\n"],"mappings":";;;;;;AAgBA,IAAa,KAAqC,EAAE,UAAO,mBAAgB;CAGzE,IAAM,EAAE,gBAAa,GAAiB,EAChC,IAAW,KAAY,MAAa,MAAM,IAAW;AAC3D,QACE,kBAAC,OAAD;EAAK,cAAW;EAAa,WAAW,EAAG,mCAAmC,EAAU;YAAxF,CACE,kBAAC,GAAD;GACE,IAAI;GACJ,WAAU;GACV,cAAW;aAEX,kBAAC,GAAD,EAAM,WAAU,eAAgB,CAAA;GAC3B,CAAA,EACN,EAAM,KAAK,GAAM,MAAU;GAC1B,IAAM,IAAS,MAAU,EAAM,SAAS;AACxC,UACE,kBAAC,QAAD;IAAuB,WAAU;cAAjC,CACE,kBAAC,GAAD,EAAc,WAAU,sCAAuC,CAAA,EAC9D,KAAU,CAAC,EAAK,OACf,kBAAC,QAAD;KAAM,WAAW,EAAG,IAAS,kCAAkC,sBAAsB;eAAG,EAAK;KAAa,CAAA,GAE1G,kBAAC,GAAD;KAAM,IAAI,EAAK;KAAM,WAAU;eAC5B,EAAK;KACD,CAAA,CAEJ;MATI,EAAK,MAST;IAET,CACE"}
@@ -5,8 +5,8 @@ import "../hooks/index.js";
5
5
  import { notify as a } from "../lib/toast.js";
6
6
  import { useEffect as o, useRef as s, useState as c } from "react";
7
7
  import { Send as l } from "lucide-react";
8
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
9
- import { Button as f, ResponsiveDialog as p, ResponsiveDialogContent as m, ResponsiveDialogDescription as h, ResponsiveDialogHeader as g, ResponsiveDialogTitle as _, ResponsiveDialogTrigger as v } from "@burdenoff/fe-libs/ui";
8
+ import { Fragment as u, jsx as d, jsxs as f } from "react/jsx-runtime";
9
+ import { Button as p, ResponsiveDialog as m, ResponsiveDialogContent as h, ResponsiveDialogDescription as g, ResponsiveDialogHeader as _, ResponsiveDialogTitle as v } from "@burdenoff/fe-libs/ui";
10
10
  //#region src/housingvista/components/ContactOwnerDialog.tsx
11
11
  var y = ({ entityId: y, entityType: b, title: x, pagePath: S, trigger: C, heading: w = "Contact", description: T }) => {
12
12
  let { currentUser: E } = e(), { openConversation: D, loading: O } = n(), { sendMessage: k, loading: A } = i(), [j, M] = c(!1), [N, P] = c(), [F, I] = c(""), { data: L, loading: R } = r(N), z = s(null);
@@ -43,39 +43,41 @@ var y = ({ entityId: y, entityType: b, title: x, pagePath: S, trigger: C, headin
43
43
  a.error("Message not sent", e.message);
44
44
  }
45
45
  }, V = E?.id ?? "";
46
- return /* @__PURE__ */ d(p, {
46
+ return /* @__PURE__ */ f(u, { children: [/* @__PURE__ */ d("span", {
47
+ className: "contents",
48
+ role: "presentation",
49
+ onClick: () => M(!0),
50
+ children: C
51
+ }), /* @__PURE__ */ d(m, {
47
52
  open: j,
48
53
  onOpenChange: M,
49
- children: [/* @__PURE__ */ u(v, {
50
- asChild: !0,
51
- children: C
52
- }), /* @__PURE__ */ d(m, {
54
+ children: /* @__PURE__ */ f(h, {
53
55
  className: "sm:max-w-lg",
54
56
  children: [
55
- /* @__PURE__ */ d(g, { children: [/* @__PURE__ */ u(_, { children: w }), /* @__PURE__ */ u(h, { children: T ?? `Start a conversation about ${x}. Messages are saved and delivered in your inbox.` })] }),
56
- /* @__PURE__ */ u("div", {
57
+ /* @__PURE__ */ f(_, { children: [/* @__PURE__ */ d(v, { children: w }), /* @__PURE__ */ d(g, { children: T ?? `Start a conversation about ${x}. Messages are saved and delivered in your inbox.` })] }),
58
+ /* @__PURE__ */ d("div", {
57
59
  ref: z,
58
60
  className: "max-h-72 min-h-40 space-y-2 overflow-y-auto rounded-md border border-border-subtle bg-bg-sunken p-3",
59
- children: O || R ? /* @__PURE__ */ u("p", {
61
+ children: O || R ? /* @__PURE__ */ d("p", {
60
62
  className: "py-8 text-center text-sm text-text-secondary",
61
63
  children: "Loading conversation…"
62
- }) : L.length === 0 ? /* @__PURE__ */ u("p", {
64
+ }) : L.length === 0 ? /* @__PURE__ */ d("p", {
63
65
  className: "py-8 text-center text-sm text-text-secondary",
64
66
  children: "No messages yet. Say hello to get the conversation started."
65
67
  }) : L.map((e) => {
66
68
  let n = e.authorId === V;
67
- return /* @__PURE__ */ u("div", {
69
+ return /* @__PURE__ */ d("div", {
68
70
  className: t("flex", n ? "justify-end" : "justify-start"),
69
- children: /* @__PURE__ */ u("div", {
71
+ children: /* @__PURE__ */ d("div", {
70
72
  className: t("max-w-[80%] rounded-lg px-3 py-2 text-sm", n ? "bg-action-primary-bg text-action-primary-text" : "bg-bg-surface text-text-primary border border-border-subtle"),
71
73
  children: e.text
72
74
  })
73
75
  }, e.id);
74
76
  })
75
77
  }),
76
- /* @__PURE__ */ d("div", {
78
+ /* @__PURE__ */ f("div", {
77
79
  className: "mt-3 flex items-end gap-2",
78
- children: [/* @__PURE__ */ u("textarea", {
80
+ children: [/* @__PURE__ */ d("textarea", {
79
81
  value: F,
80
82
  onChange: (e) => I(e.target.value),
81
83
  onKeyDown: (e) => {
@@ -84,19 +86,19 @@ var y = ({ entityId: y, entityType: b, title: x, pagePath: S, trigger: C, headin
84
86
  rows: 2,
85
87
  placeholder: "Write a message…",
86
88
  className: "min-h-10 flex-1 resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]"
87
- }), /* @__PURE__ */ d(f, {
89
+ }), /* @__PURE__ */ f(p, {
88
90
  type: "button",
89
91
  onClick: B,
90
92
  disabled: !F.trim() || !N || A,
91
- children: [/* @__PURE__ */ u(l, { className: "h-4 w-4" }), /* @__PURE__ */ u("span", {
93
+ children: [/* @__PURE__ */ d(l, { className: "h-4 w-4" }), /* @__PURE__ */ d("span", {
92
94
  className: "ml-1",
93
95
  children: "Send"
94
96
  })]
95
97
  })]
96
98
  })
97
99
  ]
98
- })]
99
- });
100
+ })
101
+ })] });
100
102
  };
101
103
  //#endregion
102
104
  export { y as ContactOwnerDialog };
@@ -1 +1 @@
1
- {"version":3,"file":"ContactOwnerDialog.js","names":[],"sources":["../../../src/housingvista/components/ContactOwnerDialog.tsx"],"sourcesContent":["/**\n * Real messaging surface backed by wspace-conversations-svc. Any \"Contact /\n * Message / Apply / Contact Owner\" CTA renders this: it resolves (get-or-create)\n * the entity's conversation, shows the persisted thread, and posts messages via\n * `sendMessage`. No stub, no dead-end — everything is persisted server-side.\n * @module housingvista\n */\n\nimport { useEffect, useRef, useState, type FC, type ReactNode } from 'react';\nimport { Send } from 'lucide-react';\nimport {\n Button,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogTrigger,\n} from '@burdenoff/fe-libs/ui';\nimport { useContactConversation, useConversationMessages, useSendMessage } from '../hooks';\nimport { useHousingVista } from '../context/HousingVistaContext';\nimport { notify } from '../lib/toast';\nimport { cn } from '../utils/helpers';\n\ninterface ContactOwnerDialogProps {\n /** Stable id of the thing being discussed (property/service/listing id). */\n entityId: string;\n /** e.g. `housingvista-property`, `housingvista-marketplace-service`. */\n entityType: string;\n /** Title used when the conversation is first created. */\n title: string;\n /** Router path back into this surface (deep link). */\n pagePath: string;\n /** Clickable trigger element (button/link). */\n trigger: ReactNode;\n /** Dialog heading, defaults to \"Contact\". */\n heading?: string;\n description?: string;\n}\n\nexport const ContactOwnerDialog: FC<ContactOwnerDialogProps> = ({\n entityId,\n entityType,\n title,\n pagePath,\n trigger,\n heading = 'Contact',\n description,\n}) => {\n const { currentUser } = useHousingVista();\n const { openConversation, loading: opening } = useContactConversation();\n const { sendMessage, loading: sending } = useSendMessage();\n const [open, setOpen] = useState(false);\n const [conversationId, setConversationId] = useState<string | undefined>();\n const [draft, setDraft] = useState('');\n const { data: messages, loading: loadingMessages } = useConversationMessages(conversationId);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resolve the conversation the first time the dialog opens.\n useEffect(() => {\n if (!open || conversationId) return;\n let cancelled = false;\n openConversation({\n entityId,\n entityType,\n title,\n contextHref: pagePath,\n pagePath,\n })\n .then((res) => {\n if (!cancelled) setConversationId(res.id);\n })\n .catch((err: Error) => notify.error('Could not open the conversation', err.message));\n return () => {\n cancelled = true;\n };\n }, [open, conversationId, openConversation, entityId, entityType, title, pagePath]);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });\n }, [messages]);\n\n const handleSend = async () => {\n const text = draft.trim();\n if (!text || !conversationId) return;\n try {\n await sendMessage(conversationId, text);\n setDraft('');\n } catch (err) {\n notify.error('Message not sent', (err as Error).message);\n }\n };\n\n const currentUserId = currentUser?.id ?? '';\n\n return (\n <ResponsiveDialog open={open} onOpenChange={setOpen}>\n <ResponsiveDialogTrigger asChild>{trigger}</ResponsiveDialogTrigger>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{heading}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {description ?? `Start a conversation about ${title}. Messages are saved and delivered in your inbox.`}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div\n ref={scrollRef}\n className=\"max-h-72 min-h-40 space-y-2 overflow-y-auto rounded-md border border-border-subtle bg-bg-sunken p-3\"\n >\n {opening || loadingMessages ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">Loading conversation…</p>\n ) : messages.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">\n No messages yet. Say hello to get the conversation started.\n </p>\n ) : (\n messages.map((message) => {\n const mine = message.authorId === currentUserId;\n return (\n <div key={message.id} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>\n <div\n className={cn(\n 'max-w-[80%] rounded-lg px-3 py-2 text-sm',\n mine\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary border border-border-subtle'\n )}\n >\n {message.text}\n </div>\n </div>\n );\n })\n )}\n </div>\n\n <div className=\"mt-3 flex items-end gap-2\">\n <textarea\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n void handleSend();\n }\n }}\n rows={2}\n placeholder=\"Write a message…\"\n className=\"min-h-10 flex-1 resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <Button type=\"button\" onClick={handleSend} disabled={!draft.trim() || !conversationId || sending}>\n <Send className=\"h-4 w-4\" />\n <span className=\"ml-1\">Send</span>\n </Button>\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n};\n"],"mappings":";;;;;;;;;;AAwCA,IAAa,KAAmD,EAC9D,aACA,eACA,UACA,aACA,YACA,aAAU,WACV,qBACI;CACJ,IAAM,EAAE,mBAAgB,GAAiB,EACnC,EAAE,qBAAkB,SAAS,MAAY,GAAwB,EACjE,EAAE,gBAAa,SAAS,MAAY,GAAgB,EACpD,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,CAAC,GAAgB,KAAqB,GAA8B,EACpE,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,EAAE,MAAM,GAAU,SAAS,MAAoB,EAAwB,EAAe,EACtF,IAAY,EAAuB,KAAK;AAsB9C,CAnBA,QAAgB;AACd,MAAI,CAAC,KAAQ,EAAgB;EAC7B,IAAI,IAAY;AAYhB,SAXA,EAAiB;GACf;GACA;GACA;GACA,aAAa;GACb;GACD,CAAC,CACC,MAAM,MAAQ;AACb,GAAK,KAAW,EAAkB,EAAI,GAAG;IACzC,CACD,OAAO,MAAe,EAAO,MAAM,mCAAmC,EAAI,QAAQ,CAAC,QACzE;AACX,OAAY;;IAEb;EAAC;EAAM;EAAgB;EAAkB;EAAU;EAAY;EAAO;EAAS,CAAC,EAEnF,QAAgB;AACd,IAAU,SAAS,SAAS,EAAE,KAAK,EAAU,QAAQ,cAAc,CAAC;IACnE,CAAC,EAAS,CAAC;CAEd,IAAM,IAAa,YAAY;EAC7B,IAAM,IAAO,EAAM,MAAM;AACrB,SAAC,KAAQ,CAAC,GACd,KAAI;AAEF,GADA,MAAM,EAAY,GAAgB,EAAK,EACvC,EAAS,GAAG;WACL,GAAK;AACZ,KAAO,MAAM,oBAAqB,EAAc,QAAQ;;IAItD,IAAgB,GAAa,MAAM;AAEzC,QACE,kBAAC,GAAD;EAAwB;EAAM,cAAc;YAA5C,CACE,kBAAC,GAAD;GAAyB,SAAA;aAAS;GAAkC,CAAA,EACpE,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAwB,GAAgC,CAAA,EACxD,kBAAC,GAAD,EAAA,UACG,KAAe,8BAA8B,EAAM,oDACxB,CAAA,CACP,EAAA,CAAA;IAEzB,kBAAC,OAAD;KACE,KAAK;KACL,WAAU;eAET,KAAW,IACV,kBAAC,KAAD;MAAG,WAAU;gBAA+C;MAAyB,CAAA,GACnF,EAAS,WAAW,IACtB,kBAAC,KAAD;MAAG,WAAU;gBAA+C;MAExD,CAAA,GAEJ,EAAS,KAAK,MAAY;MACxB,IAAM,IAAO,EAAQ,aAAa;AAClC,aACE,kBAAC,OAAD;OAAsB,WAAW,EAAG,QAAQ,IAAO,gBAAgB,gBAAgB;iBACjF,kBAAC,OAAD;QACE,WAAW,EACT,4CACA,IACI,kDACA,8DACL;kBAEA,EAAQ;QACL,CAAA;OACF,EAXI,EAAQ,GAWZ;OAER;KAEA,CAAA;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,YAAD;MACE,OAAO;MACP,WAAW,MAAU,EAAS,EAAM,OAAO,MAAM;MACjD,YAAY,MAAU;AACpB,OAAI,EAAM,QAAQ,WAAW,CAAC,EAAM,aAClC,EAAM,gBAAgB,EACjB,GAAY;;MAGrB,MAAM;MACN,aAAY;MACZ,WAAU;MACV,CAAA,EACF,kBAAC,GAAD;MAAQ,MAAK;MAAS,SAAS;MAAY,UAAU,CAAC,EAAM,MAAM,IAAI,CAAC,KAAkB;gBAAzF,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC5B,kBAAC,QAAD;OAAM,WAAU;iBAAO;OAAW,CAAA,CAC3B;QACL;;IACkB;KACT"}
1
+ {"version":3,"file":"ContactOwnerDialog.js","names":[],"sources":["../../../src/housingvista/components/ContactOwnerDialog.tsx"],"sourcesContent":["/**\n * Real messaging surface backed by wspace-conversations-svc. Any \"Contact /\n * Message / Apply / Contact Owner\" CTA renders this: it resolves (get-or-create)\n * the entity's conversation, shows the persisted thread, and posts messages via\n * `sendMessage`. No stub, no dead-end — everything is persisted server-side.\n * @module housingvista\n */\n\nimport { useEffect, useRef, useState, type FC, type ReactNode } from 'react';\nimport { Send } from 'lucide-react';\nimport {\n Button,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n} from '@burdenoff/fe-libs/ui';\nimport { useContactConversation, useConversationMessages, useSendMessage } from '../hooks';\nimport { useHousingVista } from '../context/HousingVistaContext';\nimport { notify } from '../lib/toast';\nimport { cn } from '../utils/helpers';\n\ninterface ContactOwnerDialogProps {\n /** Stable id of the thing being discussed (property/service/listing id). */\n entityId: string;\n /** e.g. `housingvista-property`, `housingvista-marketplace-service`. */\n entityType: string;\n /** Title used when the conversation is first created. */\n title: string;\n /** Router path back into this surface (deep link). */\n pagePath: string;\n /** Clickable trigger element (button/link). */\n trigger: ReactNode;\n /** Dialog heading, defaults to \"Contact\". */\n heading?: string;\n description?: string;\n}\n\nexport const ContactOwnerDialog: FC<ContactOwnerDialogProps> = ({\n entityId,\n entityType,\n title,\n pagePath,\n trigger,\n heading = 'Contact',\n description,\n}) => {\n const { currentUser } = useHousingVista();\n const { openConversation, loading: opening } = useContactConversation();\n const { sendMessage, loading: sending } = useSendMessage();\n const [open, setOpen] = useState(false);\n const [conversationId, setConversationId] = useState<string | undefined>();\n const [draft, setDraft] = useState('');\n const { data: messages, loading: loadingMessages } = useConversationMessages(conversationId);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resolve the conversation the first time the dialog opens.\n useEffect(() => {\n if (!open || conversationId) return;\n let cancelled = false;\n openConversation({\n entityId,\n entityType,\n title,\n contextHref: pagePath,\n pagePath,\n })\n .then((res) => {\n if (!cancelled) setConversationId(res.id);\n })\n .catch((err: Error) => notify.error('Could not open the conversation', err.message));\n return () => {\n cancelled = true;\n };\n }, [open, conversationId, openConversation, entityId, entityType, title, pagePath]);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight });\n }, [messages]);\n\n const handleSend = async () => {\n const text = draft.trim();\n if (!text || !conversationId) return;\n try {\n await sendMessage(conversationId, text);\n setDraft('');\n } catch (err) {\n notify.error('Message not sent', (err as Error).message);\n }\n };\n\n const currentUserId = currentUser?.id ?? '';\n\n // Render the caller's trigger inside a display:contents wrapper that opens the\n // dialog on click. A DOM-level onClick on the wrapper reliably catches the\n // bubbled click from the inner button — neither ResponsiveDialogTrigger's\n // asChild slot nor cloneElement forwarded the click through the fe-libs Button\n // in production.\n const openTrigger = (\n <span className=\"contents\" role=\"presentation\" onClick={() => setOpen(true)}>\n {trigger}\n </span>\n );\n\n return (\n <>\n {openTrigger}\n <ResponsiveDialog open={open} onOpenChange={setOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>{heading}</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {description ?? `Start a conversation about ${title}. Messages are saved and delivered in your inbox.`}\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div\n ref={scrollRef}\n className=\"max-h-72 min-h-40 space-y-2 overflow-y-auto rounded-md border border-border-subtle bg-bg-sunken p-3\"\n >\n {opening || loadingMessages ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">Loading conversation…</p>\n ) : messages.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-text-secondary\">\n No messages yet. Say hello to get the conversation started.\n </p>\n ) : (\n messages.map((message) => {\n const mine = message.authorId === currentUserId;\n return (\n <div key={message.id} className={cn('flex', mine ? 'justify-end' : 'justify-start')}>\n <div\n className={cn(\n 'max-w-[80%] rounded-lg px-3 py-2 text-sm',\n mine\n ? 'bg-action-primary-bg text-action-primary-text'\n : 'bg-bg-surface text-text-primary border border-border-subtle'\n )}\n >\n {message.text}\n </div>\n </div>\n );\n })\n )}\n </div>\n\n <div className=\"mt-3 flex items-end gap-2\">\n <textarea\n value={draft}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault();\n void handleSend();\n }\n }}\n rows={2}\n placeholder=\"Write a message…\"\n className=\"min-h-10 flex-1 resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <Button type=\"button\" onClick={handleSend} disabled={!draft.trim() || !conversationId || sending}>\n <Send className=\"h-4 w-4\" />\n <span className=\"ml-1\">Send</span>\n </Button>\n </div>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </>\n );\n};\n"],"mappings":";;;;;;;;;;AAuCA,IAAa,KAAmD,EAC9D,aACA,eACA,UACA,aACA,YACA,aAAU,WACV,qBACI;CACJ,IAAM,EAAE,mBAAgB,GAAiB,EACnC,EAAE,qBAAkB,SAAS,MAAY,GAAwB,EACjE,EAAE,gBAAa,SAAS,MAAY,GAAgB,EACpD,CAAC,GAAM,KAAW,EAAS,GAAM,EACjC,CAAC,GAAgB,KAAqB,GAA8B,EACpE,CAAC,GAAO,KAAY,EAAS,GAAG,EAChC,EAAE,MAAM,GAAU,SAAS,MAAoB,EAAwB,EAAe,EACtF,IAAY,EAAuB,KAAK;AAsB9C,CAnBA,QAAgB;AACd,MAAI,CAAC,KAAQ,EAAgB;EAC7B,IAAI,IAAY;AAYhB,SAXA,EAAiB;GACf;GACA;GACA;GACA,aAAa;GACb;GACD,CAAC,CACC,MAAM,MAAQ;AACb,GAAK,KAAW,EAAkB,EAAI,GAAG;IACzC,CACD,OAAO,MAAe,EAAO,MAAM,mCAAmC,EAAI,QAAQ,CAAC,QACzE;AACX,OAAY;;IAEb;EAAC;EAAM;EAAgB;EAAkB;EAAU;EAAY;EAAO;EAAS,CAAC,EAEnF,QAAgB;AACd,IAAU,SAAS,SAAS,EAAE,KAAK,EAAU,QAAQ,cAAc,CAAC;IACnE,CAAC,EAAS,CAAC;CAEd,IAAM,IAAa,YAAY;EAC7B,IAAM,IAAO,EAAM,MAAM;AACrB,SAAC,KAAQ,CAAC,GACd,KAAI;AAEF,GADA,MAAM,EAAY,GAAgB,EAAK,EACvC,EAAS,GAAG;WACL,GAAK;AACZ,KAAO,MAAM,oBAAqB,EAAc,QAAQ;;IAItD,IAAgB,GAAa,MAAM;AAazC,QACE,kBAAA,GAAA,EAAA,UAAA,CANA,kBAAC,QAAD;EAAM,WAAU;EAAW,MAAK;EAAe,eAAe,EAAQ,GAAK;YACxE;EACI,CAAA,EAML,kBAAC,GAAD;EAAwB;EAAM,cAAc;YAC1C,kBAAC,GAAD;GAAyB,WAAU;aAAnC;IACE,kBAAC,GAAD,EAAA,UAAA,CACE,kBAAC,GAAD,EAAA,UAAwB,GAAgC,CAAA,EACxD,kBAAC,GAAD,EAAA,UACG,KAAe,8BAA8B,EAAM,oDACxB,CAAA,CACP,EAAA,CAAA;IAEzB,kBAAC,OAAD;KACE,KAAK;KACL,WAAU;eAET,KAAW,IACV,kBAAC,KAAD;MAAG,WAAU;gBAA+C;MAAyB,CAAA,GACnF,EAAS,WAAW,IACtB,kBAAC,KAAD;MAAG,WAAU;gBAA+C;MAExD,CAAA,GAEJ,EAAS,KAAK,MAAY;MACxB,IAAM,IAAO,EAAQ,aAAa;AAClC,aACE,kBAAC,OAAD;OAAsB,WAAW,EAAG,QAAQ,IAAO,gBAAgB,gBAAgB;iBACjF,kBAAC,OAAD;QACE,WAAW,EACT,4CACA,IACI,kDACA,8DACL;kBAEA,EAAQ;QACL,CAAA;OACF,EAXI,EAAQ,GAWZ;OAER;KAEA,CAAA;IAEN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,YAAD;MACE,OAAO;MACP,WAAW,MAAU,EAAS,EAAM,OAAO,MAAM;MACjD,YAAY,MAAU;AACpB,OAAI,EAAM,QAAQ,WAAW,CAAC,EAAM,aAClC,EAAM,gBAAgB,EACjB,GAAY;;MAGrB,MAAM;MACN,aAAY;MACZ,WAAU;MACV,CAAA,EACF,kBAAC,GAAD;MAAQ,MAAK;MAAS,SAAS;MAAY,UAAU,CAAC,EAAM,MAAM,IAAI,CAAC,KAAkB;gBAAzF,CACE,kBAAC,GAAD,EAAM,WAAU,WAAY,CAAA,EAC5B,kBAAC,QAAD;OAAM,WAAU;iBAAO;OAAW,CAAA,CAC3B;QACL;;IACkB;;EACT,CAAA,CAClB,EAAA,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReviewsSection.js","names":[],"sources":["../../../src/housingvista/components/ReviewsSection.tsx"],"sourcesContent":["/**\n * Reviews / Q&A surface backed by wspace-conversations-svc EntityComments.\n * Displays persisted reviews (a comment whose `metadata.stars` is set) and lets\n * the user submit a real review — no fabricated ratings. The denormalized\n * aggregate (rating/reviewCount) stays for at-a-glance display.\n * @module housingvista\n */\n\nimport { useState, type FC } from 'react';\nimport { Star } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { useEntityComments, useCreateEntityComment } from '../hooks';\nimport { notify } from '../lib/toast';\nimport { cn, formatDate } from '../utils/helpers';\n\ninterface ReviewsSectionProps {\n entityId: string;\n entityType: string;\n /** Denormalized aggregate for the header, if the entity carries one. */\n aggregateRating?: number | null;\n reviewCount?: number | null;\n}\n\nconst toStars = (value: unknown): number => {\n const n = typeof value === 'number' ? value : Number(value);\n return Number.isFinite(n) ? Math.min(5, Math.max(0, Math.round(n))) : 0;\n};\n\nconst StarRow: FC<{ value: number; onSelect?: (v: number) => void }> = ({ value, onSelect }) => (\n <div className=\"flex items-center gap-0.5\">\n {[1, 2, 3, 4, 5].map((star) => {\n const filled = star <= value;\n const icon = (\n <Star className={cn('h-4 w-4', filled ? 'fill-status-warning text-status-warning' : 'text-text-secondary')} />\n );\n return onSelect ? (\n <button key={star} type=\"button\" onClick={() => onSelect(star)} aria-label={`${star} star`}>\n {icon}\n </button>\n ) : (\n <span key={star}>{icon}</span>\n );\n })}\n </div>\n);\n\nexport const ReviewsSection: FC<ReviewsSectionProps> = ({ entityId, entityType, aggregateRating, reviewCount }) => {\n const { data: comments, total, loading } = useEntityComments(entityType, entityId);\n const { createComment, loading: submitting } = useCreateEntityComment();\n const [stars, setStars] = useState(0);\n const [text, setText] = useState('');\n\n const handleSubmit = async () => {\n if (stars === 0) {\n notify.warning('Pick a star rating');\n return;\n }\n if (!text.trim()) {\n notify.warning('Write a short review');\n return;\n }\n try {\n await createComment({ entityType, entityId, text: text.trim(), metadata: { stars } });\n notify.success('Review posted', 'Thanks for sharing your feedback.');\n setStars(0);\n setText('');\n } catch (err) {\n notify.error('Could not post review', (err as Error).message);\n }\n };\n\n return (\n <section className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Reviews</h2>\n {(aggregateRating ?? 0) > 0 && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <StarRow value={toStars(aggregateRating)} />\n <span>\n {Number(aggregateRating).toFixed(1)}\n {reviewCount ? ` · ${reviewCount} reviews` : ''}\n </span>\n </div>\n )}\n </div>\n\n {/* Write a review */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"mb-2 text-sm font-medium text-text-primary\">Write a review</p>\n <StarRow value={stars} onSelect={setStars} />\n <textarea\n value={text}\n onChange={(event) => setText(event.target.value)}\n rows={3}\n placeholder=\"Share your experience with this provider…\"\n className=\"mt-3 w-full resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <div className=\"mt-2 flex justify-end\">\n <Button type=\"button\" onClick={handleSubmit} disabled={submitting}>\n {submitting ? 'Posting…' : 'Post review'}\n </Button>\n </div>\n </div>\n\n {/* Review list */}\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading reviews…</p>\n ) : comments.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No reviews yet. Be the first to review.</p>\n ) : (\n <ul className=\"space-y-3\">\n {comments.map((comment) => (\n <li key={comment.id} className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"mb-1 flex items-center justify-between\">\n <StarRow value={toStars(comment.metadata?.stars)} />\n <span className=\"text-xs text-text-secondary\">{formatDate(comment.createdAt)}</span>\n </div>\n <p className=\"text-sm text-text-primary\">{comment.text}</p>\n </li>\n ))}\n </ul>\n )}\n {total > comments.length && (\n <p className=\"text-xs text-text-secondary\">Showing {comments.length} of {total} reviews.</p>\n )}\n </section>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"ReviewsSection.js","names":[],"sources":["../../../src/housingvista/components/ReviewsSection.tsx"],"sourcesContent":["/**\n * Reviews / Q&A surface backed by wspace-conversations-svc EntityComments.\n * Displays persisted reviews (a comment whose `metadata.stars` is set) and lets\n * the user submit a real review — no fabricated ratings. The denormalized\n * aggregate (rating/reviewCount) stays for at-a-glance display.\n * @module housingvista\n */\n\nimport { useState, type FC } from 'react';\nimport { Star } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { useEntityComments, useCreateEntityComment } from '../hooks';\nimport { notify } from '../lib/toast';\nimport { cn, formatDate } from '../utils/helpers';\n\ninterface ReviewsSectionProps {\n entityId: string;\n entityType: string;\n /** Denormalized aggregate for the header, if the entity carries one. */\n aggregateRating?: number | null;\n reviewCount?: number | null;\n}\n\nconst toStars = (value: unknown): number => {\n const n = typeof value === 'number' ? value : Number(value);\n return Number.isFinite(n) ? Math.min(5, Math.max(0, Math.round(n))) : 0;\n};\n\nconst StarRow: FC<{ value: number; onSelect?: (v: number) => void }> = ({ value, onSelect }) => (\n <div className=\"flex items-center gap-0.5\">\n {[1, 2, 3, 4, 5].map((star) => {\n const filled = star <= value;\n const icon = (\n <Star className={cn('h-4 w-4', filled ? 'fill-status-warning text-status-warning' : 'text-text-secondary')} />\n );\n return onSelect ? (\n <button key={star} type=\"button\" onClick={() => onSelect(star)} aria-label={`${star} star`}>\n {icon}\n </button>\n ) : (\n <span key={star}>{icon}</span>\n );\n })}\n </div>\n);\n\nexport const ReviewsSection: FC<ReviewsSectionProps> = ({ entityId, entityType, aggregateRating, reviewCount }) => {\n const { data: comments, total, loading } = useEntityComments(entityType, entityId);\n const { createComment, loading: submitting } = useCreateEntityComment();\n const [stars, setStars] = useState(0);\n const [text, setText] = useState('');\n\n const handleSubmit = async () => {\n if (stars === 0) {\n notify.warning('Pick a star rating');\n return;\n }\n if (!text.trim()) {\n notify.warning('Write a short review');\n return;\n }\n try {\n await createComment({ entityType, entityId, text: text.trim(), metadata: { stars } });\n notify.success('Review posted', 'Thanks for sharing your feedback.');\n setStars(0);\n setText('');\n } catch (err) {\n notify.error('Could not post review', (err as Error).message);\n }\n };\n\n return (\n <section className=\"space-y-4\">\n <div className=\"flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">Reviews</h2>\n {(aggregateRating ?? 0) > 0 && (\n <div className=\"flex items-center gap-2 text-sm text-text-secondary\">\n <StarRow value={toStars(aggregateRating)} />\n <span>\n {Number(aggregateRating).toFixed(1)}\n {reviewCount ? ` · ${reviewCount} reviews` : ''}\n </span>\n </div>\n )}\n </div>\n\n {/* Write a review */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <p className=\"mb-2 text-sm font-medium text-text-primary\">Write a review</p>\n <StarRow value={stars} onSelect={setStars} />\n <textarea\n value={text}\n onChange={(event) => setText(event.target.value)}\n rows={3}\n placeholder=\"Share your experience with this provider…\"\n className=\"mt-3 w-full resize-none rounded-md border border-border-subtle bg-bg-surface px-3 py-2 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]\"\n />\n <div className=\"mt-2 flex justify-end\">\n <Button type=\"button\" onClick={handleSubmit} disabled={submitting}>\n {submitting ? 'Posting…' : 'Post review'}\n </Button>\n </div>\n </div>\n\n {/* Review list */}\n {loading ? (\n <p className=\"text-sm text-text-secondary\">Loading reviews…</p>\n ) : comments.length === 0 ? (\n <p className=\"text-sm text-text-secondary\">No reviews yet. Be the first to review.</p>\n ) : (\n <ul className=\"space-y-3\">\n {comments.map((comment) => (\n <li key={comment.id} className=\"rounded-lg border border-border-subtle bg-bg-surface p-4\">\n <div className=\"mb-1 flex items-center justify-between\">\n <StarRow value={toStars(comment.metadata?.stars)} />\n <span className=\"text-xs text-text-secondary\">{formatDate(comment.createdAt)}</span>\n </div>\n <p className=\"text-sm text-text-primary\">{comment.text}</p>\n </li>\n ))}\n </ul>\n )}\n {total > comments.length && (\n <p className=\"text-xs text-text-secondary\">\n Showing {comments.length} of {total} reviews.\n </p>\n )}\n </section>\n );\n};\n"],"mappings":"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"}
@@ -286,7 +286,10 @@ var r = {
286
286
  }
287
287
  `, te = e`
288
288
  ${y}
289
- query GetMarketplaceServices($filter: HousingVistaMarketplaceServiceFilterInput, $pagination: HousingVistaPaginationInput) {
289
+ query GetMarketplaceServices(
290
+ $filter: HousingVistaMarketplaceServiceFilterInput
291
+ $pagination: HousingVistaPaginationInput
292
+ ) {
290
293
  housingvistaMarketplaceServices(filter: $filter, pagination: $pagination) {
291
294
  ...MarketplaceServiceFields
292
295
  }