@burdenoff/microfe-housingvista 2026.703.13 → 2026.709.2
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/generated/global-operations.d.ts +2 -0
- package/dist/generated/global-operations.d.ts.map +1 -0
- package/dist/generated/global-types.d.ts +23527 -0
- package/dist/generated/global-types.d.ts.map +1 -0
- package/dist/generated/wspace-operations.d.ts +267 -0
- package/dist/generated/wspace-operations.d.ts.map +1 -0
- package/dist/generated/wspace-operations.js +67 -0
- package/dist/generated/wspace-operations.js.map +1 -0
- package/dist/generated/wspace-types.d.ts +57868 -0
- package/dist/generated/wspace-types.d.ts.map +1 -0
- package/dist/housingvista/HousingVistaRoot.d.ts +5 -0
- package/dist/housingvista/HousingVistaRoot.d.ts.map +1 -0
- package/dist/housingvista/HousingVistaRoutes.d.ts +7 -0
- package/dist/housingvista/HousingVistaRoutes.d.ts.map +1 -0
- package/dist/housingvista/components/Breadcrumbs.d.ts +13 -0
- package/dist/housingvista/components/Breadcrumbs.d.ts.map +1 -0
- package/dist/housingvista/components/ChartCard.d.ts +12 -0
- package/dist/housingvista/components/ChartCard.d.ts.map +1 -0
- package/dist/housingvista/components/ContactOwnerDialog.d.ts +33 -0
- package/dist/housingvista/components/ContactOwnerDialog.d.ts.map +1 -0
- package/dist/housingvista/components/DataTable.d.ts +42 -0
- package/dist/housingvista/components/DataTable.d.ts.map +1 -0
- package/dist/housingvista/components/EmptyState.d.ts +19 -0
- package/dist/housingvista/components/EmptyState.d.ts.map +1 -0
- package/dist/housingvista/components/ErrorBoundary.d.ts +19 -0
- package/dist/housingvista/components/ErrorBoundary.d.ts.map +1 -0
- package/dist/housingvista/components/FileUploader.d.ts +16 -0
- package/dist/housingvista/components/FileUploader.d.ts.map +1 -0
- package/dist/housingvista/components/FilterBar.d.ts +13 -0
- package/dist/housingvista/components/FilterBar.d.ts.map +1 -0
- package/dist/housingvista/components/LoadingSkeleton.d.ts +10 -0
- package/dist/housingvista/components/LoadingSkeleton.d.ts.map +1 -0
- package/dist/housingvista/components/PageLayout.d.ts +18 -0
- package/dist/housingvista/components/PageLayout.d.ts.map +1 -0
- package/dist/housingvista/components/PropertyCard.d.ts +26 -0
- package/dist/housingvista/components/PropertyCard.d.ts.map +1 -0
- package/dist/housingvista/components/ReviewsSection.d.ts +12 -0
- package/dist/housingvista/components/ReviewsSection.d.ts.map +1 -0
- package/dist/housingvista/components/StatCard.d.ts +18 -0
- package/dist/housingvista/components/StatCard.d.ts.map +1 -0
- package/dist/housingvista/components/StatusBadge.d.ts +12 -0
- package/dist/housingvista/components/StatusBadge.d.ts.map +1 -0
- package/dist/housingvista/components/index.d.ts +17 -0
- package/dist/housingvista/components/index.d.ts.map +1 -0
- package/dist/housingvista/context/HousingVistaContext.d.ts +15 -0
- package/dist/housingvista/context/HousingVistaContext.d.ts.map +1 -0
- package/dist/housingvista/hooks/index.d.ts +804 -0
- package/dist/housingvista/hooks/index.d.ts.map +1 -0
- package/dist/housingvista/hooks/index.js +1 -0
- package/dist/housingvista/hooks/index.js.map +1 -1
- package/dist/housingvista/hooks/messages.d.ts +65 -0
- package/dist/housingvista/hooks/messages.d.ts.map +1 -0
- package/dist/housingvista/hooks/platform.d.ts +140 -0
- package/dist/housingvista/hooks/platform.d.ts.map +1 -0
- package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts +16 -0
- package/dist/housingvista/hooks/useHousingVistaAnalytics.d.ts.map +1 -0
- package/dist/housingvista/hooks/useHousingVistaAnalytics.js +57 -0
- package/dist/housingvista/hooks/useHousingVistaAnalytics.js.map +1 -0
- package/dist/housingvista/hooks/useServerPagination.d.ts +12 -0
- package/dist/housingvista/hooks/useServerPagination.d.ts.map +1 -0
- package/dist/housingvista/index.d.ts +13 -0
- package/dist/housingvista/index.d.ts.map +1 -0
- package/dist/housingvista/index.js +2 -0
- package/dist/housingvista/lib/toast.d.ts +11 -0
- package/dist/housingvista/lib/toast.d.ts.map +1 -0
- package/dist/housingvista/pages/HomePage.d.ts +7 -0
- package/dist/housingvista/pages/HomePage.d.ts.map +1 -0
- package/dist/housingvista/pages/HomePage.js +135 -132
- package/dist/housingvista/pages/HomePage.js.map +1 -1
- package/dist/housingvista/pages/amc/AMCManagementPage.d.ts +2 -0
- package/dist/housingvista/pages/amc/AMCManagementPage.d.ts.map +1 -0
- package/dist/housingvista/pages/analytics/AnalyticsPage.d.ts +2 -0
- package/dist/housingvista/pages/analytics/AnalyticsPage.d.ts.map +1 -0
- package/dist/housingvista/pages/analytics/AnalyticsPage.js +136 -134
- package/dist/housingvista/pages/analytics/AnalyticsPage.js.map +1 -1
- package/dist/housingvista/pages/assets/AssetDetailPage.d.ts +9 -0
- package/dist/housingvista/pages/assets/AssetDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/assets/AssetManagementPage.d.ts +2 -0
- package/dist/housingvista/pages/assets/AssetManagementPage.d.ts.map +1 -0
- package/dist/housingvista/pages/assets/AssetManagementPage.js.map +1 -1
- package/dist/housingvista/pages/chat/ChatPage.d.ts +14 -0
- package/dist/housingvista/pages/chat/ChatPage.d.ts.map +1 -0
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.d.ts +11 -0
- package/dist/housingvista/pages/finance/HomeLoanDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/finance/HomeLoansPage.d.ts +2 -0
- package/dist/housingvista/pages/finance/HomeLoansPage.d.ts.map +1 -0
- package/dist/housingvista/pages/investments/InvestmentDetailPage.d.ts +2 -0
- package/dist/housingvista/pages/investments/InvestmentDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/investments/InvestmentsPage.d.ts +2 -0
- package/dist/housingvista/pages/investments/InvestmentsPage.d.ts.map +1 -0
- package/dist/housingvista/pages/investments/InvestmentsPage.js.map +1 -1
- package/dist/housingvista/pages/legal/LegalPage.d.ts +2 -0
- package/dist/housingvista/pages/legal/LegalPage.d.ts.map +1 -0
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.d.ts +12 -0
- package/dist/housingvista/pages/legal/LegalServiceDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/market/AreaInsightsPage.d.ts +2 -0
- package/dist/housingvista/pages/market/AreaInsightsPage.d.ts.map +1 -0
- package/dist/housingvista/pages/market/MarketAnalyticsPage.d.ts +2 -0
- package/dist/housingvista/pages/market/MarketAnalyticsPage.d.ts.map +1 -0
- package/dist/housingvista/pages/marketplace/MarketplacePage.d.ts +2 -0
- package/dist/housingvista/pages/marketplace/MarketplacePage.d.ts.map +1 -0
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.d.ts +12 -0
- package/dist/housingvista/pages/marketplace/ServiceDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/offers/OffersPage.d.ts +10 -0
- package/dist/housingvista/pages/offers/OffersPage.d.ts.map +1 -0
- package/dist/housingvista/pages/properties/AddPropertyPage.d.ts +8 -0
- package/dist/housingvista/pages/properties/AddPropertyPage.d.ts.map +1 -0
- package/dist/housingvista/pages/properties/AddPropertyPage.js +279 -278
- package/dist/housingvista/pages/properties/AddPropertyPage.js.map +1 -1
- package/dist/housingvista/pages/properties/PropertiesPage.d.ts +7 -0
- package/dist/housingvista/pages/properties/PropertiesPage.d.ts.map +1 -0
- package/dist/housingvista/pages/properties/PropertiesPage.js +93 -86
- package/dist/housingvista/pages/properties/PropertiesPage.js.map +1 -1
- package/dist/housingvista/pages/properties/PropertyDetailPage.d.ts +9 -0
- package/dist/housingvista/pages/properties/PropertyDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/properties/PropertyDetailPage.js +514 -511
- package/dist/housingvista/pages/properties/PropertyDetailPage.js.map +1 -1
- package/dist/housingvista/pages/rental/RentalManagementPage.d.ts +2 -0
- package/dist/housingvista/pages/rental/RentalManagementPage.d.ts.map +1 -0
- package/dist/housingvista/pages/settings/ProfilePage.d.ts +2 -0
- package/dist/housingvista/pages/settings/ProfilePage.d.ts.map +1 -0
- package/dist/housingvista/pages/settings/SettingsPage.d.ts +2 -0
- package/dist/housingvista/pages/settings/SettingsPage.d.ts.map +1 -0
- package/dist/housingvista/pages/shortlist/ShortlistPage.d.ts +8 -0
- package/dist/housingvista/pages/shortlist/ShortlistPage.d.ts.map +1 -0
- package/dist/housingvista/pages/transactions/TransactionDetailPage.d.ts +8 -0
- package/dist/housingvista/pages/transactions/TransactionDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/transactions/TransactionsPage.d.ts +7 -0
- package/dist/housingvista/pages/transactions/TransactionsPage.d.ts.map +1 -0
- package/dist/housingvista/pages/transactions/milestones.d.ts +35 -0
- package/dist/housingvista/pages/transactions/milestones.d.ts.map +1 -0
- package/dist/housingvista/pages/verification/VerificationDetailPage.d.ts +10 -0
- package/dist/housingvista/pages/verification/VerificationDetailPage.d.ts.map +1 -0
- package/dist/housingvista/pages/verification/VerificationPage.d.ts +2 -0
- package/dist/housingvista/pages/verification/VerificationPage.d.ts.map +1 -0
- package/dist/housingvista/pages/viewings/ViewingsPage.d.ts +9 -0
- package/dist/housingvista/pages/viewings/ViewingsPage.d.ts.map +1 -0
- package/dist/housingvista/services/assistantApi.d.ts +90 -0
- package/dist/housingvista/services/assistantApi.d.ts.map +1 -0
- package/dist/housingvista/services/assistantApi.js +222 -0
- package/dist/housingvista/services/assistantApi.js.map +1 -0
- package/dist/housingvista/services/createSandboxAssistantTransport.d.ts +42 -0
- package/dist/housingvista/services/createSandboxAssistantTransport.d.ts.map +1 -0
- package/dist/housingvista/services/createSandboxAssistantTransport.js +120 -0
- package/dist/housingvista/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/housingvista/store/housingvistaStore.d.ts +72 -0
- package/dist/housingvista/store/housingvistaStore.d.ts.map +1 -0
- package/dist/housingvista/types/assistant.d.ts +16 -0
- package/dist/housingvista/types/assistant.d.ts.map +1 -0
- package/dist/housingvista/types/index.d.ts +1328 -0
- package/dist/housingvista/types/index.d.ts.map +1 -0
- package/dist/housingvista/utils/helpers.d.ts +25 -0
- package/dist/housingvista/utils/helpers.d.ts.map +1 -0
- package/dist/housingvista/utils/index.d.ts +2 -0
- package/dist/housingvista/utils/index.d.ts.map +1 -0
- package/dist/housingvista/utils/pageContext.d.ts +25 -0
- package/dist/housingvista/utils/pageContext.d.ts.map +1 -0
- package/dist/housingvista/utils/pageContext.js +77 -0
- package/dist/housingvista/utils/pageContext.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -3
- package/package.json +6 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropertyDetailPage.js","names":[],"sources":["../../../../src/housingvista/pages/properties/PropertyDetailPage.tsx"],"sourcesContent":["/**\n * HousingVista Property Detail Page\n * Full property detail view backed by the single-item `housingvistaProperty(id)`\n * query, with the core buyer journey wired to real mutations: shortlist, book a\n * viewing, submit an offer, plus owner-side edit and delete.\n * @module housingvista\n */\n\nimport { useState, useMemo, type FormEvent } from 'react';\nimport { useParams, useNavigate, useLocation } from 'react-router-dom';\nimport {\n ArrowLeft,\n MapPin,\n Bed,\n Bath,\n Square,\n Car,\n Heart,\n Share2,\n CheckCircle,\n Calendar,\n DollarSign,\n ChevronLeft,\n ChevronRight,\n Building,\n Pencil,\n Trash2,\n Calculator,\n TrendingUp,\n MessageSquare,\n KeyRound,\n BadgeCheck,\n Compass,\n Waves,\n Dumbbell,\n Shield,\n TreePine,\n Wifi,\n Wind,\n Flame,\n Utensils,\n ParkingCircle,\n Navigation,\n type LucideIcon,\n} from 'lucide-react';\nimport { AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';\nimport {\n EmphasisPanel,\n PagePurpose,\n NextSteps,\n Button,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Breadcrumbs,\n StatusBadge,\n EmptyState,\n LoadingSkeleton,\n ContactOwnerDialog,\n ReviewsSection,\n} from '../../components';\nimport type { BreadcrumbItem } from '../../components';\nimport {\n useProperty,\n useProperties,\n useShortlists,\n useSaveShortlist,\n useRemoveShortlist,\n useBookViewing,\n useSubmitOffer,\n useUpdateProperty,\n useDeleteProperty,\n useRentalUnits,\n useSubmitRentalApplication,\n useCreateInvestment,\n} from '../../hooks';\nimport { notify } from '../../lib/toast';\nimport { cn, formatCurrency, formatCompactCurrency, formatNumber, formatDate } from '../../utils/helpers';\nimport type { Property, PropertyStatus } from '../../types';\n\nconst statusVariantMap: Record<string, 'success' | 'warning' | 'error' | 'info' | 'default' | 'muted'> = {\n for_sale: 'success',\n for_rent: 'info',\n sold: 'muted',\n rented: 'muted',\n under_contract: 'warning',\n off_market: 'error',\n};\n\nconst statusOptions: { value: PropertyStatus; label: string }[] = [\n { value: 'for_sale', label: 'For Sale' },\n { value: 'for_rent', label: 'For Rent' },\n { value: 'under_contract', label: 'Under Contract' },\n { value: 'sold', label: 'Sold' },\n { value: 'rented', label: 'Rented' },\n { value: 'off_market', label: 'Off Market' },\n];\n\ntype TabId = 'details' | 'amenities' | 'location';\nconst tabs: { id: TabId; label: string }[] = [\n { id: 'details', label: 'Details' },\n { id: 'amenities', label: 'Amenities' },\n { id: 'location', label: 'Location' },\n];\n\nconst inputClass =\n 'h-10 w-full rounded-md border border-border-subtle bg-bg-surface px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\n\n// Map free-text amenity names to a recognisable icon (falls back to a tick).\nconst amenityIconRules: { match: RegExp; icon: LucideIcon }[] = [\n { match: /pool|swim/i, icon: Waves },\n { match: /gym|fitness/i, icon: Dumbbell },\n { match: /park/i, icon: ParkingCircle },\n { match: /garden|green|lawn|park/i, icon: TreePine },\n { match: /security|guard|cctv|gated/i, icon: Shield },\n { match: /wifi|internet|broadband/i, icon: Wifi },\n { match: /a\\/?c|air.?condition|central air|hvac/i, icon: Wind },\n { match: /fire|chimney|heat/i, icon: Flame },\n { match: /kitchen|modular|dining/i, icon: Utensils },\n { match: /car|garage/i, icon: Car },\n];\nconst amenityIcon = (name: string): LucideIcon => amenityIconRules.find((r) => r.match.test(name))?.icon ?? CheckCircle;\n\nexport const PropertyDetailPage = () => {\n const { id } = useParams<{ id: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n\n const { data: property, loading } = useProperty(id);\n const { data: allProperties } = useProperties({ pagination: { limit: 8, offset: 0 } });\n const { data: shortlists } = useShortlists();\n const { data: rentalUnits } = useRentalUnits({\n filter: id ? { propertyId: id } : undefined,\n pagination: { limit: 1, offset: 0 },\n });\n const { saveShortlist, loading: savingShortlist } = useSaveShortlist();\n const { removeShortlist, loading: removingShortlist } = useRemoveShortlist();\n const { bookViewing, loading: bookingViewing } = useBookViewing();\n const { submitOffer, loading: submittingOffer } = useSubmitOffer();\n const { updateProperty, loading: updatingProperty } = useUpdateProperty();\n const { deleteProperty, loading: deletingProperty } = useDeleteProperty();\n const { submitRentalApplication, loading: submittingRental } = useSubmitRentalApplication();\n const { createInvestment, loading: creatingInvestment } = useCreateInvestment();\n\n const similarProperties = useMemo(() => allProperties.filter((p) => p.id !== id).slice(0, 3), [allProperties, id]);\n const isShortlisted = useMemo(() => shortlists.some((s) => s.propertyId === id), [shortlists, id]);\n\n const [currentImageIndex, setCurrentImageIndex] = useState(0);\n const [activeTab, setActiveTab] = useState<TabId>('details');\n const [viewingOpen, setViewingOpen] = useState(false);\n const [offerOpen, setOfferOpen] = useState(false);\n const [editOpen, setEditOpen] = useState(false);\n const [deleteOpen, setDeleteOpen] = useState(false);\n const [rentalOpen, setRentalOpen] = useState(false);\n const [contactOpen, setContactOpen] = useState(false);\n\n // Rental application form state\n const [applicantName, setApplicantName] = useState('');\n const [applicantEmail, setApplicantEmail] = useState('');\n const [applicantPhone, setApplicantPhone] = useState('');\n const [monthlyIncome, setMonthlyIncome] = useState('');\n const [moveInDate, setMoveInDate] = useState('');\n\n // Investment-analysis calculator inputs (blank = use a price-derived default)\n const [rentInput, setRentInput] = useState('');\n const [costInput, setCostInput] = useState('');\n const [appreciationInput, setAppreciationInput] = useState('8');\n\n // Viewing form state\n const [viewingDate, setViewingDate] = useState('');\n const [viewingType, setViewingType] = useState<'in_person' | 'virtual'>('in_person');\n const [attendeeName, setAttendeeName] = useState('');\n const [attendeeEmail, setAttendeeEmail] = useState('');\n const [viewingNotes, setViewingNotes] = useState('');\n\n // Offer form state\n const [offerAmount, setOfferAmount] = useState('');\n const [offerNotes, setOfferNotes] = useState('');\n\n // Edit form state (seeded on open)\n const [editTitle, setEditTitle] = useState('');\n const [editDescription, setEditDescription] = useState('');\n const [editStatus, setEditStatus] = useState<PropertyStatus>('for_sale');\n const [editPrice, setEditPrice] = useState('');\n\n if (loading) {\n return (\n <div className=\"space-y-6 p-6\">\n <LoadingSkeleton className=\"h-80\" />\n <LoadingSkeleton variant=\"detail\" />\n </div>\n );\n }\n\n if (!property) {\n return (\n <div className=\"p-6\">\n <EmptyState\n illustration=\"empty-search\"\n icon={<Building className=\"h-12 w-12\" />}\n title=\"Property Not Found\"\n description=\"The property you're looking for doesn't exist or has been removed.\"\n action={\n <button\n onClick={() => navigate('../properties')}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Properties\n </button>\n }\n />\n </div>\n );\n }\n\n const breadcrumbs: BreadcrumbItem[] = [{ label: 'Properties', href: '../' }, { label: property.title }];\n\n const formatPrice = (price: Property['price']) => {\n const amount = formatCurrency(price.amount, price.currency);\n if (price.type === 'rent' && price.period) return `${amount}/${price.period.replace('ly', '')}`;\n return amount;\n };\n\n const nextImage = () => setCurrentImageIndex((prev) => (prev === property.images.length - 1 ? 0 : prev + 1));\n const prevImage = () => setCurrentImageIndex((prev) => (prev === 0 ? property.images.length - 1 : prev - 1));\n\n const handleShare = () => {\n if (navigator.share) {\n navigator.share({ title: property.title, text: property.description, url: window.location.href });\n } else {\n navigator.clipboard.writeText(window.location.href);\n notify.info('Link copied', 'The property link is on your clipboard.');\n }\n };\n\n const toggleShortlist = async () => {\n try {\n if (isShortlisted) {\n await removeShortlist(property.id);\n notify.success('Removed from shortlist');\n } else {\n await saveShortlist(property.id);\n notify.success('Saved to shortlist');\n }\n } catch (err) {\n notify.error('Could not update shortlist', (err as Error).message);\n }\n };\n\n const handleBookViewing = async (e: FormEvent) => {\n e.preventDefault();\n if (!viewingDate) return;\n try {\n await bookViewing({\n propertyId: property.id,\n scheduledAt: new Date(viewingDate).toISOString(),\n type: viewingType,\n attendeeName: attendeeName.trim() || undefined,\n attendeeEmail: attendeeEmail.trim() || undefined,\n notes: viewingNotes.trim() || undefined,\n });\n notify.success('Viewing requested', 'The owner will confirm your slot shortly.');\n setViewingOpen(false);\n setViewingDate('');\n setAttendeeName('');\n setAttendeeEmail('');\n setViewingNotes('');\n } catch (err) {\n notify.error('Could not book viewing', (err as Error).message);\n }\n };\n\n const handleSubmitOffer = async (e: FormEvent) => {\n e.preventDefault();\n const amount = Number(offerAmount);\n if (!amount || amount <= 0) {\n notify.warning('Enter a valid offer amount');\n return;\n }\n try {\n await submitOffer({\n propertyId: property.id,\n amount,\n currency: property.price.currency,\n notes: offerNotes.trim() || undefined,\n });\n notify.success('Offer submitted', `Your offer of ${formatCurrency(amount, property.price.currency)} was sent.`);\n setOfferOpen(false);\n setOfferAmount('');\n setOfferNotes('');\n } catch (err) {\n notify.error('Could not submit offer', (err as Error).message);\n }\n };\n\n const openEdit = () => {\n setEditTitle(property.title);\n setEditDescription(property.description);\n setEditStatus(property.status);\n setEditPrice(String(property.price.amount));\n setEditOpen(true);\n };\n\n const handleEdit = async (e: FormEvent) => {\n e.preventDefault();\n try {\n await updateProperty(property.id, {\n title: editTitle.trim(),\n description: editDescription.trim(),\n status: editStatus,\n price: Number(editPrice) || property.price.amount,\n });\n notify.success('Property updated');\n setEditOpen(false);\n } catch (err) {\n notify.error('Could not update property', (err as Error).message);\n }\n };\n\n const handleDelete = async () => {\n try {\n await deleteProperty(property.id);\n notify.success('Property deleted');\n navigate('../properties');\n } catch (err) {\n notify.error('Could not delete property', (err as Error).message);\n }\n };\n\n // First available rental unit for this property (needed to submit an application).\n const rentalUnitId = rentalUnits[0]?.id;\n\n const handleSubmitRental = async (e: FormEvent) => {\n e.preventDefault();\n if (!rentalUnitId) {\n notify.warning('No rental unit is available for this property yet');\n return;\n }\n if (!applicantName.trim() || !applicantEmail.trim()) {\n notify.warning('Enter your name and email to apply');\n return;\n }\n try {\n await submitRentalApplication({\n rentalUnitId,\n applicantName: applicantName.trim(),\n applicantEmail: applicantEmail.trim(),\n applicantPhone: applicantPhone.trim() || undefined,\n monthlyIncome: monthlyIncome ? Number(monthlyIncome) : undefined,\n moveInDate: moveInDate ? new Date(moveInDate).toISOString() : undefined,\n });\n notify.success('Application submitted', 'The owner will review your rental application shortly.');\n setRentalOpen(false);\n setApplicantName('');\n setApplicantEmail('');\n setApplicantPhone('');\n setMonthlyIncome('');\n setMoveInDate('');\n } catch (err) {\n notify.error('Could not submit application', (err as Error).message);\n }\n };\n\n const handleTrackInvestment = async () => {\n try {\n await createInvestment({\n propertyId: property.id,\n title: `${property.title} — investment`,\n status: 'active',\n investmentType: 'full_ownership',\n riskLevel: 'medium',\n totalValue: property.price.amount,\n startDate: new Date().toISOString(),\n });\n notify.success('Tracking investment', `${property.title} was added to your portfolio.`);\n } catch (err) {\n notify.error('Could not track investment', (err as Error).message);\n }\n };\n\n // Investment analysis — modelled client-side from the listing price + user inputs.\n const price = property.price.amount;\n const monthlyRent = Number(rentInput) || Math.round(price * 0.005); // ~0.5%/mo default\n const monthlyHoldingCosts = Number(costInput) || Math.round(price * 0.0015); // ~0.15%/mo default\n const grossAnnualRent = monthlyRent * 12;\n const grossYield = price > 0 ? (grossAnnualRent / price) * 100 : 0;\n const annualHoldingCosts = monthlyHoldingCosts * 12;\n const netAnnualIncome = grossAnnualRent - annualHoldingCosts;\n const netYield = price > 0 ? (netAnnualIncome / price) * 100 : 0;\n // 5-year projected value growth at a user-adjustable appreciation rate + the\n // cumulative net rental income earned over the same window (total return).\n const appreciationRate = Math.max(0, Number(appreciationInput) || 0) / 100;\n const projection = Array.from({ length: 6 }, (_, year) => ({\n label: year === 0 ? 'Now' : `Yr ${year}`,\n value: Math.round(price * Math.pow(1 + appreciationRate, year)),\n }));\n const projectedValue5yr = projection[projection.length - 1].value;\n const totalReturn5yr = projectedValue5yr - price + netAnnualIncome * 5;\n const projectedRoi = price > 0 ? (totalReturn5yr / price) * 100 : 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <Breadcrumbs items={breadcrumbs} />\n\n {/* Header */}\n <div className=\"flex flex-wrap items-center gap-3\">\n <button\n onClick={() => navigate('../properties')}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back\n </button>\n <StatusBadge\n label={property.status.replace('_', ' ')}\n variant={statusVariantMap[property.status] ?? 'default'}\n dot\n />\n {property.verificationStatus === 'verified' && <StatusBadge label=\"Verified\" variant=\"success\" dot />}\n {property.price.negotiable && <StatusBadge label=\"Negotiable\" variant=\"info\" />}\n <div className=\"ml-auto flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={openEdit}>\n <Pencil className=\"mr-1.5 h-4 w-4\" />\n Edit\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setDeleteOpen(true)}>\n <Trash2 className=\"mr-1.5 h-4 w-4\" />\n Delete\n </Button>\n </div>\n </div>\n\n <PagePurpose className=\"max-w-3xl\">\n Everything you need to evaluate this property in one place — photos, specifications, amenities, and location.\n Use it to shortlist the property, schedule a viewing, or make an offer.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"housingvista-property-detail\"\n steps={[\n {\n id: 'schedule',\n label: 'Schedule a viewing',\n description: 'Book a time to see the property in person or virtually.',\n onClick: () => setViewingOpen(true),\n },\n {\n id: 'offer',\n label: 'Make an offer',\n description: 'Submit a price and let the owner respond.',\n onClick: () => setOfferOpen(true),\n },\n {\n id: 'location',\n label: 'Explore the location',\n description: 'See the neighborhood, nearby landmarks, and map.',\n onClick: () => setActiveTab('location'),\n },\n ]}\n />\n\n {/* Image Gallery */}\n <div className=\"space-y-3\">\n <div className=\"relative overflow-hidden rounded-xl border border-border-subtle bg-bg-sunken\">\n {property.images.length > 0 ? (\n <img\n src={property.images[currentImageIndex]?.url}\n alt={property.images[currentImageIndex]?.title ?? property.title}\n className=\"h-80 w-full object-cover sm:h-[26rem]\"\n />\n ) : (\n <div className=\"flex h-80 w-full flex-col items-center justify-center gap-3 bg-gradient-to-br from-[var(--color-action-primary-bg)]/12 via-bg-sunken to-[var(--color-accent-blue)]/12 text-text-secondary/70 sm:h-[26rem]\">\n <Building className=\"h-12 w-12\" />\n <span className=\"text-sm font-medium tracking-wide\">No photos yet</span>\n </div>\n )}\n\n {property.images.length > 1 && (\n <>\n <button\n onClick={prevImage}\n aria-label=\"Previous photo\"\n className=\"absolute left-4 top-1/2 -translate-y-1/2 rounded-full bg-bg-overlay/70 p-2 text-text-inverse transition-colors hover:bg-bg-overlay\"\n >\n <ChevronLeft className=\"h-5 w-5\" />\n </button>\n <button\n onClick={nextImage}\n aria-label=\"Next photo\"\n className=\"absolute right-4 top-1/2 -translate-y-1/2 rounded-full bg-bg-overlay/70 p-2 text-text-inverse transition-colors hover:bg-bg-overlay\"\n >\n <ChevronRight className=\"h-5 w-5\" />\n </button>\n </>\n )}\n\n {/* Verified badge overlay */}\n {property.verificationStatus === 'verified' && (\n <div className=\"absolute left-4 top-4 inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-3 py-1 text-xs font-semibold text-status-success-text shadow-elevation-1 backdrop-blur-sm\">\n <BadgeCheck className=\"h-4 w-4\" />\n Verified listing\n </div>\n )}\n\n <div className=\"absolute right-4 top-4 flex gap-2\">\n <button\n onClick={toggleShortlist}\n disabled={savingShortlist || removingShortlist}\n aria-label={isShortlisted ? 'Remove from shortlist' : 'Save to shortlist'}\n className=\"rounded-full bg-bg-surface/85 p-2 shadow-elevation-1 backdrop-blur-sm transition-colors hover:bg-bg-surface disabled:opacity-60\"\n >\n <Heart\n className={cn(\n 'h-5 w-5',\n isShortlisted ? 'fill-status-error-text text-status-error-text' : 'text-text-secondary'\n )}\n />\n </button>\n <button\n onClick={handleShare}\n aria-label=\"Share this listing\"\n className=\"rounded-full bg-bg-surface/85 p-2 shadow-elevation-1 backdrop-blur-sm transition-colors hover:bg-bg-surface\"\n >\n <Share2 className=\"h-5 w-5 text-text-secondary\" />\n </button>\n </div>\n\n {property.images.length > 0 && (\n <div className=\"absolute bottom-4 right-4\">\n <span className=\"rounded-md bg-bg-overlay/70 px-2 py-1 text-xs font-medium text-text-inverse\">\n {currentImageIndex + 1} / {property.images.length}\n </span>\n </div>\n )}\n </div>\n\n {/* Thumbnail strip */}\n {property.images.length > 1 && (\n <div className=\"flex gap-3 overflow-x-auto pb-1\">\n {property.images.map((img, index) => (\n <button\n key={img.id}\n onClick={() => setCurrentImageIndex(index)}\n aria-label={`View photo ${index + 1}`}\n aria-current={index === currentImageIndex}\n className={cn(\n 'h-16 w-24 shrink-0 overflow-hidden rounded-lg border-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]',\n index === currentImageIndex\n ? 'border-action-primary-border'\n : 'border-transparent opacity-70 hover:opacity-100'\n )}\n >\n <img src={img.url} alt={img.title ?? `Photo ${index + 1}`} className=\"h-full w-full object-cover\" />\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Main Content Grid */}\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Left: Main content */}\n <div className=\"space-y-6 lg:col-span-2\">\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">{property.title}</h1>\n <div className=\"mt-2 flex items-center text-text-secondary\">\n <MapPin className=\"mr-1.5 h-4 w-4 shrink-0\" />\n <span className=\"text-sm\">\n {[property.location.address, property.location.neighborhood, property.location.city]\n .filter(Boolean)\n .join(', ')}\n </span>\n </div>\n </div>\n <div className=\"text-right\">\n <div className=\"text-2xl font-bold text-text-primary\">{formatPrice(property.price)}</div>\n {property.price.pricePerSqft && (\n <div className=\"text-sm text-text-secondary\">{formatCurrency(property.price.pricePerSqft)}/sqft</div>\n )}\n </div>\n </div>\n\n {/* Key Specs — spec cards */}\n <div className=\"mt-6 grid grid-cols-2 gap-3 border-t border-border-subtle pt-6 sm:grid-cols-4\">\n {[\n property.specifications.bedrooms != null && {\n icon: Bed,\n value: String(property.specifications.bedrooms),\n label: property.specifications.bedrooms === 1 ? 'Bedroom' : 'Bedrooms',\n },\n property.specifications.bathrooms != null && {\n icon: Bath,\n value: String(property.specifications.bathrooms),\n label: property.specifications.bathrooms === 1 ? 'Bathroom' : 'Bathrooms',\n },\n {\n icon: Square,\n value: formatNumber(property.specifications.totalArea),\n label: 'sq ft',\n },\n property.specifications.parking != null && property.specifications.parking > 0\n ? {\n icon: Car,\n value: String(property.specifications.parking),\n label: 'Parking',\n }\n : property.specifications.facing\n ? { icon: Compass, value: property.specifications.facing, label: 'Facing' }\n : false,\n ]\n .filter((spec): spec is { icon: LucideIcon; value: string; label: string } => Boolean(spec))\n .map((spec) => {\n const Icon = spec.icon;\n return (\n <div\n key={spec.label}\n className=\"flex flex-col items-center gap-1 rounded-lg border border-border-subtle bg-bg-sunken/40 p-3 text-center\"\n >\n <Icon className=\"h-5 w-5 text-text-secondary\" />\n <span className=\"text-base font-semibold text-text-primary\">{spec.value}</span>\n <span className=\"text-xs text-text-secondary\">{spec.label}</span>\n </div>\n );\n })}\n </div>\n\n {property.description && (\n <div className=\"mt-6 border-t border-border-subtle pt-6\">\n <h3 className=\"mb-3 text-base font-semibold text-text-primary\">Description</h3>\n <p className=\"text-sm leading-relaxed text-text-secondary\">{property.description}</p>\n </div>\n )}\n </EmphasisPanel>\n\n {/* Tabbed Content */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface\">\n <div className=\"border-b border-border-subtle\">\n <nav className=\"flex space-x-6 overflow-x-auto px-6\">\n {tabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n 'whitespace-nowrap border-b-2 py-3 text-sm font-medium transition-colors',\n activeTab === tab.id\n ? 'border-action-primary-border text-text-primary'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n )}\n >\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n <div className=\"p-6\">\n {activeTab === 'details' && (\n <div className=\"grid grid-cols-1 gap-6 sm:grid-cols-2\">\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">Property Information</h4>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Property Type</dt>\n <dd className=\"font-medium capitalize text-text-primary\">{property.type}</dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Category</dt>\n <dd className=\"font-medium capitalize text-text-primary\">{property.category}</dd>\n </div>\n {property.specifications.ageOfProperty != null && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Age of Property</dt>\n <dd className=\"font-medium text-text-primary\">\n {property.specifications.ageOfProperty} years\n </dd>\n </div>\n )}\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Furnishing</dt>\n <dd className=\"font-medium capitalize text-text-primary\">\n {property.specifications.furnishingStatus?.replace('_', ' ')}\n </dd>\n </div>\n {property.specifications.facing && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Facing</dt>\n <dd className=\"font-medium text-text-primary\">{property.specifications.facing}</dd>\n </div>\n )}\n {property.specifications.floors != null && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Floor</dt>\n <dd className=\"font-medium text-text-primary\">\n {property.specifications.floors} of {property.specifications.totalFloors}\n </dd>\n </div>\n )}\n </dl>\n </div>\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">Area Details</h4>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Total Area</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatNumber(property.specifications.totalArea)} sqft\n </dd>\n </div>\n {property.specifications.carpetArea && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Carpet Area</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatNumber(property.specifications.carpetArea)} sqft\n </dd>\n </div>\n )}\n {property.specifications.builtUpArea && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Built-up Area</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatNumber(property.specifications.builtUpArea)} sqft\n </dd>\n </div>\n )}\n {property.price.pricePerSqft && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Price per sqft</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatCurrency(property.price.pricePerSqft)}\n </dd>\n </div>\n )}\n </dl>\n </div>\n </div>\n )}\n\n {activeTab === 'amenities' && (\n <div>\n {property.amenities.length > 0 ? (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4\">\n {property.amenities.map((amenity) => {\n const Icon = amenityIcon(amenity.name);\n return (\n <div\n key={amenity.id}\n className=\"flex flex-col items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken/40 p-4 text-center\"\n >\n <span className=\"flex h-10 w-10 items-center justify-center rounded-full bg-status-success-bg-subtle text-status-success-text\">\n <Icon className=\"h-5 w-5\" />\n </span>\n <span className=\"text-sm font-medium text-text-primary\">{amenity.name}</span>\n </div>\n );\n })}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title=\"No amenities listed\"\n description=\"This property has no amenities recorded yet.\"\n className=\"border-0 bg-transparent p-6\"\n />\n )}\n </div>\n )}\n\n {activeTab === 'location' && (\n <div className=\"space-y-4\">\n {/* Map card — styled placeholder pinned to the listing's locale */}\n <div className=\"relative h-56 overflow-hidden rounded-xl border border-border-subtle bg-bg-sunken\">\n <div\n className=\"absolute inset-0 opacity-60\"\n style={{\n backgroundImage:\n 'linear-gradient(var(--color-border-seam, rgba(120,120,120,.18)) 1px, transparent 1px), linear-gradient(90deg, var(--color-border-seam, rgba(120,120,120,.18)) 1px, transparent 1px)',\n backgroundSize: '32px 32px',\n }}\n />\n <div className=\"absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center gap-1 text-center\">\n <span className=\"flex h-11 w-11 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text shadow-pop\">\n <MapPin className=\"h-5 w-5\" />\n </span>\n <span className=\"mt-1 rounded-md bg-bg-surface/90 px-2 py-0.5 text-sm font-semibold text-text-primary shadow-elevation-1 backdrop-blur-sm\">\n {property.location.neighborhood || property.location.city}\n </span>\n <span className=\"text-xs text-text-secondary\">\n {[property.location.city, property.location.state].filter(Boolean).join(', ')}\n </span>\n </div>\n {property.location.coordinates?.latitude != null &&\n property.location.coordinates?.longitude != null && (\n <a\n href={`https://www.google.com/maps/search/?api=1&query=${property.location.coordinates.latitude},${property.location.coordinates.longitude}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"absolute bottom-3 right-3 inline-flex items-center gap-1.5 rounded-md bg-bg-surface/90 px-2.5 py-1.5 text-xs font-medium text-text-primary shadow-elevation-1 backdrop-blur-sm transition-colors hover:bg-bg-surface\"\n >\n <Navigation className=\"h-3.5 w-3.5\" />\n Open in Maps\n </a>\n )}\n </div>\n {property.location.address && (\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">Full Address</div>\n <div className=\"text-sm font-medium text-text-primary\">{property.location.address}</div>\n </div>\n )}\n <div className=\"grid grid-cols-1 gap-4 text-sm sm:grid-cols-3\">\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">Neighborhood</div>\n <div className=\"font-medium text-text-primary\">{property.location.neighborhood || '—'}</div>\n </div>\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">City, State</div>\n <div className=\"font-medium text-text-primary\">\n {property.location.city}, {property.location.state}\n </div>\n </div>\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">PIN / ZIP</div>\n <div className=\"font-medium text-text-primary\">{property.location.pincode || '—'}</div>\n </div>\n </div>\n\n {property.location.landmarks.length > 0 && (\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"mb-2 text-xs font-medium text-text-secondary\">Nearby Landmarks</h4>\n <div className=\"flex flex-wrap gap-2\">\n {property.location.landmarks.map((landmark) => (\n <span\n key={landmark}\n className=\"rounded-full bg-bg-sunken px-3 py-1 text-xs text-text-primary\"\n >\n {landmark}\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right Sidebar */}\n <div className=\"space-y-6\">\n {/* Price + Actions — lead panel (mirrors the listing hero) */}\n <div\n id=\"property-actions\"\n className=\"scroll-mt-6 rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-elevation-1 lg:sticky lg:top-6\"\n >\n <div className=\"flex flex-wrap items-baseline gap-x-2 gap-y-1\">\n <span className=\"text-3xl font-bold text-text-primary\">{formatPrice(property.price)}</span>\n {property.price.negotiable && <span className=\"text-sm text-text-secondary\">· Negotiable</span>}\n </div>\n {property.price.pricePerSqft && (\n <p className=\"mt-1 text-sm text-text-secondary\">\n {formatCurrency(property.price.pricePerSqft, property.price.currency)}/sqft\n </p>\n )}\n\n <div className=\"mt-4 space-y-2\">\n <Button type=\"button\" className=\"w-full justify-center\" onClick={() => setOfferOpen(true)}>\n <DollarSign className=\"mr-2 h-4 w-4\" />\n Make Offer\n </Button>\n {property.status === 'for_rent' && (\n <>\n <Button\n type=\"button\"\n className=\"w-full justify-center\"\n onClick={() => setRentalOpen(true)}\n disabled={!rentalUnitId}\n >\n <KeyRound className=\"mr-2 h-4 w-4\" />\n Apply to Rent\n </Button>\n {!rentalUnitId && (\n <p className=\"px-1 text-xs text-text-secondary\">\n No rental unit is listed for this property yet — applications open once a unit is added.\n </p>\n )}\n </>\n )}\n <div className=\"grid grid-cols-2 gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"w-full justify-center\"\n onClick={() => setViewingOpen(true)}\n >\n <Calendar className=\"mr-2 h-4 w-4\" />\n Viewing\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"w-full justify-center\"\n onClick={() => setContactOpen(true)}\n >\n <MessageSquare className=\"mr-2 h-4 w-4\" />\n Contact\n </Button>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"w-full justify-center\"\n onClick={toggleShortlist}\n disabled={savingShortlist || removingShortlist}\n >\n <Heart\n className={cn('mr-2 h-4 w-4', isShortlisted && 'fill-status-error-text text-status-error-text')}\n />\n {isShortlisted ? 'Saved to Shortlist' : 'Save to Shortlist'}\n </Button>\n </div>\n\n {property.verificationStatus === 'verified' && (\n <div className=\"mt-4 flex items-center gap-2 border-t border-border-subtle pt-4 text-sm font-medium text-status-success-text\">\n <BadgeCheck className=\"h-4 w-4\" />\n Verified listing\n </div>\n )}\n </div>\n\n {/* Investment analysis — modelled client-side from the listing price */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <div className=\"mb-4 flex items-center gap-2\">\n <Calculator className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-base font-semibold text-text-primary\">Investment Analysis</h3>\n </div>\n\n {/* Deal parameters */}\n <div className=\"space-y-3\">\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-text-secondary\">\n Expected monthly rent ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={rentInput}\n onChange={(e) => setRentInput(e.target.value)}\n placeholder={String(monthlyRent)}\n className={inputClass}\n />\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-text-secondary\">\n Monthly costs ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={costInput}\n onChange={(e) => setCostInput(e.target.value)}\n placeholder={String(monthlyHoldingCosts)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-text-secondary\">Appreciation (%/yr)</label>\n <input\n type=\"number\"\n min={0}\n step={0.5}\n value={appreciationInput}\n onChange={(e) => setAppreciationInput(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <p className=\"text-[11px] text-text-secondary\">\n Costs cover maintenance, tax, insurance, and management.\n </p>\n </div>\n\n {/* Financial projections — yield tiles */}\n <div className=\"mt-4 grid grid-cols-3 gap-2 border-t border-border-subtle pt-4\">\n <div className=\"rounded-lg border border-status-success-border bg-status-success-bg-subtle p-2.5 text-center\">\n <div className=\"text-[11px] font-medium text-status-success-text\">Gross Yield</div>\n <div className=\"mt-0.5 text-lg font-bold text-status-success-text\">{grossYield.toFixed(1)}%</div>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-2.5 text-center\">\n <div className=\"text-[11px] font-medium text-text-secondary\">Net Yield</div>\n <div className=\"mt-0.5 text-lg font-bold text-text-primary\">{netYield.toFixed(1)}%</div>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-2.5 text-center\">\n <div className=\"text-[11px] font-medium text-text-secondary\">5-yr ROI</div>\n <div className=\"mt-0.5 text-lg font-bold text-text-primary\">{projectedRoi.toFixed(0)}%</div>\n </div>\n </div>\n\n {/* Projected value growth */}\n <div className=\"mt-4\">\n <div className=\"mb-1 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-text-secondary\">Projected Value Growth</span>\n <span className=\"text-xs font-semibold text-text-primary\">\n {formatCompactCurrency(projectedValue5yr, property.price.currency)}\n </span>\n </div>\n <div className=\"h-32\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={projection} margin={{ top: 4, right: 4, bottom: 0, left: 0 }}>\n <defs>\n <linearGradient id=\"hvValueGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor=\"var(--color-chart-2)\" stopOpacity={0.35} />\n <stop offset=\"95%\" stopColor=\"var(--color-chart-2)\" stopOpacity={0} />\n </linearGradient>\n </defs>\n <XAxis dataKey=\"label\" tick={{ fontSize: 10 }} axisLine={false} tickLine={false} />\n <YAxis hide domain={['dataMin', 'dataMax']} />\n <Tooltip\n formatter={(value: number) => [formatCompactCurrency(value, property.price.currency), 'Value']}\n labelClassName=\"text-text-primary\"\n />\n <Area\n type=\"monotone\"\n dataKey=\"value\"\n stroke=\"var(--color-chart-2)\"\n fill=\"url(#hvValueGrad)\"\n strokeWidth={2}\n />\n </AreaChart>\n </ResponsiveContainer>\n </div>\n <p className=\"mt-1 text-[11px] text-text-secondary\">\n Projection based on your inputs and market appreciation. Consult a financial advisor before investing.\n </p>\n </div>\n\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"mt-4 w-full justify-center\"\n onClick={handleTrackInvestment}\n disabled={creatingInvestment}\n >\n <TrendingUp className=\"mr-2 h-4 w-4\" />\n {creatingInvestment ? 'Adding…' : 'Track as Investment'}\n </Button>\n </div>\n\n {/* Property Stats (real, derived) */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">At a Glance</h3>\n <div className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Status</span>\n <StatusBadge\n label={property.status.replace('_', ' ')}\n variant={statusVariantMap[property.status] ?? 'default'}\n />\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Verification</span>\n <span className=\"font-medium capitalize text-text-primary\">{property.verificationStatus}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Listed</span>\n <span className=\"font-medium text-text-primary\">{formatDate(String(property.createdAt))}</span>\n </div>\n </div>\n </div>\n\n {/* Similar Properties */}\n {similarProperties.length > 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">Similar Properties</h3>\n <div className=\"space-y-3\">\n {similarProperties.map((sp) => (\n <button\n key={sp.id}\n onClick={() => navigate(`../properties/${sp.id}`)}\n className=\"flex w-full items-start gap-3 rounded-lg border border-border-subtle p-3 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n {sp.images[0] && (\n <img src={sp.images[0].url} alt={sp.title} className=\"h-14 w-14 rounded object-cover\" />\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium text-text-primary\">{sp.title}</div>\n <div className=\"text-sm font-semibold text-text-primary\">{formatCurrency(sp.price.amount)}</div>\n <div className=\"truncate text-xs text-text-secondary\">\n {[sp.location.neighborhood, sp.location.city].filter(Boolean).join(', ')}\n </div>\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Q&A / reviews — real EntityComments-backed thread */}\n <ReviewsSection entityId={property.id} entityType=\"housingvista-property\" />\n\n {/* Contact-owner conversation dialog — controlled at page root (same\n reliable pattern as the Make Offer dialog) */}\n <ContactOwnerDialog\n open={contactOpen}\n onOpenChange={setContactOpen}\n entityId={property.id}\n entityType=\"housingvista-property\"\n title={property.title}\n pagePath={location.pathname}\n heading=\"Contact owner\"\n description={`Ask a question or start a conversation about ${property.title}.`}\n />\n\n {/* Apply to Rent dialog */}\n <ResponsiveDialog open={rentalOpen} onOpenChange={setRentalOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleSubmitRental}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Apply to rent</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Submit a rental application for {property.title}. The owner will review and respond.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Full name *</label>\n <input\n type=\"text\"\n required\n value={applicantName}\n onChange={(e) => setApplicantName(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Email *</label>\n <input\n type=\"email\"\n required\n value={applicantEmail}\n onChange={(e) => setApplicantEmail(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Phone</label>\n <input\n type=\"tel\"\n value={applicantPhone}\n onChange={(e) => setApplicantPhone(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Monthly income ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={monthlyIncome}\n onChange={(e) => setMonthlyIncome(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Preferred move-in date</label>\n <input\n type=\"date\"\n value={moveInDate}\n onChange={(e) => setMoveInDate(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setRentalOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={submittingRental || !rentalUnitId}>\n {submittingRental ? 'Submitting…' : 'Submit application'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Schedule Viewing dialog */}\n <ResponsiveDialog open={viewingOpen} onOpenChange={setViewingOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleBookViewing}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Schedule a viewing</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Pick a date and time to see {property.title}.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Date & time *</label>\n <input\n type=\"datetime-local\"\n required\n value={viewingDate}\n onChange={(e) => setViewingDate(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Type</label>\n <select\n value={viewingType}\n onChange={(e) => setViewingType(e.target.value as 'in_person' | 'virtual')}\n className={inputClass}\n >\n <option value=\"in_person\">In person</option>\n <option value=\"virtual\">Virtual</option>\n </select>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <input\n type=\"text\"\n placeholder=\"Your name\"\n value={attendeeName}\n onChange={(e) => setAttendeeName(e.target.value)}\n className={inputClass}\n />\n <input\n type=\"email\"\n placeholder=\"Your email\"\n value={attendeeEmail}\n onChange={(e) => setAttendeeEmail(e.target.value)}\n className={inputClass}\n />\n </div>\n <textarea\n placeholder=\"Notes (optional)\"\n rows={2}\n value={viewingNotes}\n onChange={(e) => setViewingNotes(e.target.value)}\n className=\"w-full 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>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setViewingOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={bookingViewing || !viewingDate}>\n {bookingViewing ? 'Booking…' : 'Request viewing'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Make Offer dialog */}\n <ResponsiveDialog open={offerOpen} onOpenChange={setOfferOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleSubmitOffer}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Make an offer</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Listing price is {formatPrice(property.price)}.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Your offer ({property.price.currency}) *\n </label>\n <input\n type=\"number\"\n required\n min={1}\n value={offerAmount}\n onChange={(e) => setOfferAmount(e.target.value)}\n placeholder=\"Enter amount\"\n className={inputClass}\n />\n </div>\n <textarea\n placeholder=\"Message to the owner (optional)\"\n rows={3}\n value={offerNotes}\n onChange={(e) => setOfferNotes(e.target.value)}\n className=\"w-full 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>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setOfferOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={submittingOffer}>\n {submittingOffer ? 'Submitting…' : 'Submit offer'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Edit dialog */}\n <ResponsiveDialog open={editOpen} onOpenChange={setEditOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleEdit}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit property</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Update the core listing details.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Title *</label>\n <input\n type=\"text\"\n required\n value={editTitle}\n onChange={(e) => setEditTitle(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Description</label>\n <textarea\n rows={3}\n value={editDescription}\n onChange={(e) => setEditDescription(e.target.value)}\n className=\"w-full 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>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Status</label>\n <select\n value={editStatus}\n onChange={(e) => setEditStatus(e.target.value as PropertyStatus)}\n className={inputClass}\n >\n {statusOptions.map((s) => (\n <option key={s.value} value={s.value}>\n {s.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Price ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={editPrice}\n onChange={(e) => setEditPrice(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setEditOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={updatingProperty}>\n {updatingProperty ? 'Saving…' : 'Save changes'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Delete confirm dialog */}\n <ResponsiveDialog open={deleteOpen} onOpenChange={setDeleteOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Delete this property?</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {property.title} will be permanently removed. This cannot be undone.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setDeleteOpen(false)}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"destructive\" onClick={handleDelete} disabled={deletingProperty}>\n {deletingProperty ? 'Deleting…' : 'Delete property'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PropertyDetailPage.js","names":[],"sources":["../../../../src/housingvista/pages/properties/PropertyDetailPage.tsx"],"sourcesContent":["/**\n * HousingVista Property Detail Page\n * Full property detail view backed by the single-item `housingvistaProperty(id)`\n * query, with the core buyer journey wired to real mutations: shortlist, book a\n * viewing, submit an offer, plus owner-side edit and delete.\n * @module housingvista\n */\n\nimport { useState, useMemo, type FormEvent } from 'react';\nimport { useParams, useNavigate, useLocation } from 'react-router-dom';\nimport {\n ArrowLeft,\n MapPin,\n Bed,\n Bath,\n Square,\n Car,\n Heart,\n Share2,\n CheckCircle,\n Calendar,\n DollarSign,\n ChevronLeft,\n ChevronRight,\n Building,\n Pencil,\n Trash2,\n Calculator,\n TrendingUp,\n MessageSquare,\n KeyRound,\n BadgeCheck,\n Compass,\n Waves,\n Dumbbell,\n Shield,\n TreePine,\n Wifi,\n Wind,\n Flame,\n Utensils,\n ParkingCircle,\n Navigation,\n type LucideIcon,\n} from 'lucide-react';\nimport { AreaChart, Area, XAxis, YAxis, Tooltip, ResponsiveContainer } from 'recharts';\nimport {\n EmphasisPanel,\n PagePurpose,\n NextSteps,\n Button,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport {\n Breadcrumbs,\n StatusBadge,\n EmptyState,\n LoadingSkeleton,\n ContactOwnerDialog,\n ReviewsSection,\n} from '../../components';\nimport type { BreadcrumbItem } from '../../components';\nimport {\n useProperty,\n useProperties,\n useShortlists,\n useSaveShortlist,\n useRemoveShortlist,\n useBookViewing,\n useSubmitOffer,\n useUpdateProperty,\n useDeleteProperty,\n useRentalUnits,\n useSubmitRentalApplication,\n useCreateInvestment,\n} from '../../hooks';\nimport { notify } from '../../lib/toast';\nimport { useHousingVistaAnalytics, useTrackPageView } from '../../hooks/useHousingVistaAnalytics';\nimport { cn, formatCurrency, formatCompactCurrency, formatNumber, formatDate } from '../../utils/helpers';\nimport type { Property, PropertyStatus } from '../../types';\n\nconst statusVariantMap: Record<string, 'success' | 'warning' | 'error' | 'info' | 'default' | 'muted'> = {\n for_sale: 'success',\n for_rent: 'info',\n sold: 'muted',\n rented: 'muted',\n under_contract: 'warning',\n off_market: 'error',\n};\n\nconst statusOptions: { value: PropertyStatus; label: string }[] = [\n { value: 'for_sale', label: 'For Sale' },\n { value: 'for_rent', label: 'For Rent' },\n { value: 'under_contract', label: 'Under Contract' },\n { value: 'sold', label: 'Sold' },\n { value: 'rented', label: 'Rented' },\n { value: 'off_market', label: 'Off Market' },\n];\n\ntype TabId = 'details' | 'amenities' | 'location';\nconst tabs: { id: TabId; label: string }[] = [\n { id: 'details', label: 'Details' },\n { id: 'amenities', label: 'Amenities' },\n { id: 'location', label: 'Location' },\n];\n\nconst inputClass =\n 'h-10 w-full rounded-md border border-border-subtle bg-bg-surface px-3 text-sm text-text-primary placeholder:text-text-secondary focus:outline-none focus:ring-2 focus:ring-[var(--color-focus-ring)]';\n\n// Map free-text amenity names to a recognisable icon (falls back to a tick).\nconst amenityIconRules: { match: RegExp; icon: LucideIcon }[] = [\n { match: /pool|swim/i, icon: Waves },\n { match: /gym|fitness/i, icon: Dumbbell },\n { match: /park/i, icon: ParkingCircle },\n { match: /garden|green|lawn|park/i, icon: TreePine },\n { match: /security|guard|cctv|gated/i, icon: Shield },\n { match: /wifi|internet|broadband/i, icon: Wifi },\n { match: /a\\/?c|air.?condition|central air|hvac/i, icon: Wind },\n { match: /fire|chimney|heat/i, icon: Flame },\n { match: /kitchen|modular|dining/i, icon: Utensils },\n { match: /car|garage/i, icon: Car },\n];\nconst amenityIcon = (name: string): LucideIcon => amenityIconRules.find((r) => r.match.test(name))?.icon ?? CheckCircle;\n\nexport const PropertyDetailPage = () => {\n const { id } = useParams<{ id: string }>();\n const navigate = useNavigate();\n const location = useLocation();\n const { emit, emitResource } = useHousingVistaAnalytics();\n useTrackPageView('housingvista.property.viewed', id);\n\n const { data: property, loading } = useProperty(id);\n const { data: allProperties } = useProperties({ pagination: { limit: 8, offset: 0 } });\n const { data: shortlists } = useShortlists();\n const { data: rentalUnits } = useRentalUnits({\n filter: id ? { propertyId: id } : undefined,\n pagination: { limit: 1, offset: 0 },\n });\n const { saveShortlist, loading: savingShortlist } = useSaveShortlist();\n const { removeShortlist, loading: removingShortlist } = useRemoveShortlist();\n const { bookViewing, loading: bookingViewing } = useBookViewing();\n const { submitOffer, loading: submittingOffer } = useSubmitOffer();\n const { updateProperty, loading: updatingProperty } = useUpdateProperty();\n const { deleteProperty, loading: deletingProperty } = useDeleteProperty();\n const { submitRentalApplication, loading: submittingRental } = useSubmitRentalApplication();\n const { createInvestment, loading: creatingInvestment } = useCreateInvestment();\n\n const similarProperties = useMemo(() => allProperties.filter((p) => p.id !== id).slice(0, 3), [allProperties, id]);\n const isShortlisted = useMemo(() => shortlists.some((s) => s.propertyId === id), [shortlists, id]);\n\n const [currentImageIndex, setCurrentImageIndex] = useState(0);\n const [activeTab, setActiveTab] = useState<TabId>('details');\n const [viewingOpen, setViewingOpen] = useState(false);\n const [offerOpen, setOfferOpen] = useState(false);\n const [editOpen, setEditOpen] = useState(false);\n const [deleteOpen, setDeleteOpen] = useState(false);\n const [rentalOpen, setRentalOpen] = useState(false);\n const [contactOpen, setContactOpen] = useState(false);\n\n // Rental application form state\n const [applicantName, setApplicantName] = useState('');\n const [applicantEmail, setApplicantEmail] = useState('');\n const [applicantPhone, setApplicantPhone] = useState('');\n const [monthlyIncome, setMonthlyIncome] = useState('');\n const [moveInDate, setMoveInDate] = useState('');\n\n // Investment-analysis calculator inputs (blank = use a price-derived default)\n const [rentInput, setRentInput] = useState('');\n const [costInput, setCostInput] = useState('');\n const [appreciationInput, setAppreciationInput] = useState('8');\n\n // Viewing form state\n const [viewingDate, setViewingDate] = useState('');\n const [viewingType, setViewingType] = useState<'in_person' | 'virtual'>('in_person');\n const [attendeeName, setAttendeeName] = useState('');\n const [attendeeEmail, setAttendeeEmail] = useState('');\n const [viewingNotes, setViewingNotes] = useState('');\n\n // Offer form state\n const [offerAmount, setOfferAmount] = useState('');\n const [offerNotes, setOfferNotes] = useState('');\n\n // Edit form state (seeded on open)\n const [editTitle, setEditTitle] = useState('');\n const [editDescription, setEditDescription] = useState('');\n const [editStatus, setEditStatus] = useState<PropertyStatus>('for_sale');\n const [editPrice, setEditPrice] = useState('');\n\n if (loading) {\n return (\n <div className=\"space-y-6 p-6\">\n <LoadingSkeleton className=\"h-80\" />\n <LoadingSkeleton variant=\"detail\" />\n </div>\n );\n }\n\n if (!property) {\n return (\n <div className=\"p-6\">\n <EmptyState\n illustration=\"empty-search\"\n icon={<Building className=\"h-12 w-12\" />}\n title=\"Property Not Found\"\n description=\"The property you're looking for doesn't exist or has been removed.\"\n action={\n <button\n onClick={() => navigate('../properties')}\n className=\"inline-flex items-center gap-2 rounded-md bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back to Properties\n </button>\n }\n />\n </div>\n );\n }\n\n const breadcrumbs: BreadcrumbItem[] = [{ label: 'Properties', href: '../' }, { label: property.title }];\n\n const formatPrice = (price: Property['price']) => {\n const amount = formatCurrency(price.amount, price.currency);\n if (price.type === 'rent' && price.period) return `${amount}/${price.period.replace('ly', '')}`;\n return amount;\n };\n\n const nextImage = () => setCurrentImageIndex((prev) => (prev === property.images.length - 1 ? 0 : prev + 1));\n const prevImage = () => setCurrentImageIndex((prev) => (prev === 0 ? property.images.length - 1 : prev - 1));\n\n const handleShare = () => {\n if (navigator.share) {\n navigator.share({ title: property.title, text: property.description, url: window.location.href });\n } else {\n navigator.clipboard.writeText(window.location.href);\n notify.info('Link copied', 'The property link is on your clipboard.');\n }\n };\n\n const toggleShortlist = async () => {\n try {\n if (isShortlisted) {\n await removeShortlist(property.id);\n notify.success('Removed from shortlist');\n } else {\n await saveShortlist(property.id);\n emitResource('housingvista.shortlist.property_added', property.id);\n notify.success('Saved to shortlist');\n }\n } catch (err) {\n notify.error('Could not update shortlist', (err as Error).message);\n }\n };\n\n const handleBookViewing = async (e: FormEvent) => {\n e.preventDefault();\n if (!viewingDate) return;\n try {\n await bookViewing({\n propertyId: property.id,\n scheduledAt: new Date(viewingDate).toISOString(),\n type: viewingType,\n attendeeName: attendeeName.trim() || undefined,\n attendeeEmail: attendeeEmail.trim() || undefined,\n notes: viewingNotes.trim() || undefined,\n });\n emitResource('housingvista.viewing.scheduled', property.id);\n notify.success('Viewing requested', 'The owner will confirm your slot shortly.');\n setViewingOpen(false);\n setViewingDate('');\n setAttendeeName('');\n setAttendeeEmail('');\n setViewingNotes('');\n } catch (err) {\n notify.error('Could not book viewing', (err as Error).message);\n }\n };\n\n const handleSubmitOffer = async (e: FormEvent) => {\n e.preventDefault();\n const amount = Number(offerAmount);\n if (!amount || amount <= 0) {\n notify.warning('Enter a valid offer amount');\n return;\n }\n try {\n await submitOffer({\n propertyId: property.id,\n amount,\n currency: property.price.currency,\n notes: offerNotes.trim() || undefined,\n });\n emitResource('housingvista.offer.created', property.id);\n notify.success('Offer submitted', `Your offer of ${formatCurrency(amount, property.price.currency)} was sent.`);\n setOfferOpen(false);\n setOfferAmount('');\n setOfferNotes('');\n } catch (err) {\n notify.error('Could not submit offer', (err as Error).message);\n }\n };\n\n const openEdit = () => {\n setEditTitle(property.title);\n setEditDescription(property.description);\n setEditStatus(property.status);\n setEditPrice(String(property.price.amount));\n setEditOpen(true);\n };\n\n const handleEdit = async (e: FormEvent) => {\n e.preventDefault();\n try {\n await updateProperty(property.id, {\n title: editTitle.trim(),\n description: editDescription.trim(),\n status: editStatus,\n price: Number(editPrice) || property.price.amount,\n });\n emitResource('housingvista.property.updated', property.id);\n notify.success('Property updated');\n setEditOpen(false);\n } catch (err) {\n notify.error('Could not update property', (err as Error).message);\n }\n };\n\n const handleDelete = async () => {\n try {\n await deleteProperty(property.id);\n emitResource('housingvista.property.deleted', property.id);\n notify.success('Property deleted');\n navigate('../properties');\n } catch (err) {\n notify.error('Could not delete property', (err as Error).message);\n }\n };\n\n // First available rental unit for this property (needed to submit an application).\n const rentalUnitId = rentalUnits[0]?.id;\n\n const handleSubmitRental = async (e: FormEvent) => {\n e.preventDefault();\n if (!rentalUnitId) {\n notify.warning('No rental unit is available for this property yet');\n return;\n }\n if (!applicantName.trim() || !applicantEmail.trim()) {\n notify.warning('Enter your name and email to apply');\n return;\n }\n try {\n await submitRentalApplication({\n rentalUnitId,\n applicantName: applicantName.trim(),\n applicantEmail: applicantEmail.trim(),\n applicantPhone: applicantPhone.trim() || undefined,\n monthlyIncome: monthlyIncome ? Number(monthlyIncome) : undefined,\n moveInDate: moveInDate ? new Date(moveInDate).toISOString() : undefined,\n });\n notify.success('Application submitted', 'The owner will review your rental application shortly.');\n setRentalOpen(false);\n setApplicantName('');\n setApplicantEmail('');\n setApplicantPhone('');\n setMonthlyIncome('');\n setMoveInDate('');\n } catch (err) {\n notify.error('Could not submit application', (err as Error).message);\n }\n };\n\n const handleTrackInvestment = async () => {\n try {\n await createInvestment({\n propertyId: property.id,\n title: `${property.title} — investment`,\n status: 'active',\n investmentType: 'full_ownership',\n riskLevel: 'medium',\n totalValue: property.price.amount,\n startDate: new Date().toISOString(),\n });\n notify.success('Tracking investment', `${property.title} was added to your portfolio.`);\n } catch (err) {\n notify.error('Could not track investment', (err as Error).message);\n }\n };\n\n // Investment analysis — modelled client-side from the listing price + user inputs.\n const price = property.price.amount;\n const monthlyRent = Number(rentInput) || Math.round(price * 0.005); // ~0.5%/mo default\n const monthlyHoldingCosts = Number(costInput) || Math.round(price * 0.0015); // ~0.15%/mo default\n const grossAnnualRent = monthlyRent * 12;\n const grossYield = price > 0 ? (grossAnnualRent / price) * 100 : 0;\n const annualHoldingCosts = monthlyHoldingCosts * 12;\n const netAnnualIncome = grossAnnualRent - annualHoldingCosts;\n const netYield = price > 0 ? (netAnnualIncome / price) * 100 : 0;\n // 5-year projected value growth at a user-adjustable appreciation rate + the\n // cumulative net rental income earned over the same window (total return).\n const appreciationRate = Math.max(0, Number(appreciationInput) || 0) / 100;\n const projection = Array.from({ length: 6 }, (_, year) => ({\n label: year === 0 ? 'Now' : `Yr ${year}`,\n value: Math.round(price * Math.pow(1 + appreciationRate, year)),\n }));\n const projectedValue5yr = projection[projection.length - 1].value;\n const totalReturn5yr = projectedValue5yr - price + netAnnualIncome * 5;\n const projectedRoi = price > 0 ? (totalReturn5yr / price) * 100 : 0;\n\n return (\n <div className=\"space-y-6 p-6\">\n <Breadcrumbs items={breadcrumbs} />\n\n {/* Header */}\n <div className=\"flex flex-wrap items-center gap-3\">\n <button\n onClick={() => navigate('../properties')}\n className=\"inline-flex items-center gap-2 rounded-md border border-border-subtle px-3 py-1.5 text-sm text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <ArrowLeft className=\"h-4 w-4\" />\n Back\n </button>\n <StatusBadge\n label={property.status.replace('_', ' ')}\n variant={statusVariantMap[property.status] ?? 'default'}\n dot\n />\n {property.verificationStatus === 'verified' && <StatusBadge label=\"Verified\" variant=\"success\" dot />}\n {property.price.negotiable && <StatusBadge label=\"Negotiable\" variant=\"info\" />}\n <div className=\"ml-auto flex items-center gap-2\">\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={openEdit}>\n <Pencil className=\"mr-1.5 h-4 w-4\" />\n Edit\n </Button>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setDeleteOpen(true)}>\n <Trash2 className=\"mr-1.5 h-4 w-4\" />\n Delete\n </Button>\n </div>\n </div>\n\n <PagePurpose className=\"max-w-3xl\">\n Everything you need to evaluate this property in one place — photos, specifications, amenities, and location.\n Use it to shortlist the property, schedule a viewing, or make an offer.\n </PagePurpose>\n\n <NextSteps\n storageKey=\"housingvista-property-detail\"\n steps={[\n {\n id: 'schedule',\n label: 'Schedule a viewing',\n description: 'Book a time to see the property in person or virtually.',\n onClick: () => setViewingOpen(true),\n },\n {\n id: 'offer',\n label: 'Make an offer',\n description: 'Submit a price and let the owner respond.',\n onClick: () => setOfferOpen(true),\n },\n {\n id: 'location',\n label: 'Explore the location',\n description: 'See the neighborhood, nearby landmarks, and map.',\n onClick: () => setActiveTab('location'),\n },\n ]}\n />\n\n {/* Image Gallery */}\n <div className=\"space-y-3\">\n <div className=\"relative overflow-hidden rounded-xl border border-border-subtle bg-bg-sunken\">\n {property.images.length > 0 ? (\n <img\n src={property.images[currentImageIndex]?.url}\n alt={property.images[currentImageIndex]?.title ?? property.title}\n className=\"h-80 w-full object-cover sm:h-[26rem]\"\n />\n ) : (\n <div className=\"flex h-80 w-full flex-col items-center justify-center gap-3 bg-gradient-to-br from-[var(--color-action-primary-bg)]/12 via-bg-sunken to-[var(--color-accent-blue)]/12 text-text-secondary/70 sm:h-[26rem]\">\n <Building className=\"h-12 w-12\" />\n <span className=\"text-sm font-medium tracking-wide\">No photos yet</span>\n </div>\n )}\n\n {property.images.length > 1 && (\n <>\n <button\n onClick={prevImage}\n aria-label=\"Previous photo\"\n className=\"absolute left-4 top-1/2 -translate-y-1/2 rounded-full bg-bg-overlay/70 p-2 text-text-inverse transition-colors hover:bg-bg-overlay\"\n >\n <ChevronLeft className=\"h-5 w-5\" />\n </button>\n <button\n onClick={nextImage}\n aria-label=\"Next photo\"\n className=\"absolute right-4 top-1/2 -translate-y-1/2 rounded-full bg-bg-overlay/70 p-2 text-text-inverse transition-colors hover:bg-bg-overlay\"\n >\n <ChevronRight className=\"h-5 w-5\" />\n </button>\n </>\n )}\n\n {/* Verified badge overlay */}\n {property.verificationStatus === 'verified' && (\n <div className=\"absolute left-4 top-4 inline-flex items-center gap-1.5 rounded-full bg-status-success-bg-subtle px-3 py-1 text-xs font-semibold text-status-success-text shadow-elevation-1 backdrop-blur-sm\">\n <BadgeCheck className=\"h-4 w-4\" />\n Verified listing\n </div>\n )}\n\n <div className=\"absolute right-4 top-4 flex gap-2\">\n <button\n onClick={toggleShortlist}\n disabled={savingShortlist || removingShortlist}\n aria-label={isShortlisted ? 'Remove from shortlist' : 'Save to shortlist'}\n className=\"rounded-full bg-bg-surface/85 p-2 shadow-elevation-1 backdrop-blur-sm transition-colors hover:bg-bg-surface disabled:opacity-60\"\n >\n <Heart\n className={cn(\n 'h-5 w-5',\n isShortlisted ? 'fill-status-error-text text-status-error-text' : 'text-text-secondary'\n )}\n />\n </button>\n <button\n onClick={handleShare}\n aria-label=\"Share this listing\"\n className=\"rounded-full bg-bg-surface/85 p-2 shadow-elevation-1 backdrop-blur-sm transition-colors hover:bg-bg-surface\"\n >\n <Share2 className=\"h-5 w-5 text-text-secondary\" />\n </button>\n </div>\n\n {property.images.length > 0 && (\n <div className=\"absolute bottom-4 right-4\">\n <span className=\"rounded-md bg-bg-overlay/70 px-2 py-1 text-xs font-medium text-text-inverse\">\n {currentImageIndex + 1} / {property.images.length}\n </span>\n </div>\n )}\n </div>\n\n {/* Thumbnail strip */}\n {property.images.length > 1 && (\n <div className=\"flex gap-3 overflow-x-auto pb-1\">\n {property.images.map((img, index) => (\n <button\n key={img.id}\n onClick={() => setCurrentImageIndex(index)}\n aria-label={`View photo ${index + 1}`}\n aria-current={index === currentImageIndex}\n className={cn(\n 'h-16 w-24 shrink-0 overflow-hidden rounded-lg border-2 transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]',\n index === currentImageIndex\n ? 'border-action-primary-border'\n : 'border-transparent opacity-70 hover:opacity-100'\n )}\n >\n <img src={img.url} alt={img.title ?? `Photo ${index + 1}`} className=\"h-full w-full object-cover\" />\n </button>\n ))}\n </div>\n )}\n </div>\n\n {/* Main Content Grid */}\n <div className=\"grid grid-cols-1 gap-6 lg:grid-cols-3\">\n {/* Left: Main content */}\n <div className=\"space-y-6 lg:col-span-2\">\n <EmphasisPanel>\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div>\n <h1 className=\"text-2xl font-bold text-text-primary\">{property.title}</h1>\n <div className=\"mt-2 flex items-center text-text-secondary\">\n <MapPin className=\"mr-1.5 h-4 w-4 shrink-0\" />\n <span className=\"text-sm\">\n {[property.location.address, property.location.neighborhood, property.location.city]\n .filter(Boolean)\n .join(', ')}\n </span>\n </div>\n </div>\n <div className=\"text-right\">\n <div className=\"text-2xl font-bold text-text-primary\">{formatPrice(property.price)}</div>\n {property.price.pricePerSqft && (\n <div className=\"text-sm text-text-secondary\">{formatCurrency(property.price.pricePerSqft)}/sqft</div>\n )}\n </div>\n </div>\n\n {/* Key Specs — spec cards */}\n <div className=\"mt-6 grid grid-cols-2 gap-3 border-t border-border-subtle pt-6 sm:grid-cols-4\">\n {[\n property.specifications.bedrooms != null && {\n icon: Bed,\n value: String(property.specifications.bedrooms),\n label: property.specifications.bedrooms === 1 ? 'Bedroom' : 'Bedrooms',\n },\n property.specifications.bathrooms != null && {\n icon: Bath,\n value: String(property.specifications.bathrooms),\n label: property.specifications.bathrooms === 1 ? 'Bathroom' : 'Bathrooms',\n },\n {\n icon: Square,\n value: formatNumber(property.specifications.totalArea),\n label: 'sq ft',\n },\n property.specifications.parking != null && property.specifications.parking > 0\n ? {\n icon: Car,\n value: String(property.specifications.parking),\n label: 'Parking',\n }\n : property.specifications.facing\n ? { icon: Compass, value: property.specifications.facing, label: 'Facing' }\n : false,\n ]\n .filter((spec): spec is { icon: LucideIcon; value: string; label: string } => Boolean(spec))\n .map((spec) => {\n const Icon = spec.icon;\n return (\n <div\n key={spec.label}\n className=\"flex flex-col items-center gap-1 rounded-lg border border-border-subtle bg-bg-sunken/40 p-3 text-center\"\n >\n <Icon className=\"h-5 w-5 text-text-secondary\" />\n <span className=\"text-base font-semibold text-text-primary\">{spec.value}</span>\n <span className=\"text-xs text-text-secondary\">{spec.label}</span>\n </div>\n );\n })}\n </div>\n\n {property.description && (\n <div className=\"mt-6 border-t border-border-subtle pt-6\">\n <h3 className=\"mb-3 text-base font-semibold text-text-primary\">Description</h3>\n <p className=\"text-sm leading-relaxed text-text-secondary\">{property.description}</p>\n </div>\n )}\n </EmphasisPanel>\n\n {/* Tabbed Content */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface\">\n <div className=\"border-b border-border-subtle\">\n <nav className=\"flex space-x-6 overflow-x-auto px-6\">\n {tabs.map((tab) => (\n <button\n key={tab.id}\n onClick={() => setActiveTab(tab.id)}\n className={cn(\n 'whitespace-nowrap border-b-2 py-3 text-sm font-medium transition-colors',\n activeTab === tab.id\n ? 'border-action-primary-border text-text-primary'\n : 'border-transparent text-text-secondary hover:text-text-primary'\n )}\n >\n {tab.label}\n </button>\n ))}\n </nav>\n </div>\n\n <div className=\"p-6\">\n {activeTab === 'details' && (\n <div className=\"grid grid-cols-1 gap-6 sm:grid-cols-2\">\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">Property Information</h4>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Property Type</dt>\n <dd className=\"font-medium capitalize text-text-primary\">{property.type}</dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Category</dt>\n <dd className=\"font-medium capitalize text-text-primary\">{property.category}</dd>\n </div>\n {property.specifications.ageOfProperty != null && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Age of Property</dt>\n <dd className=\"font-medium text-text-primary\">\n {property.specifications.ageOfProperty} years\n </dd>\n </div>\n )}\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Furnishing</dt>\n <dd className=\"font-medium capitalize text-text-primary\">\n {property.specifications.furnishingStatus?.replace('_', ' ')}\n </dd>\n </div>\n {property.specifications.facing && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Facing</dt>\n <dd className=\"font-medium text-text-primary\">{property.specifications.facing}</dd>\n </div>\n )}\n {property.specifications.floors != null && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Floor</dt>\n <dd className=\"font-medium text-text-primary\">\n {property.specifications.floors} of {property.specifications.totalFloors}\n </dd>\n </div>\n )}\n </dl>\n </div>\n <div>\n <h4 className=\"mb-3 text-sm font-semibold text-text-primary\">Area Details</h4>\n <dl className=\"space-y-2 text-sm\">\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Total Area</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatNumber(property.specifications.totalArea)} sqft\n </dd>\n </div>\n {property.specifications.carpetArea && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Carpet Area</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatNumber(property.specifications.carpetArea)} sqft\n </dd>\n </div>\n )}\n {property.specifications.builtUpArea && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Built-up Area</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatNumber(property.specifications.builtUpArea)} sqft\n </dd>\n </div>\n )}\n {property.price.pricePerSqft && (\n <div className=\"flex justify-between\">\n <dt className=\"text-text-secondary\">Price per sqft</dt>\n <dd className=\"font-medium text-text-primary\">\n {formatCurrency(property.price.pricePerSqft)}\n </dd>\n </div>\n )}\n </dl>\n </div>\n </div>\n )}\n\n {activeTab === 'amenities' && (\n <div>\n {property.amenities.length > 0 ? (\n <div className=\"grid grid-cols-2 gap-3 sm:grid-cols-3 lg:grid-cols-4\">\n {property.amenities.map((amenity) => {\n const Icon = amenityIcon(amenity.name);\n return (\n <div\n key={amenity.id}\n className=\"flex flex-col items-center gap-2 rounded-lg border border-border-subtle bg-bg-sunken/40 p-4 text-center\"\n >\n <span className=\"flex h-10 w-10 items-center justify-center rounded-full bg-status-success-bg-subtle text-status-success-text\">\n <Icon className=\"h-5 w-5\" />\n </span>\n <span className=\"text-sm font-medium text-text-primary\">{amenity.name}</span>\n </div>\n );\n })}\n </div>\n ) : (\n <EmptyState\n illustration=\"empty-generic\"\n title=\"No amenities listed\"\n description=\"This property has no amenities recorded yet.\"\n className=\"border-0 bg-transparent p-6\"\n />\n )}\n </div>\n )}\n\n {activeTab === 'location' && (\n <div className=\"space-y-4\">\n {/* Map card — styled placeholder pinned to the listing's locale */}\n <div className=\"relative h-56 overflow-hidden rounded-xl border border-border-subtle bg-bg-sunken\">\n <div\n className=\"absolute inset-0 opacity-60\"\n style={{\n backgroundImage:\n 'linear-gradient(var(--color-border-seam, rgba(120,120,120,.18)) 1px, transparent 1px), linear-gradient(90deg, var(--color-border-seam, rgba(120,120,120,.18)) 1px, transparent 1px)',\n backgroundSize: '32px 32px',\n }}\n />\n <div className=\"absolute left-1/2 top-1/2 flex -translate-x-1/2 -translate-y-1/2 flex-col items-center gap-1 text-center\">\n <span className=\"flex h-11 w-11 items-center justify-center rounded-full bg-action-primary-bg text-action-primary-text shadow-pop\">\n <MapPin className=\"h-5 w-5\" />\n </span>\n <span className=\"mt-1 rounded-md bg-bg-surface/90 px-2 py-0.5 text-sm font-semibold text-text-primary shadow-elevation-1 backdrop-blur-sm\">\n {property.location.neighborhood || property.location.city}\n </span>\n <span className=\"text-xs text-text-secondary\">\n {[property.location.city, property.location.state].filter(Boolean).join(', ')}\n </span>\n </div>\n {property.location.coordinates?.latitude != null &&\n property.location.coordinates?.longitude != null && (\n <a\n href={`https://www.google.com/maps/search/?api=1&query=${property.location.coordinates.latitude},${property.location.coordinates.longitude}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className=\"absolute bottom-3 right-3 inline-flex items-center gap-1.5 rounded-md bg-bg-surface/90 px-2.5 py-1.5 text-xs font-medium text-text-primary shadow-elevation-1 backdrop-blur-sm transition-colors hover:bg-bg-surface\"\n >\n <Navigation className=\"h-3.5 w-3.5\" />\n Open in Maps\n </a>\n )}\n </div>\n {property.location.address && (\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">Full Address</div>\n <div className=\"text-sm font-medium text-text-primary\">{property.location.address}</div>\n </div>\n )}\n <div className=\"grid grid-cols-1 gap-4 text-sm sm:grid-cols-3\">\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">Neighborhood</div>\n <div className=\"font-medium text-text-primary\">{property.location.neighborhood || '—'}</div>\n </div>\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">City, State</div>\n <div className=\"font-medium text-text-primary\">\n {property.location.city}, {property.location.state}\n </div>\n </div>\n <div>\n <div className=\"mb-1 text-xs text-text-secondary\">PIN / ZIP</div>\n <div className=\"font-medium text-text-primary\">{property.location.pincode || '—'}</div>\n </div>\n </div>\n\n {property.location.landmarks.length > 0 && (\n <div className=\"border-t border-border-subtle pt-4\">\n <h4 className=\"mb-2 text-xs font-medium text-text-secondary\">Nearby Landmarks</h4>\n <div className=\"flex flex-wrap gap-2\">\n {property.location.landmarks.map((landmark) => (\n <span\n key={landmark}\n className=\"rounded-full bg-bg-sunken px-3 py-1 text-xs text-text-primary\"\n >\n {landmark}\n </span>\n ))}\n </div>\n </div>\n )}\n </div>\n )}\n </div>\n </div>\n </div>\n\n {/* Right Sidebar */}\n <div className=\"space-y-6\">\n {/* Price + Actions — lead panel (mirrors the listing hero) */}\n <div\n id=\"property-actions\"\n className=\"scroll-mt-6 rounded-lg border border-border-subtle bg-bg-surface p-5 shadow-elevation-1 lg:sticky lg:top-6\"\n >\n <div className=\"flex flex-wrap items-baseline gap-x-2 gap-y-1\">\n <span className=\"text-3xl font-bold text-text-primary\">{formatPrice(property.price)}</span>\n {property.price.negotiable && <span className=\"text-sm text-text-secondary\">· Negotiable</span>}\n </div>\n {property.price.pricePerSqft && (\n <p className=\"mt-1 text-sm text-text-secondary\">\n {formatCurrency(property.price.pricePerSqft, property.price.currency)}/sqft\n </p>\n )}\n\n <div className=\"mt-4 space-y-2\">\n <Button type=\"button\" className=\"w-full justify-center\" onClick={() => setOfferOpen(true)}>\n <DollarSign className=\"mr-2 h-4 w-4\" />\n Make Offer\n </Button>\n {property.status === 'for_rent' && (\n <>\n <Button\n type=\"button\"\n className=\"w-full justify-center\"\n onClick={() => setRentalOpen(true)}\n disabled={!rentalUnitId}\n >\n <KeyRound className=\"mr-2 h-4 w-4\" />\n Apply to Rent\n </Button>\n {!rentalUnitId && (\n <p className=\"px-1 text-xs text-text-secondary\">\n No rental unit is listed for this property yet — applications open once a unit is added.\n </p>\n )}\n </>\n )}\n <div className=\"grid grid-cols-2 gap-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"w-full justify-center\"\n onClick={() => setViewingOpen(true)}\n >\n <Calendar className=\"mr-2 h-4 w-4\" />\n Viewing\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"w-full justify-center\"\n onClick={() => setContactOpen(true)}\n >\n <MessageSquare className=\"mr-2 h-4 w-4\" />\n Contact\n </Button>\n </div>\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"w-full justify-center\"\n onClick={toggleShortlist}\n disabled={savingShortlist || removingShortlist}\n >\n <Heart\n className={cn('mr-2 h-4 w-4', isShortlisted && 'fill-status-error-text text-status-error-text')}\n />\n {isShortlisted ? 'Saved to Shortlist' : 'Save to Shortlist'}\n </Button>\n </div>\n\n {property.verificationStatus === 'verified' && (\n <div className=\"mt-4 flex items-center gap-2 border-t border-border-subtle pt-4 text-sm font-medium text-status-success-text\">\n <BadgeCheck className=\"h-4 w-4\" />\n Verified listing\n </div>\n )}\n </div>\n\n {/* Investment analysis — modelled client-side from the listing price */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <div className=\"mb-4 flex items-center gap-2\">\n <Calculator className=\"h-5 w-5 text-text-secondary\" />\n <h3 className=\"text-base font-semibold text-text-primary\">Investment Analysis</h3>\n </div>\n\n {/* Deal parameters */}\n <div className=\"space-y-3\">\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-text-secondary\">\n Expected monthly rent ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={rentInput}\n onChange={(e) => setRentInput(e.target.value)}\n placeholder={String(monthlyRent)}\n className={inputClass}\n />\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-text-secondary\">\n Monthly costs ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={costInput}\n onChange={(e) => setCostInput(e.target.value)}\n placeholder={String(monthlyHoldingCosts)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-xs font-medium text-text-secondary\">Appreciation (%/yr)</label>\n <input\n type=\"number\"\n min={0}\n step={0.5}\n value={appreciationInput}\n onChange={(e) => setAppreciationInput(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <p className=\"text-[11px] text-text-secondary\">\n Costs cover maintenance, tax, insurance, and management.\n </p>\n </div>\n\n {/* Financial projections — yield tiles */}\n <div className=\"mt-4 grid grid-cols-3 gap-2 border-t border-border-subtle pt-4\">\n <div className=\"rounded-lg border border-status-success-border bg-status-success-bg-subtle p-2.5 text-center\">\n <div className=\"text-[11px] font-medium text-status-success-text\">Gross Yield</div>\n <div className=\"mt-0.5 text-lg font-bold text-status-success-text\">{grossYield.toFixed(1)}%</div>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-2.5 text-center\">\n <div className=\"text-[11px] font-medium text-text-secondary\">Net Yield</div>\n <div className=\"mt-0.5 text-lg font-bold text-text-primary\">{netYield.toFixed(1)}%</div>\n </div>\n <div className=\"rounded-lg border border-border-subtle bg-bg-sunken/40 p-2.5 text-center\">\n <div className=\"text-[11px] font-medium text-text-secondary\">5-yr ROI</div>\n <div className=\"mt-0.5 text-lg font-bold text-text-primary\">{projectedRoi.toFixed(0)}%</div>\n </div>\n </div>\n\n {/* Projected value growth */}\n <div className=\"mt-4\">\n <div className=\"mb-1 flex items-center justify-between\">\n <span className=\"text-xs font-medium text-text-secondary\">Projected Value Growth</span>\n <span className=\"text-xs font-semibold text-text-primary\">\n {formatCompactCurrency(projectedValue5yr, property.price.currency)}\n </span>\n </div>\n <div className=\"h-32\">\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart data={projection} margin={{ top: 4, right: 4, bottom: 0, left: 0 }}>\n <defs>\n <linearGradient id=\"hvValueGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor=\"var(--color-chart-2)\" stopOpacity={0.35} />\n <stop offset=\"95%\" stopColor=\"var(--color-chart-2)\" stopOpacity={0} />\n </linearGradient>\n </defs>\n <XAxis dataKey=\"label\" tick={{ fontSize: 10 }} axisLine={false} tickLine={false} />\n <YAxis hide domain={['dataMin', 'dataMax']} />\n <Tooltip\n formatter={(value: number) => [formatCompactCurrency(value, property.price.currency), 'Value']}\n labelClassName=\"text-text-primary\"\n />\n <Area\n type=\"monotone\"\n dataKey=\"value\"\n stroke=\"var(--color-chart-2)\"\n fill=\"url(#hvValueGrad)\"\n strokeWidth={2}\n />\n </AreaChart>\n </ResponsiveContainer>\n </div>\n <p className=\"mt-1 text-[11px] text-text-secondary\">\n Projection based on your inputs and market appreciation. Consult a financial advisor before investing.\n </p>\n </div>\n\n <Button\n type=\"button\"\n variant=\"outline\"\n className=\"mt-4 w-full justify-center\"\n onClick={handleTrackInvestment}\n disabled={creatingInvestment}\n >\n <TrendingUp className=\"mr-2 h-4 w-4\" />\n {creatingInvestment ? 'Adding…' : 'Track as Investment'}\n </Button>\n </div>\n\n {/* Property Stats (real, derived) */}\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">At a Glance</h3>\n <div className=\"space-y-3 text-sm\">\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Status</span>\n <StatusBadge\n label={property.status.replace('_', ' ')}\n variant={statusVariantMap[property.status] ?? 'default'}\n />\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Verification</span>\n <span className=\"font-medium capitalize text-text-primary\">{property.verificationStatus}</span>\n </div>\n <div className=\"flex items-center justify-between\">\n <span className=\"text-text-secondary\">Listed</span>\n <span className=\"font-medium text-text-primary\">{formatDate(String(property.createdAt))}</span>\n </div>\n </div>\n </div>\n\n {/* Similar Properties */}\n {similarProperties.length > 0 && (\n <div className=\"rounded-lg border border-border-subtle bg-bg-surface p-5\">\n <h3 className=\"mb-4 text-base font-semibold text-text-primary\">Similar Properties</h3>\n <div className=\"space-y-3\">\n {similarProperties.map((sp) => (\n <button\n key={sp.id}\n onClick={() => navigate(`../properties/${sp.id}`)}\n className=\"flex w-full items-start gap-3 rounded-lg border border-border-subtle p-3 text-left transition-colors hover:bg-bg-sunken/50\"\n >\n {sp.images[0] && (\n <img src={sp.images[0].url} alt={sp.title} className=\"h-14 w-14 rounded object-cover\" />\n )}\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium text-text-primary\">{sp.title}</div>\n <div className=\"text-sm font-semibold text-text-primary\">{formatCurrency(sp.price.amount)}</div>\n <div className=\"truncate text-xs text-text-secondary\">\n {[sp.location.neighborhood, sp.location.city].filter(Boolean).join(', ')}\n </div>\n </div>\n </button>\n ))}\n </div>\n </div>\n )}\n </div>\n </div>\n\n {/* Q&A / reviews — real EntityComments-backed thread */}\n <ReviewsSection entityId={property.id} entityType=\"housingvista-property\" />\n\n {/* Contact-owner conversation dialog — controlled at page root (same\n reliable pattern as the Make Offer dialog) */}\n <ContactOwnerDialog\n open={contactOpen}\n onOpenChange={setContactOpen}\n entityId={property.id}\n entityType=\"housingvista-property\"\n title={property.title}\n pagePath={location.pathname}\n heading=\"Contact owner\"\n description={`Ask a question or start a conversation about ${property.title}.`}\n />\n\n {/* Apply to Rent dialog */}\n <ResponsiveDialog open={rentalOpen} onOpenChange={setRentalOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleSubmitRental}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Apply to rent</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Submit a rental application for {property.title}. The owner will review and respond.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Full name *</label>\n <input\n type=\"text\"\n required\n value={applicantName}\n onChange={(e) => setApplicantName(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Email *</label>\n <input\n type=\"email\"\n required\n value={applicantEmail}\n onChange={(e) => setApplicantEmail(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Phone</label>\n <input\n type=\"tel\"\n value={applicantPhone}\n onChange={(e) => setApplicantPhone(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Monthly income ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={monthlyIncome}\n onChange={(e) => setMonthlyIncome(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Preferred move-in date</label>\n <input\n type=\"date\"\n value={moveInDate}\n onChange={(e) => setMoveInDate(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setRentalOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={submittingRental || !rentalUnitId}>\n {submittingRental ? 'Submitting…' : 'Submit application'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Schedule Viewing dialog */}\n <ResponsiveDialog open={viewingOpen} onOpenChange={setViewingOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleBookViewing}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Schedule a viewing</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Pick a date and time to see {property.title}.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Date & time *</label>\n <input\n type=\"datetime-local\"\n required\n value={viewingDate}\n onChange={(e) => setViewingDate(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Type</label>\n <select\n value={viewingType}\n onChange={(e) => setViewingType(e.target.value as 'in_person' | 'virtual')}\n className={inputClass}\n >\n <option value=\"in_person\">In person</option>\n <option value=\"virtual\">Virtual</option>\n </select>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <input\n type=\"text\"\n placeholder=\"Your name\"\n value={attendeeName}\n onChange={(e) => setAttendeeName(e.target.value)}\n className={inputClass}\n />\n <input\n type=\"email\"\n placeholder=\"Your email\"\n value={attendeeEmail}\n onChange={(e) => setAttendeeEmail(e.target.value)}\n className={inputClass}\n />\n </div>\n <textarea\n placeholder=\"Notes (optional)\"\n rows={2}\n value={viewingNotes}\n onChange={(e) => setViewingNotes(e.target.value)}\n className=\"w-full 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>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setViewingOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={bookingViewing || !viewingDate}>\n {bookingViewing ? 'Booking…' : 'Request viewing'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Make Offer dialog */}\n <ResponsiveDialog open={offerOpen} onOpenChange={setOfferOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleSubmitOffer}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Make an offer</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Listing price is {formatPrice(property.price)}.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Your offer ({property.price.currency}) *\n </label>\n <input\n type=\"number\"\n required\n min={1}\n value={offerAmount}\n onChange={(e) => setOfferAmount(e.target.value)}\n placeholder=\"Enter amount\"\n className={inputClass}\n />\n </div>\n <textarea\n placeholder=\"Message to the owner (optional)\"\n rows={3}\n value={offerNotes}\n onChange={(e) => setOfferNotes(e.target.value)}\n className=\"w-full 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>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setOfferOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={submittingOffer}>\n {submittingOffer ? 'Submitting…' : 'Submit offer'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Edit dialog */}\n <ResponsiveDialog open={editOpen} onOpenChange={setEditOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <form onSubmit={handleEdit}>\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Edit property</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>Update the core listing details.</ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <div className=\"space-y-3 py-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Title *</label>\n <input\n type=\"text\"\n required\n value={editTitle}\n onChange={(e) => setEditTitle(e.target.value)}\n className={inputClass}\n />\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Description</label>\n <textarea\n rows={3}\n value={editDescription}\n onChange={(e) => setEditDescription(e.target.value)}\n className=\"w-full 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>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">Status</label>\n <select\n value={editStatus}\n onChange={(e) => setEditStatus(e.target.value as PropertyStatus)}\n className={inputClass}\n >\n {statusOptions.map((s) => (\n <option key={s.value} value={s.value}>\n {s.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label className=\"mb-1.5 block text-sm font-medium text-text-primary\">\n Price ({property.price.currency})\n </label>\n <input\n type=\"number\"\n min={0}\n value={editPrice}\n onChange={(e) => setEditPrice(e.target.value)}\n className={inputClass}\n />\n </div>\n </div>\n </div>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setEditOpen(false)}>\n Cancel\n </Button>\n <Button type=\"submit\" disabled={updatingProperty}>\n {updatingProperty ? 'Saving…' : 'Save changes'}\n </Button>\n </ResponsiveDialogFooter>\n </form>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n\n {/* Delete confirm dialog */}\n <ResponsiveDialog open={deleteOpen} onOpenChange={setDeleteOpen}>\n <ResponsiveDialogContent className=\"sm:max-w-md\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Delete this property?</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n {property.title} will be permanently removed. This cannot be undone.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n <ResponsiveDialogFooter>\n <Button type=\"button\" variant=\"outline\" onClick={() => setDeleteOpen(false)}>\n Cancel\n </Button>\n <Button type=\"button\" variant=\"destructive\" onClick={handleDelete} disabled={deletingProperty}>\n {deletingProperty ? 'Deleting…' : 'Delete property'}\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RentalManagementPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/rental/RentalManagementPage.tsx"],"names":[],"mappings":"AA8IA,wBAAgB,oBAAoB,gCAw9BnC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfilePage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/settings/ProfilePage.tsx"],"names":[],"mappings":"AAcA,wBAAgB,WAAW,gCAqG1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/settings/SettingsPage.tsx"],"names":[],"mappings":"AA6CA,wBAAgB,YAAY,gCA8E3B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HousingVista Shortlist Page
|
|
3
|
+
* The properties the user has saved (housingvistaShortlists), with one-tap
|
|
4
|
+
* un-save and a jump into each property's detail. No mock data.
|
|
5
|
+
* @module housingvista
|
|
6
|
+
*/
|
|
7
|
+
export declare const ShortlistPage: () => import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=ShortlistPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ShortlistPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/shortlist/ShortlistPage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,eAAO,MAAM,aAAa,mCAgGzB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HousingVista Transaction Detail Page
|
|
3
|
+
* Full transaction detail with milestones, documents, parties, financial breakdown.
|
|
4
|
+
* Migrated from legacy housingvista-frontend transaction-detail.tsx
|
|
5
|
+
* @module housingvista
|
|
6
|
+
*/
|
|
7
|
+
export declare const TransactionDetailPage: () => import("react").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=TransactionDetailPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TransactionDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/transactions/TransactionDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AA2EH,eAAO,MAAM,qBAAqB,mCAofjC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TransactionsPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/transactions/TransactionsPage.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AA0DH,eAAO,MAAM,gBAAgB,mCAgjB5B,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for the Transactions surfaces. The transaction `milestones` and
|
|
3
|
+
* `escrow` columns arrive as opaque JSON from the subgraph, so everything here
|
|
4
|
+
* guards runtime shape and never throws on missing / malformed data. Used by
|
|
5
|
+
* both the Transactions list (inline deal preview) and the Transaction detail
|
|
6
|
+
* page (deal stage stepper) so the two views stay visually consistent.
|
|
7
|
+
* @module housingvista
|
|
8
|
+
*/
|
|
9
|
+
export interface ParsedMilestone {
|
|
10
|
+
id: string;
|
|
11
|
+
title: string;
|
|
12
|
+
status: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ParsedEscrow {
|
|
15
|
+
amount: number | null;
|
|
16
|
+
status: string | null;
|
|
17
|
+
}
|
|
18
|
+
export declare function parseMilestones(value: unknown): ParsedMilestone[];
|
|
19
|
+
export declare function parseEscrow(value: unknown): ParsedEscrow | null;
|
|
20
|
+
export declare function milestoneProgress(milestones: ParsedMilestone[]): number;
|
|
21
|
+
/** A thin, calm progress bar (semantic tokens only). */
|
|
22
|
+
export declare function ProgressBar({ percent, className }: {
|
|
23
|
+
percent: number;
|
|
24
|
+
className?: string;
|
|
25
|
+
}): import("react").JSX.Element;
|
|
26
|
+
/**
|
|
27
|
+
* Horizontal deal-stage stepper: Offer accepted → Escrow → Documents →
|
|
28
|
+
* Registration → Closing (whatever the deal's real milestones are). Completed
|
|
29
|
+
* stages get a check, the in-progress stage a highlighted ring, and pending
|
|
30
|
+
* stages a quiet outline. Scrolls horizontally on narrow screens.
|
|
31
|
+
*/
|
|
32
|
+
export declare function MilestoneStepper({ milestones }: {
|
|
33
|
+
milestones: ParsedMilestone[];
|
|
34
|
+
}): import("react").JSX.Element;
|
|
35
|
+
//# sourceMappingURL=milestones.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"milestones.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/transactions/milestones.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAKH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAKD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,GAAG,eAAe,EAAE,CAUjE;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI,CAO/D;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,eAAe,EAAE,GAAG,MAAM,CAIvE;AAED,wDAAwD;AACxD,wBAAgB,WAAW,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAO1F;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,UAAU,EAAE,EAAE;IAAE,UAAU,EAAE,eAAe,EAAE,CAAA;CAAE,+BAiDjF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HousingVista Verification Detail Page
|
|
3
|
+
* Single verification item backed by `housingvistaVerificationItem(id)` — its
|
|
4
|
+
* status, type, priority, reviewer, notes, and a submitted → review → decision
|
|
5
|
+
* timeline. Approve / reject are surfaced for still-open items and call the real
|
|
6
|
+
* `approve/rejectHousingvistaVerificationItem` mutations (gateway enforces RBAC).
|
|
7
|
+
* @module housingvista
|
|
8
|
+
*/
|
|
9
|
+
export declare function VerificationDetailPage(): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=VerificationDetailPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerificationDetailPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/verification/VerificationDetailPage.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAqDH,wBAAgB,sBAAsB,gCA8SrC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VerificationPage.d.ts","sourceRoot":"","sources":["../../../../src/housingvista/pages/verification/VerificationPage.tsx"],"names":[],"mappings":"AAoIA,wBAAgB,gBAAgB,gCAgU/B"}
|